Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From 7ce3553bf5f4bccd To e6215cb721c88b57
2017-09-12
| ||
12:24 | Small fix to allow tools/version to be run by Makefile when building out of tree. Also cleaned up the code a bit. check-in: c94cb7be8f user: tangent tags: trunk | |
2017-09-08
| ||
05:02 | Added cover scan of the green-yellow 1968 edition of DEC's "Small Computer Handbook" for the PDP-8/I. check-in: e6215cb721 user: tangent tags: trunk | |
2017-09-05
| ||
06:30 | Added a sensible-default cd $prefix/share/media to etc/pidp8i-init.in just before the "start simulator under screen" call, so that SIMH's CWD will be somewhere useful, not taking the default used by the OS's init system, which may well be something entirely unhelpful like /. check-in: 46366581f0 user: tangent tags: trunk | |
2016-11-21
| ||
09:33 | Upstream version 20151215, containing everything from the tarball except for backups and *.o. Also, all CRLF text files converted to LF. check-in: ec36ee3dab user: tangent tags: trunk, v20151215 | |
09:11 | initial empty check-in check-in: 7ce3553bf5 user: tangent tags: trunk | |
> > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 | doc/*.jpg doc/*.png examples/*.pt labels/*.pdf media/*/*.bin media/*/*.dsk media/*/*.pt media/*/*.rk05 media/*/*.tu56 pics/*/*.jpg pics/*/*.png schematics/*.pdf |
> > > > > | 1 2 3 4 5 | src/scp.* src/sim_*.[ch] src/sim_*.in src/PDP8/pdp8_*.[ch] src/PDP8/pidp8i.c.in |
> | 1 | doc/simh/*.pdf |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | # Creators and Major Contributors to the PiDP-8/I Project * **Oscar Vermeulen <oscar.vermeulen@hotmail.com>**: - Creator of the project (both hardware and software) - Author of the initial modifications to the SIMH PDP-8 simulator necessary to make it use the PiDP-8/I front panel hardware - Curator of the default set of binary demo media - Author of the simulator setup scripts - Initiator of much else in the project - Author of the bulk of the documentation - Host and major contributor to the PiDP-8/I support forum on Google Groups - Hardware kit assembler and distributor * **Robert M Supnik** Primary author of the SIMH PDP-8 simulator upon which this project is based. * **Mike Barnes** Ported Oscar Vermeulen's SIMH 3.9 based PiDP-8/I simulator to the new SIMH 4.0 code base. (September 2015.) * **Dylan McNamee** Ported the software to Buildroot for the official 2015.12.15 binary OS images, and helped to merge the James L-W "alt-serial" mode in. * **Mark G. Thomas** Creator of the installation scripts for the 2015.12.15 release, which were folded into the `make install` handler within `Makefile.in`. Also wrote the version of the SysV init script that came with that release as `rc.pidp8`, shipped here as `pidp8i-init`. * **Ian Schofield <isysxp@gmail.com>** Modified the LED lamp driving code in the simulator to better simulate the incandescent lamps in the original PDP-8/I hardware. (The bulk of his original code has since been rewritten, but the core idea remains, and it is doubtful whether the current method would exist without his instigation.) * **Henk Gooijen <henk.gooijen@boschrexroth.nl>** Pushed the PDP-8 simulator's internal EAE step counter value down into the PiDP-8/I's LED manipulation code, without which the step counter LEDs remain dark even when using the EAE. * **Paul R. Bernard <prb@downspout.ca>** wrote `src/test.c` and the core of what now appears as `doc/pidp8i-test.md`. (The program builds and installs as `pidp8i-test`.) He also provided a one-line fix that completes the work of Henk Gooijen's step counter patch. * **Rick Murphy <k1mu.nospam@gmail.com>** optimized the `pep001.pal` example so that it fits into a single page of PDP-8 core, and provided several useful files in his OS/8 disk images that have managed to land in this software distribution's OS/8 disk image. * **Tony Hill <hill.anthony@gmail.com>** Merged all the upstream SIMH changes produced between late September 2015 and late December 2016 into the PiDP-8/I simulator. * **Bill Cattey <bill.cattey@gmail.com>** aka poetnerd. Currently working on system pack images. Making myself useful where I can. * **Warren Young <tangentsoft@gmail.com>** Did everything listed in `ChangeLog.md` that is not attributed to anyone else. |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | # Licenses The PiDP-8/I software distribution is an agglomeration of software from multiple sources. Several different licenses apply to its parts. This file guides you to those individual licenses. ## SIMH License Most of the files in this software distribution are released under the terms of the SIMH license, a copy of which typically appears at the top of each file it applies to. This includes not only SIMH proper but also several files written by PiDP-8/I software project contributors who chose to license their contributions under the same license. For a few files, textual inclusion of the license inside the file itself was impractical, so this license is applied by reference to [a file included with the distribution][sl]. [sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md ## PiDP-8/I Design Files The PiDP-8/I design files in [`hardware/pidp8i`][hwp] were released under the Creative Commons [Attribution-NonCommercial-ShareAlike 4.0 International][ccl] license [on the mailing list][pdp8il] by their author, Oscar Vermeulen. [ccl]: https://creativecommons.org/licenses/by-nc-sa/4.0/ [hwp]: https://tangentsoft.com/pidp8i/dir?name=hardware/pdp8i&ci=trunk [pdp8il]: https://groups.google.com/d/msg/pidp-8/bcIH9uEB_kU/zg9uho7NDAAJ ## autosetup License The `configure` script and the contents of the `autosetup` directory are released under the FreeBSD license given in [`autosetup/LICENSE`][as]. [as]: https://tangentsoft.com/pidp8i/doc/trunk/autosetup/LICENSE ## palbart License The `palbart` program and its manual page are released under the terms of the license given in [`palbart/LICENSE.md`][pl]. [pl]: https://tangentsoft.com/pidp8i/doc/trunk/palbart/LICENSE.md ## OS/8 License The OS/8 media images included with this software distribution are released under the Digital License Agreement presented in [`media/os8/LICENSE.md`][dla]. [dla]: https://tangentsoft.com/pidp8i/doc/trunk/media/os8/LICENSE.md ## Other DEC Software The other files in the [`media`][md] and [`examples`][ed] directories that originate from Digital Equipment Corporation are believed to fall under the [public domain license][pdp8pd] DEC released all their PDP-8 software under after it stopped being ecomonmically viable. Documented releases for specific software (e.g. TSS/8) may be difficult to come by, however. [md]: https://tangentsoft.com/pidp8i/dir?ci=trunk&name=media [ed]: https://tangentsoft.com/pidp8i/dir?ci=trunk&name=examples ## ETOS License ETOS was a commercial product produced outside of DEC. No public documented declaration of license is known to be available for it, but we have [a third-hand report][el] that its creators are fine with ETOS being redistributed. [el]: http://mailman.trailing-edge.com/pipermail/simh/2017-January/016169.html |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 | # PiDP-8/I Changes ## Version 2017.04.04 * Removed the PDP-8 CPU idle detection feature. Oscar Vermeulen reports that it also interfered with NLS LED driving mode in his last version, and we have no reason to believe our NLS code is sufficiently different to avoid the problem. This does not affect ILS users, since enabling ILS mode disables this change. NLS system upgrades wouldn't normally be affected because the changed files are not normally overwritten on installation. If you're affected, you know it, and how to fix it. * Replaced the earlier attempts at finding an ideal IPS rate for the simulator when run on single-core hosts with usage of SIMH's percentage style throttle rates. We now explicitly set the throttle rate to "50%" which not only achieves an even higher throttle rate than in earlier releases, it's reliable in the face of varying background CPU usage. See the single-core section of `README-throttle.md` for details. ## Version 2017.04.01 The "I May Be a Fool, but I am *Your* Fool" Release * Added the `configure --alt-serial-mod` option to change the GPIO code to work with [James L-W's alternative serial mod][sm2]. * Increased the stock CPU throttle from 0.67 MIPS to 0.85 MIPS on most Pi 1 class devices, except for the Pi Zero which is a bit faster and so is able to run at 1.25 MIPS. (Testing shows that increasing it further causes SIMH to complain that it doesn't have enough CPU power to run that fast, despite the fact that top(1) shows it taking only about half the available CPU power. It's just as well: we don't want to hog all the CPU power on a single-core Pi, anyway.) * When built in NLS mode, most of the PDP-8 simulator configuration files we generate now have CPU idle detection enabled, allowing host CPU usage to drop when the simulated CPU is basically idle, such as when waiting for keyboard input. * Replaced a simplistic 2-second delay in the startup sequence of the simulator, `pidp8i-test`, and "[Incandescent Thought][it]" with a smarter interlocked startup sequencing mechanism that largely eliminates the delay. * Fixed a problem introduced in v20170204 which causes the `LOAD_ADD` and `DEPOSIT` switch handlers to generate incorrect core addresses when the SIMH PDP-8 CPU core sets bits beyond the lower 12 in the PC register. We were assuming this register is always 12-bit clean, but it isn't. * Merged in upstream SIMH improvements. Changes relevant to the PiDP-8/I include: * The PDP-8 CPU reset mechanism now does more of what our preexisting `START` switch handler did, so we now delegate to that upstream mechanism, reducing behavior differences between the cases. * Improved keyboard polling behavior in terminal handler. * Fixed many bugs identified by Coverity Scan in many different subsystems of the simulator. Normally I wouldn't note such a low-level change in this user-centric document, but it is possible that some of these improvements fix user-visible bugs. * SIMH's default PDP-8 configuration enables the DF32 disk device with the short name "DF", but since the SIMH `DEPOSIT` command works on both devices and registers, a command like `d df 0` is ambiguous, causing the default configuration of SIMH to give a "Too few arguments" error for this command, even though it's obvious that you mean the CPU DF register here. (Surely you didn't mean to overwrite the first word of your disk image instead?) Since upstream refuses to fix it, I have disabled the DF32 device in all of the default `boot/*.script` files. Since these scripts aren't overwritten on installation, this will only affect new installs unless you say `make mediainstall`, in which case your binary OS media is also overwritten. Do this at your own risk! * Many improvements to the `SING_STEP` + `DF` USB auto-mounting and SIMH attaching feature: * Prior versions apparently could only mount paper tape images correctly. This release includes a fix that allows RX type floppy images and TU type DECtape images to autoattach. * Changed the meaning of `SING_STEP` + `DF=7` from attaching an RL type removable hard disk cartridge image to the first RL01 drive to attaching an older and more period-correct RK type image to the *second* RK05 drive. The second half of the change lets you use this feature along with the stock OS/8 image to attach a second hard disk at runtime. * The file name matching code used by this feature was only using the first character of the file name extension, and it wasn't pinning the match to the end of the file name string. Thus, if you'd set `DF=0`, it would look for the first file with `.p` anywhere in the file name, not `.pt` at the end, as expected. * Improved error messages given when this feature doesn't work. * The `pidp8i-test` program now accepts a `-v` flag to make it give the version and configuration string and exit. * `pidp8i-test` now exits more cleanly, shutting down ncurses, turning off the front panel LEDs, and writing a diagnostic message on signal exits. * The version number part of the configuration string written by `pidp8i-test -v` and as the first line of output from the simulator now uses the same 10-digit Fossil checkin ID format as the Fossil timeline, making it easier to match that version to a particular Fossil checkin. * The Raspberry Pi model detection code behind the Pi model tag in the configuration string was only doing the right thing for the more common Pi models. It now reports the correct Pi model for the various flavors of Compute Module and the Pi Zero. * Improved error handling in the process that inserts the version info into the configuration string emitted when the simulator and test programs start up. * We now build and link in the upstream `sim_video` module, which allows access to a video display via SDL. We do not currently use this in the project core, but I recall hearing about a third-party project that uses this for a local graphical X-Y vector display implementation for playing Spacewar! When built on a system without SDL or even a local bitmap display, this code becomes nearly a no-op, affecting build time very little. * SIMH changes to a different delay mechanism at CPU throttle rates below 1000 IPS, which prevents our incandescent lamp simulator from running correctly. Therefore, when you give a `./configure --throttle` flag value that would use this throttle mode, we disable the ILS even when building on multi-core Raspberry Pis. (This fix doesn't disable the ILS at run time if you manually set a throttle value under 1000 IPS via a SIMH command. We'll try to help you avoid accidentally shooting yourself in the foot, but if you're going to *aim*, you're on your own.) * Several internal refactorings to improve code style, reduce the [upstream SIMH patch footprint][foot], and fix corner case bugs. [foot]: http://pastebin.com/5Jnx15QX [it]: https://tangentsoft.com/pidp8i/wiki?name=Incandescent+Thought [sm2]: https://groups.google.com/d/msg/pidp-8/-leCRMKqI1Q/Dy5RiELIFAAJ ## Version 2017.02.04 * Largely rewrote the incandescent lamp simulator (ILS) feature. The core of Ian Schofield's original contribution is still hiding in there if you go spelunking, but everything surrounding it is different. The changes and design decisions surrounding this are [complicated and subtle][ilsstory], but the end result is that the ILS is now free of judders, blips, shudders, and chugs. (Those are nuanced technical terms for "badness.") The ILS is now buttery smooth from 1 kIPS to the many-MIPS rate you get running un-throttled on a Pi 3. * Although most of the ILS work does not directly apply to the "no lamp simulator" (NLS) case, the sample rate dithering reduces display update artifacts seen in this case as well. * Slowed the ILS brightness rates down a bit: more lampy, less snappy. Whether this is accurate or not is something we'll have to determine through research separately in progress. * The ILS display is a bit brighter: the delay values used in prior versions put a cap on max brightness that was well under the full LED brightness achievable. * For the first time, it is possible to build Deeper Thought (any version) against the ILS, with minor adjustments. Prior versions of the ILS had too different an external interface to allow this. Full details are in a [new wiki article][ithought]. * In normal free-running mode, the simulator lights the Fetch and Execute LEDs at 50%, whereas before there was an imbalance that purely had to do with the much lower complexity of fetching an instruction inside the simulator vs executing it. (In real hardware, the complexities were different: fetch involved a core memory retrieval, very much non-instantaneous, whereas the execution of the fetched instruction kind of happened all at once in complicated electron flows, rather than the sequential C code of the SIMH PDP-8 simulator. Thus, it was reasonable for DEC to talk about PDP-8/I fetch-and-execute cycles as if the two steps were of equal time complexity.) I haven't compared the resulting LED appearance to a real PDP-8/I. * Several other tweaks to LED state handling to better match real hardware. * Redesigned the `pidp8i-test` program to allow manual stepping forwards and backwards in addition to the previous auto-advancing behavior. As soon as you press one of the arrow keys, the test program moves to the next or previous action in the sequence and stops auto-advancing. This mode is useful when testing the hardware with a multimeter or similar, and you need a certain row or column to stay lit up indefinitely. You can also press <kbd>R</kbd> to resume auto-advancing behavior, or either <kbd>Ctrl-C</kbd> or <kbd>X</kbd> to exit the program gracefully. This requires that you have `libncurses-dev` installed on your Pi. * The SIMH PDP-8 simulator's internal SR register now matches the hardware switches when you say Ctrl-E then `ex sr`. Prior versions only loaded the hardware switch register values into the internal register when it executed an `OSR` instruction. * Copied the KiCad design files into the source tree since they are now formally released by Oscar Vermeulen under a Creative Commons license. Also included the PDF version of the schematic produced by Tony Hill. (This is all in the `hardware/` directory.) * Lowered the default simulator throttle value for single-core Pi boards from 1332 kIPS to 666 kIPS after doing some testing with the current code on a Raspberry Pi 1 Model B+. This value was chosen since it is approximately twice the speed of a PDP-8/I. This leaves a fair bit of CPU left over for background tasks, including interactive shell use. This value may be a bit low for Pi Zero users, but it is easily [adjustable][rmth]. * Merged in the relevant SIMH updates. This is all internal stuff that doesn't affect current PiDP-8/I behavior. * Many build system and documentation improvements. [ilsstory]: https://tangentsoft.com/pidp8i/wiki?name=Incandescent+Lamp+Simulator [ithought]: https://tangentsoft.com/pidp8i/wiki?name=Incandescent+Thought ## Version 2017.01.23 * When any program that talks to the PiDP-8/I front panel starts up, it now prints out a banner modeled on the [Erlang configuration line][ecl]. For example, when I run the software in the development tree on my PiDP-8/I, I get the following: PiDP-8/I trunk:i49cd065c [pi3b] [ils] [serpcb] [gpio] It tells me that: * I'm running code built from Fossil checkin ID 49cd065c on the trunk branch, as opposed to a release version, which would be marked `release:v20170123` or similar. (The `i` here is a tag standing for "ID", as in Fossil checkin ID. Contrast `v` used to tag release version numbers.) * I'm running it on a Raspberry Pi 3 Model B with Ian Schofield's incandescent lamp simulator (ILS) feature enabled. * The software is built to expect that the PiDP-8/I PCB and the Pi board attached to it have had the serial mods made to them. * The GPIO module found the GPIO hardware and was able to attach to it. * I get a very different result when running it on my desktop machine: PiDP-8/I trunk:id8536d91 [cake] [nls] [nopcb] [rt] This tells me: * I'm running a different version of the development branch (i.e. the "trunk") of the code than what's running on the Pi. * It's not running on a Pi at all. (Cake ≠ pi.) * I've disabled the ILS feature, so it's running with the "no lamp simulator" (NLS) GPIO module. * Which is all to the good, because there's no point burning CPU power running the ILS code on a host machine that doesn't have a PiDP-8/I PCB attached. * The GPIO thread is running with real-time privileges. * The ILS feature can now be disabled at `configure` time via the new `--no-lamp-simulator` flag. This option is automatically set when building on a single-core Raspberry Pi. (The flag is there only to allow someone building the software on a multi-core host machine to disable the ILS.) * Tweaked the ILS decay constants to be asymmetric, better mimicking the way real incandescent lamps work: they heat up to full brightness faster than they fade to perceptively "off." * The LED values used by the GPIO thread were being recalculated way too often. In the ILS case, it was updating the values approximately at the same rate as the ILS's PWM core frequency, roughly 7,500 times per second, which is far higher than the human persistence of vision limit. While the PWM rate does need to be that fast to do its job, the underlying LED state values do not need to change nearly that often to fool the human into seeing instantaneous updates. The NLS case was actually worse, recalculating the LED values on every instruction executed by the PDP-8 CPU simulator, which even on a Pi 1 is likely to be a few MHz. In both the ILS and NLS cases, we now update the LED values about 100 times a second, maintaining that rate dynamically based on the current execution speed of the simulator. * In prior versions, the ILS was only updating at its intended rate when the PDP-8 simulator was running flat-out on a current multi-core Raspberry Pi. If you throttled the SIMH simulator to a slower execution rate, the display quality would start to degrade noticeably below about 1 MIPS. * With the prior fix, we now ship 5.script (i.e. the handler for starting the simulator with IF=5, or restarting it with IF=5 + `SING_STEP`) set to a throttle value of 30 kIPS, which allows the human to see each AC/MQ modification. The built-in delay loops are still there, else we'd have to drop this to well under 1 kIPS. * The `SING_INST` switch now immediately puts the processor into single instruction mode, not requiring a separate press of the `STOP` key, as in prior versions. This is the correct behavior according to the 1967-1968 edition of DEC's Small Computer Handbook for the PDP-8/I. * Greatly simplified the way single-instruction mode, processor stoppage, and the `CONT` key work. The prior implementation was error-prone and difficult to understand. This fixes a particularly bad interaction between the way `HLT` instructions and `CONT` key presses were handled, causing the processor to not resume correctly from `HLT` state. * Consolidated and cleaned up the bulk of the PiDP-8/I switch handling code so that it is not so intimately tied into the guts of the PDP-8 CPU emulator. This will greatly increase the chance that future updates to the upstream SIMH code will apply cleanly to our version. * Fixed a bug in `examples/bit-rotate.pal` which caused it to skip the actual bit rotation step. We were trying to microcode two instructions into one that the PDP-8 won't accept together, and we didn't catch it until now because the HLT bug masked it, and the `palbart` assembler we ship isn't smart enough to notice the bug. * Fully generalized the mechanism for generating `obj/*.lst`, `bin/*.pt`, and `boot/*.script` from `examples/*.pal`. You can now drop any PAL assembly language program into the `examples` directory and type `make` to build these various output forms automatically using the shipped version of `palbart`. This effectively turns this PiDP-8/I software distribution into a PDP-8 assembly language development environment: rapidly build, test, and debug your PAL programs on your PC before you deploy them to real hardware. Or, write PAL programs to debug the hardware or simulator, as we did with `examples/bit-rotate.pal`. * Fixed a sorting bug in the tool that generates `boot/*.script` from `obj/*.lst`, resulting in `dep` instructions that weren't sorted by core address. This didn't cause any real problem, but it made tracing the execution of a PAL assembly program difficult if you were trying to refer to the `boot/*.script` file to check that the PiDP-8/I's front panel is showing the correct register values. * Updated SIMH to the latest upstream version and shipping a subset of the SIMH docs as unversioned files from tangentsoft.com. * The `configure` script now aborts the build if it sees that you're trying to build the software as root, since that means it generates the init script and the pidp8i script expecting to run the installed software as root, not as your normal user. The most common way this happens is that you have a configured source tree, then change one of the `*.in` files and say `sudo make install`, thinking to build and install the change in one step. This fixes that. * Several improvements to the build system. [ecl]: http://stackoverflow.com/q/1182025/142454 ## Version 2017.01.16 * Prior releases did not include proper licensing for many of the included files. This project was, therefore, not a proper Open Source Software project. This problem has been fixed. In this release, many files that were previously technically only under standard copyright due to having no grant of license now have an explicit license, typically the same as SIMH itself. (Thank you to all of the authors who allowed me to apply this license to their contributions!) For several other files, I was able to trace down some prior license and include its text here for the first time. There remain a few "gray" items: the TSS/8 and ETOS disk images. See the [`COPYING.md` file][copying] for more on the current status of these OS images. If the legal status of these files clarifies in the future, this software distribution will react accordingly, even if that means removing these files from the distribution if we learn that these files are not freely-redistributable, as we currently believe them to be today. * The Step Counter LEDs on the front panel weren't being lit properly when EAE instructions were being used. Thanks for this patch go to Henk Gooijen and Paul R. Bernard. * The prior `boot/1.script` and `boot/5.script` files are no longer simply opaque lists of octal addresses and machine code. They are generated from PAL assembly files provided in the `examples` directory, so that you can now modify the assembly code and type `make` to rebuild these boot scripts. * The mechanism behind the prior item is fully general-purpose, not something that only works with `1.script` and `5.script`. Any `examples/*.pal` file found at `make` time is transformed into a SIMH boot script named after the PAL file and placed in the `boot` directory. This gives you an easier way to run PDP-8 assembly code inside the simulator. After saying `make` to transform `*.pal` into `*.script` files, you can run the program with `bin/pidp8i-sim boot/my-program.script` to poke your program's octal values into core and run it. This round-trip edit-and-run process is far faster than any of the options given in the [examples' `README.md` file][ex]. * Disassembled both versions of the RIM loader to commented, labeled PAL assembly language files. If you ever wanted to know what those 16 mysterious instructions printed on the front panel of your PiDP-8/I did, you can now read my pidgin interpretation of these programs in `examples/*-rim.loader.pal` and become just as confused as I am now. :) * The two RIM loader implementations now start with a nonstandard `HLT` instruction so that when you fire up the simulator with IF=1 to start the high-speed RIM loader, it automatically halts for you, so you don't have to remember to STOP the processor manually. There is currently [a bug][hltbug] in the way the simulator handles `HLT` instructions which prevents you from simply pressing START or CONT to enter the RIM loader after you've attached your paper tape, so you still have to manually toggle in the 7756 starting address and press START to load the tape into core. (I hope to fix this before the next release, but no promises.) * Added the `configure --throttle` feature for making the simulator run at a different speed than it normally does. See [`README-throttle.md`][rmth] for details. * The build system now reacts differently when building the PiDP-8/I software on a single-core Raspberry Pi: * If you're building the trunk or release branch, you'll get a configure error because it knows you can't run the current implementation of the incandescent lamp simulator on a single-core Pi. (Not enough spare CPU power, even with heavy amounts of throttling.) * If you're building the no-lamp-simulator branch, it inserts a throttle value into the generated `boot/*.script` files that do not already contain a throttle value so that the simulator doesn't hog 100% of the lone core, leaving some spare cycles for background tasks. The above `--throttle` feature overrides this. These features effectively replace the manual instructions in the old `README-single-core.md` file, which is no longer included with this software distribution, starting with this release. * Lowered the real-time priority of the GPIO thread from 98 to 4. This should not result in a user-visible change in behavior, but it is called out here in case it does. (In our testing, such high values simply aren't necessary to get the necessary performance, even on the trunk branch with the incandescent lamp simulator.) * Since v20161128, when you `make install` on a system with an existing PiDP-8/I software installation, the binary OS media images were not being overwritten, on purpose, since you may have modified them locally, so the installer chose not to overwrite your versions. With this release, the same principle applies to the SIMH boot scripts (e.g. `$prefix/share/boot/0.script`) since those are also things the user might want to modify. This release and prior ones do have important changes to some of these files, so if you do not wish to overwrite your local changes with a `make mediainstall` command, you might want to diff the two versions and decide which changes to copy over or merge into your local files. [hltbug]: https://tangentsoft.com/pidp8i/info/f961906a5c24f5de [copying]: https://tangentsoft.com/pidp8i/doc/trunk/COPYING.md [rmth]: https://tangentsoft.com/pidp8i/doc/trunk/README-throttle.md ## Version 2017.01.05 * Automated the process for merging in new SIMH updates. From within the PiDP-8/I software build directory, simply say `make simh-update` and it will do its best to merge in the latest upstream changes. This process is more for the PiDP-8/I software maintainers than for the end users of that software, but if you wish to update your SIMH software without waiting for a new release of *this* software, you now have a nice automated system for doing that. * Updated SIMH using that new process. The changes relevant to the PiDP-8/I since the prior update in release v20161226 are: * Many more improvements to the simulator's internal timer system. This should make deliberate underclocking more accurate. * It is now possible to get hex debug logs for the simulator console port by cranking up the simulator's debug level. * The simulator now reports the upstream Git commit ID it is based on in its version string, so that if you report bugs upstream to the SIMH project, you can give them a version number that will be meaningful to them. (They don't care about our vYYYYMMDD release numbers or our Fossil checkin IDs.) ## Version 2016.12.26 (The Boxing Day release) * Tony Hill updated SIMH to the latest upstream version. This change represents about 15 months worth of work in the [upstream project][simh] — plus a fair bit of work by Tony to merge it all — so I will only summarize the improvements affecting the PDP-8 simulator here: * Many improvements to the internal handling of timers. The most user-visible improvement is that you can now clock your emulated PDP-8 down to well below the performance of a real PDP-8 via `SET THROTTLE`, which can be useful for making blinkenlights demos run at human speeds without adding huge delay loops to the PDP-8 code implementing that demo. * Increased the number of supported terminals from four to either twelve or sixteen, depending on how you look at it. Eight of the additional supported terminal devices are conflict-free, while the final four variously conflict with one or more of the other features of the simulated PDP-8. If you want to use all 16, you will be unable to use the FPP, CT, MT and TSC features of the system. This limitation reflects the way the PDP-8 worked. It is not an arbitrary limitation of SIMH. * Added support for the LS8E printer interface option used by the WPS8 word processing system. * The simulator's command console now shows the FPP register descriptions when using it as a PDP-8 debugger. * Added the `SHOW TTIX/TTOX DEVNO` SIMH command to display the device numbers used for TTIX and TTOX. * The `SHOW TTIX SUMMARY` SIMH command is now case-insensitive. * Upstream improvements to host OS/compiler compatibility. This increases the chances that this software will build out of the box on random non-Raspbian systems such as your development laptop running some uncommon operating system. * When you `make install`, we now disable Deeper Thought 2 and the legacy `pidp8` service if we find them, since they conflict with our `pidp8i` service. * Added the install user to the `gpio` group if you `make install` if that group is present at install time. This is useful when building and installing the software on an existing Raspbian SD card while logged in as a user other than `pi` or `pidp8i`. [simh]: https://github.com/simh/simh/ ## Version 2016.12.18 * The entire software stack now runs without explicit root privileges. It now runs under the user and group of the one who built the software. For the few instances where it does need elevated privileges, a limited-scope set of sudo rules are installed that permit the simulator to run the necessary helper programs. * The power down and reboot front panel switch combinations are no longer sensitive to the order you flip the switches. * Changed the powerdown front panel switch combination to the more mnemonically sensible `Sing_Step` + `Sing_Inst` + `Stop`. Its prior switch combo — `Sing_Step` + `Sing_Inst` + `Start` — is now the reboot sequence, with the mnemomic "restart." * Removed the USB stick mount/unmount front panel switch combos. The automount feature precludes a need for a manual mount command, and unmount isn't necessary for paper tape images on FAT sticks. * The simulator now runs correctly on systems where the GPIO setup process fails. (Basically, anything that isn't a Raspberry Pi.) Prior to this, this failure was just blithely ignored, causing subsequent code to behave as though all switches were being pressed at the same time, causing utter havoc. The practical benefit of this is that you can now work with the software on your non-Pi desktop machine, losing out only on the front panel LEDs and switches. Everything else works just as on the Pi. You no longer need a separate vanilla SimH setup. * Added a locking mechanism that prevents `pidpi8-test` and `pidp8i-sim` from fighting over the front panel LEDs. While one of the two is running, the other refuses to run. * Added `examples/ac-mq-blinker.pal`, the PAL8 assembly code for the `boot/5.script` demo. * Fixed two unrelated problems with OS/8's FORTRAN IV implementation which prevented it from a) building new software; and b) running already-built binaries. Thanks go to Rick Murphy for providing the working OS/8 images from which the files needed to fix these two problems were extracted. * Added the VT100-patched `VTEDIT` TECO macro from Rick Murphy's OS/8 images, and made it automatically run when you run TECO from the OS/8 disk pack. Also added documentation for it in `VTEDIT.DC` on the disk pack as well as [in the wiki][vteditdoc]. * The default user name on the binary OS images is now `pidp8i` instead of `pi`, its password has changed to `edsonDeCastro1968`, and it demands a password change on first login. I realize it's a hassle, but I decided I didn't want to contribute to the plague of open-to-the-world IoT boxes. * Many build system and documentation improvements. [vteditdoc]: https://tangentsoft.com/pidp8i/wiki?name=Using+VTEDIT ## Version 2016.12.06 * The `pidp8i-test` program's LED test routines did not work correctly when built against the incandescent lamp simulator version of the GPIO module. Reworked the build so that this test program builds against the no-lamp-simulator version instead so that you don't have to choose between having the lamp simulator or having a working `pidp8i-test` program. * More improvements to `examples/pep001.pal`. * Extracted improved `PRINTS` routine from that example as `examples/routines/prints.pal`. ## Version 2016.12.05 * This release marks the first binary SD card image released under my maintainership of the software. As such, the major user-visible features in this release of the Fossil tree simply support that: * The `pidp8i-init` script now understands that the OS's SSH host keys may be missing, and re-generates them. Without this security measure, anyone who downloads that binary OS image could impersonate the SSH server on *your* PiDP-8/I. * Added a `RELEASE-PROCESS.md` document. This is primarily for my own benefit, to ensure that I don't miss a step, particularly given the complexity of producing the binary OS image. However, you may care to look into it to see what goes on over here on the other side of the Internet. :) * Added an OS/8 BASIC solution to Project Euler Problem #1, so you can see how much simpler it is compared to the PAL8 assembly language version added in the prior release. * Updated the PAL8 assembly version with several clever optimizations by Rick Murphy, the primary effect of which is that it now fits into a single page of PDP-8 core memory. ## Version 2016.12.03 * Debounced the switches. See [the mailing list post][cdb] announcing this fix for details. * Merged the [`pidp8i-test` program][testpg] from the mailing list. The LED testing portion of this program [currently][gpiols] only works correctly without the incandescent lamp simulation patch applied. * Added a solution to [Project Euler Problem #1][pep001] in PAL8 assembly language and wrote the [saga of my battle][p1saga] with this problem into the wiki. This also adds a couple of useful PAL8 routines in `examples/routines`. * Integrated David Gesswein's latest `palbart` program (v2.13) into the source distribution so that we don't have to: 1. ship pre-built RIM format paper tapes for the examples; and 2. put up with the old versions that OS package repos tend to have (Ubuntu is still shipping v2.4, from 6 years ago!) * Fixed a bug in the `make install` script that caused it to skip installing `screen` and `usbmount` from the OS's package repo when they are found to be missing. * Fixed a related bug that prevented it from disabling the serial console if you configure the software without `--serial-mod` and then install it, causing the serial console and the GPIO code in the PiDP-8/I simulator to fight over GPIO pins 14 and 15. * Removed the last of the duplicate binary media entries. This makes the zip files for this version well under half the size of those for the 2015.12.15 upstream release despite having more features. [cdb]: https://groups.google.com/d/msg/pidp-8/Fg9I8OFTXHU/VjamSoFxDAAJ [testpg]: https://groups.google.com/d/msg/pidp-8/UmIaBv2L9Ts/wB1CVeGDAwAJ [gpiols]: https://tangentsoft.com/pidp8i/tktview?name=9843cab968 [pep001]: https://projecteuler.net/problem=1 [p1saga]: https://tangentsoft.com/pidp8i/wiki?name=PEP001.PA ## Version 2016.11.28 * Added an intelligent, powerful build system, replacing the bare-bones `Makefile` based build system in the upstream version. See [`README.md`][readme] for more info on this. * The installation is now completely relocatable via `./configure --prefix=/some/other/place`. The upstream version would not work if installed somewhere other than `/opt/pidp8` due to many hard-coded absolute paths. (This is enabled by the new build system, but fixing it was not simply a matter of swapping out the build system.) * Changed all of the various "PDP," "PDP-8", and "PiDP-8" strings to variants on "PiDP-8/I", partly for consistency and partly because it seems unlikely that this software will ever be used with anything other than the PiDP-8/I project. Part of this renaming means that the default installation location is now `/opt/pidp8i`, which has the nice side benefit that installing this version of the software will not overwrite an existing installation of the upstream version in `/opt/pidp8`. Another user-visible aspect of this change is that the upstream version's `pdp.sh` script to [re]enter the simulator is now called `pidp8i`. * Merged Ian Schofield's [Display update for the PiDP8][dupatch] patch. Currently it is not optional, but there is [a plan][dudis] to allow this feature to be disabled via a `configure` script option. * The scripts that control the startup sequence of the PiDP-8/I simulator now include helpful header comments and emit useful status messages to the console. Stare no more at opaque lists of SimH commands, wondering what each script does! * Merged `scanswitch` into the top-level `src` directory, since the only thing keeping it in a separate directory was the redundant `gpio.h` file. There were minor differences between the two `gpio.h` files, but their differences do not matter. * Installing multiple times no longer overwrites the binary OS/program media, since the disk images in particular may contain local changes. If you want your media images overwritten, you can insist on it via `make mediainstall`. * The installation tree follows the Linux Filesystem Hierarchy Standard, so that files are in locations an experienced Linux user would expect to find them. The biggest changes are that the content of the upstream `bootscripts` tree is now installed into `$prefix/share/boot`, and the OS/program media images which used to be in `imagefiles` are now in `$prefix/share/media`. * Added a bunch of ancillary material: [wiki articles][wiki], [USB stick label artwork][art], a PAL8 assembly [example program][ex] for you to toggle in, etc. Also filed a bunch of [tickets][tix] detailing feature proposals, known bugs and weaknesses, etc. If you were looking for ways to contribute to the development effort, these new resources provide a bunch of ideas. * Made some efforts toward portability. While this project will always center around Raspbian and the PiDP-8/I add-on board, the intent is that you should be able to unpack the project on any other Unix type system and at least get the simulator up and running with the normal SimH manual control over execution instead of the nice front panel controls provided by the PiDP-8/I board. In particular, the software now builds under Mac OS X, though it does not yet run properly. (The modified SimH PDP-8 simulator currently misbehaves if the PiDP-8/I panel is not present. Fixing this is on the radar.) * Fixed a bunch of bugs! [readme]: https://tangentsoft.com/pidp8i/doc/trunk/README.md [dupatch]: https://groups.google.com/forum/#!topic/pidp-8/fmjt7AD1gIA [dudis]: https://tangentsoft.com/pidp8i/tktview?name=e06f8ae936 [wiki]: https://tangentsoft.com/pidp8i/wcontent [ex]: https://tangentsoft.com/pidp8i/doc/trunk/examples/README.md [art]: https://tangentsoft.com/pidp8i/dir?c=trunk&name=labels [tix]: https://tangentsoft.com/pidp8i/tickets ## Version 2015.12.15 * The last release of the software made by Oscar Vermeulen, the creator of the PiDP-8/I project. This version of the software derives from it, but differs in many ways. (See above.) Since May of 2017, this version of the software is now considered the current stable version. |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | Hacking on the PiDP-8/I Software ==== If you are going to make any changes to the PiDP-8/I software, here are some rules and hints to keep in mind while you work. Getting Started with Fossil ---- The PiDP-8/I software project is hosted using the [Fossil][fossil] [distributed version control system][dvcs]. Fossil provides most of the features of GitHub under a simpler operating model than Subversion without tying you to a proprietary web service. This guide will introduce you to some of the basics, but you should also at least read the [Fossil Quick Start Guide][fqsg]. For a more thorough introduction, I recommend [the Schimpf book][fbook]. If you have questions, it is best to ask them on [its low-volume mailing list][fml], though you may also ask me, either on [the PiDP-8/I mailing list][ggml] or via private email. You must use Fossil version 2.1 or higher with our repository, or you will get an error. If you started with one of our PiDP-8/I binary OS images made in or after April 2017, Fossil 2.x is already installed. If you're starting from some other OS, you either won't have Fossil installed at all, or you'll most likley be using an older version, since the Debian project is still shipping version 1.37 and likely will continue to do so until 2020 or so. You'll have to build Fossil from source: $ sudo apt install libssl-dev $ wget -O fossil-release.tar.gz \ https://fossil-scm.org/index.html/tarball/fossil-release?uuid=release $ tar xvf fossil-release.tar.gz $ cd fossil-release $ ./configure $ make $ sudo make install Fossil is also available for all common desktop platforms. One of [the official binaries][fbin] may work on your system. If you're getting binaries from a third party, be sure it is Fossil 2.1 or higher. [fbin]: http://fossil-scm.org/index.html/uv/download.html [dvcs]: http://en.wikipedia.org/wiki/Distributed_revision_control [fbook]: http://www.fossil-scm.org/schimpf-book/home [fml]: http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/fossil-users [fossil]: http://fossil-scm.org/ [fqsg]: http://fossil-scm.org/index.html/doc/trunk/www/quickstart.wiki [ggml]: https://groups.google.com/forum/#!forum/pidp-8 Fossil Anonymous Access ---- To clone the code repository anonymously, say: $ mkdir -p ~/museum ~/src/pidp8i/trunk $ sudo apt install fossil $ fossil clone https://tangentsoft.com/pidp8i ~/museum/pidp8i.fossil $ cd ~/src/pidp8i/trunk $ fossil open ~/museum/pidp8i.fossil The `clone` command gets you a file called `pidp8i.fossil` containing the full history of PiDP-8/I from the upstream 2015.12.15 release onward. You can call that clone file anything you like and put it in any directory you like. Even the `.fossil` extension is largely a convention, not a requirement. Working With Existing Tags and Branches ---- The directory structure shown in the commands above is more complicated than strictly necessary, but it has a number of nice properties. First, it collects other software projects under a common top-level directory, which I'm calling `~/src`, but you are free to use any scheme you like. Second, the top-level project directory stores multiple separate checkouts, one for each branch or tag I'm actively working with at the moment. So, to add a few other checkouts, you could say: $ cd ~/src/pidp8i $ mkdir -p release # another branch $ mkdir -p v20151215 # a tag this time, not a branch ...etc... $ cd release $ fossil open ~/museum/pidp8i.fossil release $ cd ../v20151215 $ fossil open ~/museum/pidp8i.fossil v20151215 ...etc... This gives you multiple independent checkouts. The branch checkouts remain pinned to the tip of that branch, so that if someone else checks changes in on that branch and you say `fossil update`, those changes appear in your checkout of that branch. The tag checkouts simply give you the latest checkin with that tag; saying `fossil update` in a checkout made from a tag will fast-forward you to the tip of the branch that tag was made on. (In Fossil, tags and branches are related, but the details are beyond our scope here. See the [Fossil Quick Start Guide][fqsg] and the documents it links to for more details.) This directory scheme shows an important difference between Fossil and Git: with Git, the checkout and the clone are intermingled in the same directory tree, but in Fossil, they are strictly separate. Git can emulate Fossil's normal working style through its [worktree][gitwt] feature, but it's a kind of lash-up using symlinks and such, whereas with Fossil, there is no confusion: the repository clone is a single SQLite database file — here, `pidp8i.fossil` — and the checkouts are made from the contents of that database. Another important difference relative to Git is that with Fossil, local checkins attempt to automatically sync checked-in changes back to the repository you cloned from. (This only works if you have a login on the remote repository, the subject of the next section.) This solves a number of problems with Git, all stemming from the fact that Git almost actively tries to make sure every clone differs from every other in some important way. While Fossil does allow offline operation and local independent clones, its default mode of operation is to try and keep the clones in sync as much as possible. Git works the way it does because it was designed to meet the needs of the Linux kernel development project, which is inherently federated, so Git tries to operate in a federated model as well. Fossil is better for smaller, more coherent teams, where there is a single, clear goal for the project and a single source for its official code. Fossil helps remote developers cooperate, whereas Git helps remote developers go off on their own tangents for extended periods of time and optionally sync back up with each other occasionally. Fossil is a better match for the way the PiDP-8/I software project works: we want you to cooperate closely with us, not go off on wild tangents. [gitwt]: https://git-scm.com/docs/git-worktree Fossil Developer Access ---- If you have a developer account on tangentsoft.com's Fossil instance, just add your username to the URL like so: $ fossil clone http://username@tangentsoft.com/pidp8i pidp8i.fossil Fossil will ask you for the password for `username` on the remote Fossil instance, and it will offer to remember it for you. If you let it remember the password, operation from then on is scarcely different from working with an anonymous clone, except that on checkin, your changes will be sync'd back to the repository on tangentsoft.com if you're online at the time. If you're working offline, Fossil will still do the checkin, but you'll be able to sync with the central repoisitory once you get back online. It is best to work on a branch when unable to use Fossil's autosync feature, as you are less likely to have a sync conflict when attempting to send a new branch to the central server than in attempting to merge your changes to the tip of trunk into the current upstream trunk, which may well have changed since you went offline. You can purposely work offline by disabling autosync mode: $ fossil set autosync 0 Until you re-enable it (`autosync 1`) Fossil will stop trying to sync your local changes back to the central repo. In this mode, Fossil works more like Git's default mode, buying you many of the same problems that go along with that working style. I recommend disabling autosync mode only when you are truly going to be offline, and don't want Fossil attempting to sync when you know it will fail. Getting Developer Access ---- The administrator of this repository is Warren Young, whose email you can find on the [official PiDP-8/I project mailing list][ggml]. I generally give developer access to anyone who makes a reasonable request. Creating Branches ---- Creating a branch in Fossil is scary-simple, to the point that those coming from other version control systems may ask, "Is that really all there is to it?" Yes, really, this is it: $ fossil ci --branch new-branch-name That is to say, you make your changes as you normally would; then when you go to check them in, you give the `--branch` option to the `ci/checkin` command to put the changes on a new branch, rather than add them to the same branch the changes were made against. While developers with login rights to the PiDP-8/I Fossil instance are allowed to check in on the trunk at any time, we recommend using branches whenever you're working on something experimental, or where you can't make the necessary changes in a single coherent checkin. Basically, `trunk` should always build without error, and it should always function correctly. Branches are for isolating work until it is ready to merge into the trunk. Here again we have a difference with Git: because Fossil normally syncs your work back to the central repository, this means we get to see the branches you are still working on. This is a *good thing*. Do not fear committing broken or otherwise bad code to a branch. [You are not your code.][daff] We are software developers, too: we understand that software development is an iterative process, and that not all ideas spring forth perfect and production-ready from the fingers of its developers. These public branches let your collaborators see what you're up to, and maybe lend advice or a hand in the work, but mostly public branches let your collaborators see what you're up to, so they're not surprised when the change finally lands in trunk. This is part of what I mean about Fossil fostering close cooperation rather than fostering wild tangents. Jim McCarthy (author of [Dynamics of Software Development][dosd]) has a presentation on YouTube that touches on this topic at a couple of points: * [Don't go dark](https://www.youtube.com/watch?v=9OJ9hplU8XA) * [Beware of a guy in a room](https://www.youtube.com/watch?v=oY6BCHqEbyc) Fossil's sync-by-default behavior fights these negative tendencies. PiDP-8/I project developers are welcome to create branches at will. The main rule is to follow the branch naming scheme: all lowercase with hyphens separating words. See the [available branch list][brlist] for examples to emulate. [brlist]: https://tangentsoft.com/pidp8i/brlist [daff]: http://www.hanselman.com/blog/YouAreNotYourCode.aspx [dosd]: http://amzn.to/2iEVoBL Debug Builds ---- By default, the build system creates a release build, but you can force it to produce a binary without as much optimization and with debug symbols included: $ ./configure --debug-mode Manipulating the Build System Source Files ---- The [autosetup build system][asbs] is composed of these files and directories: auto.def autosetup/ configure Makefile.in Unlike with GNU Autoconf, which you may be familiar with, the `configure` script is not output from some other tool. It is just a driver for the Tcl and C code under the `autosetup` directory. If you have to modify any of these files to get some needed effect, you should try to get that change into the upstream project, then merge that change down into the local copy when it lands upstream. The bulk of the customization to the build system is in `auto.def`, which is a Tcl script run by `autosetup` via the `configure` script. Some knowledge of [Tcl syntax][tcldoc] will therefore be helpful in modifying it. If you do not have Tcl installed on your system, `configure` builds a minimal Tcl interpreter called `jimsh0`, based on the [Jim Tcl][jim] project. Developers working on the build system are encoruaged to use this stripped-down version of Tcl rather than "real" Tcl because Jim Tcl is more or less a strict subset of Tcl, so any changes you make that work with the `jimsh0` interpreter should also work with "real" Tcl, but not vice versa. If you have Tcl installed and don't really need it, consider uninstalling it to force `autosetup` to build and use `jimsh0`. The `Makefile.in` file is largely a standard [GNU `make`][gmake] file excepting only that it has variables substituted into it by [`autosetup`][asbs] using its `@VARIABLE@` syntax. At this time, we do not attempt to achieve compatibility with other `make` programs, though in the future we may need it to work with [BSD `make`][bmake] as well, so if you are adding features, you might want to stick to the common subset of features implemented by both the GNU and BSD flavors of `make`. We do not anticpate any need to support any other `make` flavors. (This, by the way, is why we're not using some heavy-weight build system such as the GNU Autotools, CMake, etc. The primary advantage of GNU Autotools is that you can generate source packages that will configure and build on weird and ancient flavors of Unix; we don't need that. Cross-platform build systems such as CMake ease building the same software on multiple disparate platforms straightforward, but the PiDP-8/I software is built primarily on and for a single operating system, Rasbpian Linux. It also happens to build and run on other modern Unix and Linux systems, for which we also do not need the full power of something like CMake. `autosetup` and GNU `make` suffice for our purposes here.) [asbs]: http://msteveb.github.io/autosetup/ [bmake]: https://www.freebsd.org/doc/en/books/developers-handbook/tools-make.html [gmake]: https://www.gnu.org/software/make/ [jim]: http://jim.tcl.tk/ [tcldoc]: http://wiki.tcl.tk/11485 Submitting Patches ---- If you do not have a developer login on the PiDP-8/I software repository, you can still send changes to the project. The simplest way is to say this after developing your change against the trunk of PiDP-8/I: $ fossil diff > my-changes.patch Then attach that file to a new [PiDP-8/I mailing list][ggml] message along with a declaration of the license you wish to contribute your changes under. We suggest using the [SIMH license][simhl], but any [non-viral][viral] [OSI-approved license][osil] should suffice. If your change is more than a small patch, `fossil diff` might not incorporate all of the changes you have made. The old unified `diff` format can't encode branch names, file renamings, file deletions, tags, checkin comments, and other Fossil-specific information. For such changes, it is better to send a Fossil bundle: $ fossil set autosync 0 # disable autosync $ fossil checkin --branch my-changes ...followed by more checkins on that branch... $ fossil bundle export --branch my-changes my-changes.bundle After that first `fossil checkin --branch ...` command, any subsequent changes will also be made on that branch without needing a `--branch` option until you explicitly switch to some other branch. This lets you build up a larger change on a private branch until you're ready to submit the whole thing as a bundle. Because you are working on a branch on your private copy of the PiDP-8/I Fossil repository, you are free to make as many checkins as you like on the new branch before giving the `bundle export` command. Once you are done with the bundle, send it to the mailing list just as with the patch. If you provide a quality patch, we are likely to offer you a developer login on [the repository][repo] so you don't have to continue with the patch or bundle methods. Please make your patches or experimental branch bundles against the tip of the current trunk. PiDP-8/I often drifts enough during development that a patch against a stable release may not apply to the trunk cleanly otherwise. [osil]: https://opensource.org/licenses [repo]: http://tangentsoft.com/pidp8i/ [simhl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md [viral]: https://en.wikipedia.org/wiki/Viral_license The PiDP-8/I Software Project Code Style Rules ---- Every code base should have a common code style. Love it or hate it, here are PiDP-8/I's current code style rules: **C Source Code** File types: `c`, `h`, `c.in` We follow the SIMH project's pre-existing code style when modifying one of its source files: * Spaces for indents, size 4 * DOS line endings. (Yes, even though this is a Linux-based project! All decent Linux text editors can cope with this.) * Function, structure, type, and variable names are all lowercase, with underscores separating words * Macro names are in `ALL_UPPERCASE_WITH_UNDERSCORES` * Whitespace in the SIMH C files is of a style I have never seen anywhere else in my decades of software development. This example shows the important features: int some_function (char some_parameter) { int some_variable = 0; if (some_parameter != '\0') { int nbytes = sizeof (some_parameter); char *buffer = malloc (4 * nbytes); switch (some_parameter) { case 'a': do_something_with_buffer ((char *)buffer); default: do_something_else (); } } else { some_other_function (with_a_large, "number of parameters", wraps_with_a_single, "indent level"); printf (stderr, "Failed to allocate buffer.\n"); } } It is vaguely like K&R C style except that: - The top level of statements in a function are not indented - The closing curly brace is indented to the same level as the statement(s) it contains - There is a space before all opening parentheses, not just those used in `if`, `while`, and similar flow control statements. Nested open parentheses do not have extra spaces, however. Only the outer opening parenthesis has a space separating it from what went before. - Multiple variables declared together don't have their types and variable names aligned in columns. I find that this style is mostly sensible, but with two serious problems: I find the indented closing curly braces confusing, and I find that the loss of the first indent level for the statements inside a function makes functions all visually run together in a screenful of code. Therefore, when we have the luxury to be working on a file separate from SIMH, we use a variant of its style with these two changes, which you can produce with the `tools/restyle` command. See its internal comments for details. That gives the following, when applied to the above example: int some_function (char some_parameter) { int some_variable = 0; if (some_parameter != '\0') { int nbytes = sizeof (some_parameter); char *buffer = malloc (4 * nbytes); switch (some_parameter) { case 'a': do_something_with_buffer ((char *)buffer); default: do_something_else (); } } else { some_other_function (with_a_large, "number of parameters", wraps_with_a_single, "indent level"); printf (stderr, "Failed to allocate buffer.\n"); } } If that looks greatly different, realize that it is just two indenting level differences: add one indent at function level, except for the closing braces, which we leave at their previous position. SIMH occasionally exceeds 100-column lines. I recommend breaking long lines at 72 columns. Call me an 80-column traditionalist. When in doubt, mimic what you see in the current code. When still in doubt, ask on the mailing list. [indent]: http://linux.die.net/man/1/indent **Plain Text Files** File types: `md`, `txt` * Spaces for indents, size 4. * Unix line endings. The only common text editor I'm aware of that has a problem with this is Notepad, and people looking at these files anywhere other than unpacked on a Raspberry Pi box are probably looking at them through the Fossil web interface on tangentsoft.com. * Markdown files must follow the syntax flavor understood by [Fossil's Markdown interpreter][fmd]. [fmd]: https://tangentsoft.com/pidp8i/md_rules |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | ######################################################################## # Makefile.in - Processed by autosetup's configure script to generate # the GNU make(1) file for building the PiDP-8/I software. # # If you are seeing this at the top of a file called Makefile and you # intend to make edits, do that in Makefile.in. Saying "make" will then # re-build Makefile from that modified Makefile.in before proceeding to # do the "make" operation. # # Copyright © 2015-2017 Oscar Vermeulen, Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## # Git commit ID of the latest version of the SIMH 4 project on GitHub # that has been merged into this source base. SGCID=17903827bdb294f7e60d4c7f172bd6a1a71dfbd5 CFLAGS = @CFLAGS@ -Wno-unused-result -Wno-parentheses @BUILDMODE@ \ -DUSE_READER_THREAD -DHAVE_DLOPEN=so -DPIDP8I -DSIM_ASYNCH_IO \ -DHAVE_REGEX_H -DHAVE_GLOB -DSIM_GIT_COMMIT_ID=$(SGCID) \ -D_GNU_SOURCE -U__STRICT_ANSI__ \ -I @srcdir@/src -I @srcdir@/src/PDP8 -I src SIM = bin/pidp8i-sim BINS = bin/palbart $(SIM) bin/pidp8i-test libexec/scanswitch BUILDDIRS = bin libexec obj/PDP8 INSTDIRS = bin etc libexec share/boot share/media share/man/man1 OBJS = \ obj/gpio-common.o \ obj/PDP8/pdp8_df.o \ obj/PDP8/pdp8_cpu.o \ obj/PDP8/pdp8_clk.o \ obj/PDP8/pdp8_ct.o \ obj/PDP8/pdp8_dt.o \ obj/PDP8/pdp8_fpp.o \ obj/PDP8/pdp8_lp.o \ obj/PDP8/pdp8_mt.o \ obj/PDP8/pdp8_pt.o \ obj/PDP8/pdp8_rf.o \ obj/PDP8/pdp8_rk.o \ obj/PDP8/pdp8_rl.o \ obj/PDP8/pdp8_rx.o \ obj/PDP8/pdp8_sys.o \ obj/PDP8/pdp8_td.o \ obj/PDP8/pdp8_tsc.o \ obj/PDP8/pdp8_tt.o \ obj/PDP8/pdp8_ttx.o \ obj/PDP8/pidp8i.o \ obj/scp.o \ obj/sim_console.o \ obj/sim_disk.o \ obj/sim_ether.o \ obj/sim_fio.o \ obj/sim_serial.o \ obj/sim_sock.o \ obj/sim_tape.o \ obj/sim_timer.o \ obj/sim_tmxr.o \ obj/sim_video.o ifeq (@BUILD_DEEPER_THOUGHT@, 1) BINS += bin/deeper endif LIBS = -lm -ldl -lpthread ASM_PTS := $(wildcard @srcdir@/asm/*.pal) ASM_PTS := $(subst @srcdir@/asm,bin,$(ASM_PTS)) ASM_PTS := $(ASM_PTS:.pal=.pt) EX_PTS := $(wildcard @srcdir@/examples/*.pal) EX_PTS := $(subst @srcdir@/examples,bin,$(EX_PTS)) EX_PTS := $(EX_PTS:.pal=.pt) LISTINGS := $(ASM_PTS:.pt=.lst) $(EX_PTS:.pt=.lst) LISTINGS := $(subst bin/,obj/,$(LISTINGS)) BOOTSCRIPTS := $(LISTINGS:.lst=.script) BOOTSCRIPTS := $(subst obj/,boot/,$(BOOTSCRIPTS)) \ boot/1.script \ boot/5.script # List of *.in files from auto.def file, except for this present file # (Makefile.in) which is handled separately. This list should only # change when the list of "make-template" calls in auto.def changes. # # If the first file listed below changes, change the AUTOREBUILD rule # near the end of this file to match! INFILES = \ @srcdir@/bin/pidp8i.in \ @srcdir@/boot/0.script.in \ @srcdir@/boot/2.script.in \ @srcdir@/boot/3.script.in \ @srcdir@/boot/4.script.in \ @srcdir@/boot/6.script.in \ @srcdir@/boot/7.script.in \ @srcdir@/etc/pidp8i-init.in \ @srcdir@/etc/sudoers.in \ @srcdir@/src/gpio-common.c.in \ @srcdir@/src/PDP8/pidp8i.c.in \ @srcdir@/tools/simh-update.in PRECIOUS_INFILES = \ @srcdir@/Makefile.in \ @srcdir@/examples/Makefile.in \ @srcdir@/src/Makefile.in \ @srcdir@/src/PDP8/Makefile.in OUTFILES := $(subst @srcdir@/,,$(INFILES)) OUTFILES := $(subst .in,,$(OUTFILES)) PRECIOUS_OUTFILES := $(subst @srcdir@/,,$(PRECIOUS_INFILES)) PRECIOUS_OUTFILES := $(subst .in,,$(PRECIOUS_OUTFILES)) CLTXT = /boot/cmdline.txt .PHONY: tags .PRECIOUS: $(PRECIOUS_OUTFILES) all: $(OUTFILES) $(PRECIOUS_OUTFILES) $(BUILDDIRS) $(BINS) $(BOOTSCRIPTS) $(LISTINGS) $(ASM_PTS) $(EX_PTS) @chmod 755 bin/pidp8i clean: @rm -f $(BINS) $(BOOTSCRIPTS) $(ASM_PTS) $(EX_PTS) $(LISTINGS) $(OBJS) $(OUTFILES) \ tags \ obj/*.d \ obj/*.o \ obj/PDP8/*.d \ @srcdir@/examples/*.err @-rmdir -p $(BUILDDIRS) 2> /dev/null || true distclean: clean @rm -f $(PRECIOUS_OUTFILES) \ config.log \ autosetup/jimsh0 \ src/config.h ctags tags: @ctags -R @srcdir@ ifeq (@HAVE_PROG_CSCOPE@, 1) @cscope -bR -s@srcdir@ endif install: all @echo Installing to @prefix@... @# Create any missing install tree directories for d in $(INSTDIRS) ; do @INSTALL@ -m 755 -d @prefix@/$$d ; done @# Install files into those dirs and set their perms for f in $(BINS) ; do @INSTALL@ -m 755 -D -s $$f @prefix@/$$f ; done @INSTALL@ -m 755 @srcdir@/bin/pidp8i @prefix@/bin -for f in @prefix@/bin/pidp8i-* ; do setcap 'cap_sys_nice=eip' $$f ; done || true test -e @MEDIADIR@/os8/os8.rk05 || $(MAKE) mediainstall @# If this is a Debian-type system, install needed helper programs @test -x /usr/bin/apt-get -a ! -h /media/usb && apt-get -y install usbmount || true @test -x /usr/bin/apt-get -a ! -x /usr/bin/screen && apt-get -y install screen || true @# Disable competing services if this is a Raspberry Pi @(test -x /bin/systemctl && /bin/systemctl disable deeper || true) @(test -x /bin/systemctl && /bin/systemctl disable pidp8 || true) @# Install the init script if this system is systemd based. @INSTALL@ -m 755 @srcdir@/etc/pidp8i-init @prefix@/etc @( test -w /etc/init.d -a -x /bin/systemctl && \ ln -sf @ABSPREFIX@/etc/pidp8i-init /etc/init.d/pidp8i && \ /bin/systemctl enable pidp8i \ ) || true @# Give the install user permission to use GPIO if done on a Pi @grep -q '^gpio:' /etc/group && usermod -a -G gpio @INSTUSR@ || true @# Give the install user permission to shut down and reboot the Pi @# if this is a systemd/sudo based system. @( test -d /etc/sudoers.d -a -w /etc/sudoers.d -a -x /bin/systemctl && \ @INSTALL@ -m 440 -o root -g root @srcdir@/etc/sudoers \ /etc/sudoers.d/099_pidp8i \ ) || true @# Add installation bin dir to the non-root user's PATH unless it's @# already in there or we aren't running under sudo. @(for p in .profile .bash_profile ; do \ test -n "$$SUDO_USER" -a -w "/home/$$SUDO_USER/$$p" && \ ! grep -qF "@ABSPREFIX@/bin" "/home/$$SUDO_USER/$$p" && \ echo "export PATH=\$$PATH:@ABSPREFIX@/bin" >> "/home/$$SUDO_USER/$$p" ; \ done) || true @# Ditto for MANPATH @(for p in .profile .bash_profile ; do \ test -n "$$SUDO_USER" -a -w "/home/$$SUDO_USER/$$p" && \ ! grep -qF "@ABSPREFIX@/share/man" "/home/$$SUDO_USER/$$p" && \ echo "export MANPATH=\$$MANPATH:@ABSPREFIX@/share/man" >> "/home/$$SUDO_USER/$$p" ; \ done) || true @# If serial mod is disabled, turn off serial console and kgdb stuff @# in case they were enabled previously, else they will fight with @# our use of GPIO. @( test -z "@PCB_SERIAL_MOD_ANY@" -a -r $(CLTXT) && ! -w $(CLTXT) && \ cp -p $(CLTXT) "$(CLTXT)"_orig && \ sed -e 's/console\=[a-zA-Z0-9]+,[0-9]+ //' \ -e 's/kgdboc\=[a-zA-Z0-9]+,[0-9]+ //' -i $(CLTXT) \ ) || true @# Install palbart stuff @INSTALL@ -m 755 bin/palbart @prefix@/bin @INSTALL@ -m 644 @srcdir@/palbart/palbart.1 @prefix@/share/man/man1 mediainstall: @echo "[Re]installing OS and program media..." @cd @srcdir@ ; \ find media \( \ -name \*.bin -o \ -name \*.dsk -o \ -name \*.rk05 -o \ -name \*.tu56 \ \) -exec @INSTALL@ -D -m 664 -g @INSTGRP@ {} @ABSPREFIX@/share/{} \; @INSTALL@ -m 664 -g @INSTGRP@ boot/*.script @BOOTDIR@ reconfig: @AUTOREMAKE@ release: all @srcdir@/tools/mkrel run: $(SIM) @srcdir@/boot/0.script simh-update simh-update-f: @@srcdir@/tools/simh-update $(subst simh-update,,$@) # Rule for compiling *.c to *.o and autogenerating dependency info. # Explained at http://scottmcpeak.com/autodepend/autodepend.html # # Reflect any changes here into near-duplicate below! obj/%.o: @srcdir@/src/%.c $(CC) -c $(CFLAGS) @srcdir@/src/$*.c -o obj/$*.o $(CC) -MM $(CFLAGS) @srcdir@/src/$*.c > obj/$*.d @mv -f obj/$*.d obj/$*.d.tmp @sed -e 's|.*:|obj/$*.o:|' < obj/$*.d.tmp > obj/$*.d @sed -e 's/.*://' -e 's/\\$$//' < obj/$*.d.tmp | fmt -1 | \ sed -e 's/^ *//' -e 's/$$/:/' >> obj/$*.d @rm -f obj/$*.d.tmp # Near-duplicate of above rule for those *.c files generated from *.c.in # files in the srcdir. Needed when building out-of-tree. obj/%.o: src/%.c $(CC) -c $(CFLAGS) src/$*.c -o obj/$*.o $(CC) -MM $(CFLAGS) src/$*.c > obj/$*.d @mv -f obj/$*.d obj/$*.d.tmp @sed -e 's|.*:|obj/$*.o:|' < obj/$*.d.tmp > obj/$*.d @sed -e 's/.*://' -e 's/\\$$//' < obj/$*.d.tmp | fmt -1 | \ sed -e 's/^ *//' -e 's/$$/:/' >> obj/$*.d @rm -f obj/$*.d.tmp # Rule for building PAL assembly language programs in asm/*.pal. obj/%.lst bin/%.pt: @srcdir@/asm/%.pal bin/palbart bin/palbart -lr $< || cat obj/$*.err mv @srcdir@/asm/$*.lst obj mv @srcdir@/asm/$*.rim bin/$*.pt # Ditto for those in examples/*.pal. obj/%.lst bin/%.pt: @srcdir@/examples/%.pal bin/palbart bin/palbart -lr $< || cat obj/$*.err mv @srcdir@/examples/$*.lst obj mv @srcdir@/examples/$*.rim bin/$*.pt # Rule for translating PAL assembly language program listings to SIMH # boot scripts. boot/%.script: obj/%.lst @srcdir@/tools/mkbootscript $< # Rules for making aliases of named example programs translated to boot # scripts as special numbered boot scripts boot/1.script: boot/hs-rim-loader.script ln -f $< $@ boot/5.script: boot/ac-mq-blinker.script ln -f $< $@ bin/palbart: @srcdir@/palbart/palbart.c $(CC) -Wall -Wno-strict-prototypes @BUILDMODE@ $< -o $@ $(CC) -MM $< -o obj/palbart.d $(BUILDDIRS): mkdir -p $@ $(SIM): $(OBJS) obj/gpio-@LED_DRIVER_MODULE@ls.o $(CC) -o $@ $^ $(LIBS) bin/pidp8i-test: obj/test.o obj/gpio-nls.o obj/gpio-common.o $(CC) -o $@ $^ $(LIBS) -lncurses bin/deeper: obj/deeper.o obj/gpio-@LED_DRIVER_MODULE@ls.o obj/gpio-common.o $(CC) -o $@ $^ $(LIBS) libexec/scanswitch: obj/scanswitch.o obj/gpio-nls.o obj/gpio-common.o $(CC) -o $@ $^ $(LIBS) ifeq ($(findstring clean,$(MAKECMDGOALS)),) Makefile: @srcdir@/Makefile.in @srcdir@/auto.def $(INFILES) $(PRECIOUS_INFILES) @AUTODEPS@ @AUTOREMAKE@ && $(MAKE) # Rebuild simulator whenever one of its *.in files change. # # This is trickier than it appears. If you simply make $(OUTFILES) # depend on $(INFILES), make(1) thinks it can build all of $(OUTFILES) # in parallel if given -jN, which causes ./configure --args to run N # times in parallel, which blows the build system up right good and # proper; bits everywhere. We purposely list only the first file in # $(INFILES) here to prevent that. The other files in $(INFILES) will # also be built, which confuses make(1) somewhat, but it figures things # out on the subsequent $(MAKE) call. # # We also list files like tools/version which, when they change, trigger # a rebuild of $(OUTFILES) because their change may affect what gets # generated. This happened when we moved from 8 to 10 character Fossil # artifact IDs in the version string to match Fossil timeline's default. bin/pidp8i: @srcdir@/bin/pidp8i.in @srcdir@/tools/version @AUTOREMAKE@ && $(MAKE) endif # Rebuild simulator if the version string tool changes, since its output # may have changed. src/gpio-common.c: @srcdir@/tools/version -include $(OBJS:.o=.d) obj/scanswitch.d |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | # Throttling the Simulator When you do not give the `--throttle` option to the `configure` script, the simulator's speed is set based on the number of CPU cores detected by the `tools/corecount` script. ## Multi-Core Default If `corecount` detects a multi-core system, the default behavior is to not throttle the simulator at all, since there are only 2 threads in the software that take substantial amounts of CPU power. The most hungry thread is the PDP-8 simulator proper, which runs flat-out, taking an entire core's available power by default. The other hungry thread is the one that drives the front panel LEDs, which takes about 35% of a single core's power on a Raspberry Pi 3 when you build the software with the incandescent lamp simulator enabled. This leaves over 2 cores worth of CPU power untapped on multi-core Raspberry Pis, so the system performance remains snappy even with the simulator running. You can force this behavior with `--throttle=none`. ## Single-Core Default If the `configure` script decides that you're building this on a single-core system, it purposely throttles the PDP-8 simulator so that it takes about 50% of a single core's worth of power on your system. Since different single-core Raspberry Pi boards run at different default clock rates — overclocking aside — we cannot just set a single IPS value and know that it's correct. Besides that, SIMH's reaction to not having enough host CPU power to run at the requested IPS rate is to *turn off throttling entirely*, thus hogging the whole host CPU, exactly the opposite of what you want by turning on throttling! Since host CPU power is briefly impacted when starting the simulator up for the first time, SIMH's guesses about whether you've asked it to run at too fast a rate undershoot the actual capability of the hardware badly. Worse, when you set the PiDP-8/I software to start on boot via `systemd`, it's running in parallel with other startup tasks, further reducing the amount of host CPU power available to the simulator at the instant of startup, requiring an even lower IPS rate if you want to prevent SIMH from going into no-throttle mode. The solution to all of these problems is `set throttle 50%`, which tells SIMH to dynamically adjust the IPS rate according to available host CPU power. This does mean you don't get a steady IPS rate, but it does enforce our wish to leave some CPU power left over for background tasks. You might wish to adjust that default host/simulator CPU usage split. The `--throttle` option accepts percentages: ./configure --throttle='75%' Note the single-quoted value: you must do that to avoid problems with the shell, since the percent character is special to it. Incidentally, you cannot use this throttling feature to leave enough CPU power on a single-core Pi to run the [incandescent lamp simulator][ils]. We've tried, and you have to clock the simulator down to less than the speed of a PDP-8/S! We're working on ways to improve the speed of that lamp simulator to let it run on single-core raspberry Pis, but we may not succeed. For this reason, the build system disables the incandescent lamp simulator feature on a single-core Pi. You can force the build system to select this throttle value even on a multi-core Pi with `--throttle=single-core`. You will erroneously get this single-core behavior if you run the `configure` script on a system where `tools/corecount` has no built-in way to count the CPU cores in your system correctly, so it returns 1, forcing a single-core build. That script currently only returns the correct value on Linux, BSD, and macOS systems. To fix it, you can either say `--throttle=none` or you can patch `tools/corecount` to properly report the number of cores on your system. If you choose the latter path, please send the patch to the mailing list so it can be integrated into the next release of the software. ## Underclocking There are many reasons to make the software run slower than it normally would. You may achieve such ends by giving the `--throttle` option to the `configure` script: * `--throttle=CPUTYPE`: if you give a value referencing one of the many PDP-8 family members, it selects a value based on the execution time of a `TAD` instruction in direct access mode on that processor: | Value | Alias For | Memory Cycle Time --------------------------------------------------- | `pdp8e` | 416k | 1.2 µs | `pdp8i`, `pdp8a` | 333k | 1.5 µs | `pdp8l`, `pdp8` | 313k | 1.6 µs | `ha6120` | 182k | 2.7 µs | `im6100a` | 200k | 2.5 µs | `im6100` | 100k | 5 µs | `im6100c` | 83k | 6 µs | `pdp8s` | 63k | 8 µs I chose `TAD` because it's a typical instruction for the processor, and its execution speed is based on the memory cycle time for the processor, an easy specification to find. Other instructions (e.g. most OPR instructions) execute faster than this, while others (e.g. IOT) execute far slower. (See the processor's manual for details.) SIMH, on the other hand, does not discriminate. When you say `--throttle=pdp8i`, causing the build system to insert `SET THROTTLE 333k` commands into the SIMH boot scripts, the SIMH PDP-8 simulator does its best to execute exactly 333,000 instructions per second, regardless of the instruction type. Consequently, if you were to benchmark this simulator configured with one of the options above, there would doubtless be some difference in execution speed when compared to the original hardware, depending on the mix of instructions executed. (See the I/O Matters section below for a further complication.) The values for the Intersil and Harris CMOS microprocessors are for the fastest clock speed supported for that particular chip. Use the `STRING` form of this option (documented below) if you wish to emulate an underclocked microprocessor. * `--throttle=human`: Causes the computer to throttle the human. "I'm sorry, Dave, but you are not worthy to run this software." "Aaackkthhhpptt..." No, wait, that can't be right. Let's see here...ah, yes, what it *actually* does is slows the processor down to 10 instructions per second, about the fastest that allows the human eye to easily discern LED state changes as separate. If you increase it very much above this, the eye starts seeing the LED state changes as a blur. This mode is useful for running otherwise-useful software as a "blinkenlights" demo. This mode disables the incandescent lamp simulator (ILS); see below. * `--throttle=trace`: Runs one instruction per second. The effect is as if you were running a PDP-8/I in single-instruction mode and were pressing the `CONT` button once a second to step through a program. This mode also disables the ILS. * `--throttle=STRING`: any value not otherwise understood is passed directly to SIMH in `SET THROTTLE` commands inserted into the generated `boot/*.script` files. You can use any string here that SIMH itself supports; [read the fine manual][tfm]. If you use the ratio form here (e.g. `--throttle=123/456`) the configuration script disables the ILS feature because of the way SIMH handles this type of timing. The ratio form of CPU throttling tells SIMH to run some number of instructions and then sleep for some number of milliseconds. (The above 123/456 example means "run 123 instructions, then sleep for 456 ms.") This batched instruction execution scheme interferes with the high-speed LED panel update rate, so we must disable the ILS when running with such a throttle value set. Therefore, you should only use the ratio form of throttle value when you need to get under 1000 instructions per second. For any value over that, give `--throttle=1k` or higher, which allows the ILS feature to properly maintain its LED brightness values. ## I/O Matters The throttle mechanism discussed above only affects the speed of the PDP-8 CPU simulator. It does not affect the speed of I/O operations. The only I/O channel you can throttle in the same way is a serial terminal by purposely choosing a slower bit rate for it than the maximum value. If you set it to 110 bps, it runs at the speed of a Teletype Model 33 ASR, the most common terminal type used for the PDP-8/I, and most other early PDP-8 flavors. Later PDP-8s were often paired with (or integrated into!) glass TTYs such as the VT05, which flew along at 2400 bps. Then things got really fancy with the VT52, which screamed along at 9600 bps. Wowee! I'm not aware of a way to make SIMH slow the other I/O operations, such as disk access speeds, in order to emulate the speed of the actual hardware. ## License Copyright © 2017 by Warren Young. This document is licensed under the terms of [the SIMH license][sl]. [sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md [ils]: https://tangentsoft.com/pidp8i/wiki?name=Incandescent+Lamp+Simulator [tfm]: https://tangentsoft.com/pidp8i/uv/doc/simh/main.pdf |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | # Getting Started with the PiDP-8/I Software ## Prerequisites * A Raspberry Pi with the 40-pin GPIO connector. That rules out the first-generation Raspberry Pi model A and B boards which had a 26-pin GPIO connector. * An SD card containing Raspbian or something sufficiently close. This software is currently tested with the Jessie Lite distribution. Ideally, you will install a fresh OS image onto an unused SD card rather than use this software to modify an existing OS installation, but there is currently no known hard incompatibilty that prevents you from integrating this software into an existing OS. * This software distribution, unpacked somewhere convenient within the Raspberry Pi filesystem. Unlike with the [upstream 2015.12.15 release][upst], this present release of the software should *not* be unpacked into `/opt/pidp8`. I recommend that you unpack it into `$HOME/src`, `/usr/local/src` or similar, but it really doesn't matter where you put it, as long as your user has full write access to that directory. * A working C compiler and other standard Linux build tools, such as `make(1)`. On Debian type systems — including Raspbian — you can install such tools with `sudo apt install build-essential` ## Configuring, Building and Installing This software distribution builds and installs in the same way as most other Linux/Unix software these days. The short-and-sweet is: $ ./configure && make && sudo make install If you've checked out a new version of the source code and the `make` step fails, try redoing the `configure` step. Sometimes changes made to the source code invalidate prior `make` dependencies, which are implicitly repaired by the `configure` script. ### Configure Script Options You can change a few things about the way the software is built and installed by giving options to the `configure` script: #### --prefix Perhaps the most widely useful `configure` script option is `--prefix`, which lets you override the default installation directory, `/opt/pidp8i`. You could make it install the software under your home directory on the Pi with this command: $ ./configure --prefix=$HOME/pidp8i && sudo make install Although this is installing to a directory your user has write access to, you still need to install via `sudo` because the installation process does other things that do require `root` access. #### --no-lamp-simulator If you build the software on a multi-core host, the PDP-8/I simulator is normally built with the [incandescent lamp simulator][ils] feature, which drives the LEDs in a way that mimics the incandescent lamps used in the original PDP-8/I. (We call this the ILS for short.) This feature currently takes too much CPU power to run on anything but a multi-core Raspberry Pi, currently limited to the Pi 2 and Pi 3 series. If you configure the software on a single-core Pi — models A+, B+, and Zero — the simulator uses the original low-CPU-usage LED driving method instead. (a.k.a. NLS for short, named after this configuration option.) Those on a multi-core host who want this low-CPU-usage LED driving method can give the `--no-lamp-simulator` option to `configure`. This method not only uses less CPU, which may be helpful if you're trying to run a lot of background tasks on your Pi 2 or Pi 3, it can also be helpful when the CPU is [heavily throttled][thro]. #### --serial-mod If you have done [Oscar's serial mod][sm1] to your PiDP-8/I PCB and the Raspberry Pi you have connected to it, add `--serial-mod` to the `configure` command above. If you do not give this flag at `configure` time with these hardware modifications in place, the front panel will not work correctly, and trying to run the software may even crash the Pi. If you give this flag and your PCBs are *not* modified, most of the hardware will work correctly, but several lights and switches will not work correctly. #### --alt-serial-mod This flag is for an [alternative serial mod by James L-W][sm2]. It doesn't require mods to the Pi, and the mods to the PiDP-8/I board are different from Oscar's. This flag changes the GPIO code to work with these modifications to the PiDP-8/I circuit design. See the linked mailing list thread for details. As with `--serial-mod`, you should only enable this flag if you have actually done the mods as specified by James L-W. #### --throttle See [`README-throttle.md`][thro] for the values this option takes. If you don't give this option, the simulator runs as fast as possible, more or less. #### --help Run `./configure --help` for more information on your options here. ## Overwriting the Local Simulator Setup When you run `sudo make install` step on a system that already has an existing installation, it purposely does not overwrite two classes of files: 1. **The binary PDP-8 media files**, such as the RK05 disk image that holds the OS/8 image the simulator boots from by default. These media image files are considered "precious" because you may have modified the OS configuration or saved personal files to the disk the OS boots from, which in turn modifies this media image file out in the host operating environment. 2. **The PDP-8 simulator configuration files**, installed as `$prefix/share/boot/*.script`, which may similarly have local changes, and thus be precious to you. Sometimes this "protect the precious" behavior isn't what you want. (Gollum!) One common reason this may be the case is that you've damaged your local configuration and want to start over. Another common case is that the newer software you're installing contains changes that you want to reflect into your local configuration. You have several options here: 1. If you just want to reflect upstream PDP-8 simulator configuration file changes into your local versions, you can hand-edit the installed simulator configuration scripts to match the changes in the newly-generated `boot/*.script` files under the build directory. 2. If the upstream change is to the binary PDP-8 media image files and you're unwilling to overwrite them wholesale, you'll have to mount both versions of the media image files under the PDP-8 simulator and copy the changes over by hand. 3. If your previously installed binary OS media images — e.g. the OS/8 RK05 disk image that the simulator boots from by default — are precious but the simulator configuration scripts aren't precious, you can just copy the generated `boot/*.script` files from the build directory into the installation directory, `$prefix/share/boot`. (See the `--prefix` option above for the meaning of `$prefix`.) 4. If neither your previously installed simulator configuration files nor the binary media images are precious, you can force the installation script to overwrite them both with a `sudo make mediainstall` command after `sudo make install`. Beware that this is potentially destructive! If you've made changes to your PDP-8 operating systems or have saved files to your OS system disks, this option will overwrite those changes! ## Testing You can test your PiDP-8/I LED and switch functions with these commands: $ sudo systemctl stop pidp8i $ pidp8i-test You may have to log out and back in before the second command will work, since the installation script modifies your normal user's `PATH` the first time you install onto a given system. It is important to stop the PiDP-8/I simulator before running the test program, since both programs need exclusive access to the LEDs and switches on the front panel. After you are done testing, you can start the PiDP-8/I simulator back up with: $ sudo systemctl start pidp8i See [its documentation][test] for more details. ## Using the Software For the most part, this software distribution works like the upstream [2015.12.15 distribution][usd]. Its [documentation][prj] therefore describes this software too, for the most part. The largest user-visible difference between the two software distributions is that all of the shell commands affecting the software were renamed to include `pidp8i` in their name: 1. To start the simulator: $ sudo systemctl start pidp8i This will happen automatically on reboot unless you disable the service, such as in order to run one of the various [forks of Deeper Thought][dt2]. 2. To attach the terminal you're working on to the simulator: $ pidp8i 3. To detach from the simulator's terminal interface while leaving the PiDP-8/I simulator running, type <kbd>Ctrl-A d</kbd>. You can re-attach to it later with a `pidp8i` command. 4. To shut the simulator down while attached to its terminal interface, type <kbd>Ctrl-E</kbd> to pause the simulator, then at the `simh>` prompt type `quit`. Type `help` at that prompt to get some idea of what else you can do with the simulator command language, or read the [SIMH Users' Guide][sdoc]. 5. To shut the simulator down from the Raspbian command line: $ sudo systemctl stop pidp8i There are [other major differences][mdif] between the upstream distribution and this one. See that linked wiki article for details. ## License Copyright © 2016-2017 by Warren Young. This document is licensed under the terms of [the SIMH license][sl]. [prj]: https://tangentsoft.com/pidp8i/ [upst]: http://obsolescence.wixsite.com/obsolescence/pidp-8 [sm1]: http://obsolescence.wixsite.com/obsolescence/2016-pidp-8-building-instructions [sm2]: https://groups.google.com/d/msg/pidp-8/-leCRMKqI1Q/Dy5RiELIFAAJ [usd]: http://obsolescence.wixsite.com/obsolescence/pidp-8-details [dt2]: https://github.com/VentureKing/Deeper-Thought-2 [sdoc]: https://tangentsoft.com/pidp8i/uv/doc/simh/main.pdf [prj]: http://obsolescence.wixsite.com/obsolescence/pidp-8 [test]: https://tangentsoft.com/pidp8i/doc/trunk/doc/pidp8i-test.md [thro]: https://tangentsoft.com/pidp8i/doc/trunk/README-throttle.md [mdif]: https://tangentsoft.com/pidp8i/wiki?name=Major+Differences [sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md [ils]: https://tangentsoft.com/pidp8i/wiki?name=Incandescent+Lamp+Simulator |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | # PiDP-8/I Software Release Process This documents the process for producing release versions of the software. ## Update ChangeLog.md Trawl the Fossil timeline for user-visible changes since the last release, and write them up in user-focused form into the `ChangeLog.md` file. If a regular user of the software cannot see a given change, it shouldn't go in the `ChangeLog.md`; let it be documented via the timeline only. ## Update the Release Branch Run `make release` to check the `ChangeLog.md` file changes in, tagging that checkin with a release version tag of the form vYYYYMMDD and merge those changes into the `release` branch. It runs entirely automatically unless an error occurs, in which case it stops immediately, so check its output for errors before continuing. ## Update the Home Page Links The zip and tarball links on the front page produce files named after the date of the release. Those dates need to be updated immediately after tagging the release, since they point at the "release" tag applied by the previous step, so they begin shipping the new release immediately after tagging it. ## Produce the Normal Binary OS Image Start with the latest version of [Raspbian Lite][os] on a multi-core Raspberry Pi. 1. If the version of the base OS has changed since the last binary OS image was created, download the new one. While the OS is downloading, zero the SD card you're going to use for this, so the prior contents don't affect this process. Blast the base OS image onto the cleaned SD card. 2. Boot it up on a multi-core Pi. Log in, then retreive and initialize BOSI: $ wget https://tangentsoft.com/bosi $ chmod +x bosi $ exec sudo ./bosi init The `exec` bit is required so that the `bosi` invocation is run as root without any processes running as `pi` in case the `init` step sees that user `pi` hasn't been changed to `pidp8i` here: the `usermod` command we give to make that change will refuse to do what we ask if there are any running processes owned by user `pi`. It will either reboot the system after completing its tasks successfully or exit early, giving the reason it failed. 3. Clone the software repo and build the softare: $ ./bosi build On reboot, say `top -H` to make sure the software is running and that the CPU percentages are reasonable for the platform. You may also want to check that it is running properly with a `pidp8i` command. Is the configuration line printed by the simulator correct? Does OS/8 run? Are there any complaints from SIMH, such as about insufficient CPU power? 4. Do final inside-the-image steps: $ ./bosi prepare 5. Move the SD card to a USB reader plugged into the Pi, boot the Pi from its prior SD card, and shrink the OS image: $ wget https://tangentsoft.com/bosi $ chmod +x bosi $ ./bosi shrink 6. Move the USB reader to the Mac,¹ then say: $ bosi image [nls] For the ILS images, you can give "ils" as a parameter or leave it blank. 7. The prior step rewrote the SD card with the image file it created. Boot it up and make sure it still works. If you're happy with it, give this command *on the desktop PC*. $ bosi finish [nls] As above, the parameter can be "ils" or left off for the ILS images. [os]: https://www.raspberrypi.org/downloads/raspbian/ ## Produce the "No Lamp Simulator" Binary OS Image Do the same series of steps above on a single-core Raspberry Pi, except that you give "nls" parameters to the `image` and `finish` steps. ## Publicizing While the NLS image uploads — the ILS image was already sent in step 7 in the first pass through the list above — compose the announcement message, and modify the front page to point to the new images. You might also need to update the approximate image sizes reported on that page. Post the announcement message and new front page once that second upload completes. ---------------------- ### Footnotes 1. The image production steps could just as well be done on a Linux box or on a Windows box via Cygwin or WSL, but the commands in that final stage change due to OS differences. Since this document exists primarily for use by the one who uses it, there is little point in having alternatives for other desktop OSes above. Should someone else take over maintainership, they can translate the above commands for their own desktop PC. ### License Copyright © 2016-2017 by Warren Young. This document is licensed under the terms of [the SIMH license][sl]. [sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md |
> > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | Copyright © 2015-2017 by various authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the names of the authors above shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from those authors. |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | / asr33-rim-loader.pal / / Load paper tapes in RIM format from a Teletype Model 33 ASR's paper / tape reader. By contrast with the loader in hs-rim-loader.pal, this / is the low-speed paper tape RIM loader. / / This is the RIM loader printed on the front panel of the PDP-8/I. The / RIM loader in hs-rim-loader.pal (which is translated to boot/1.script / at build time) is similar to this one, but it works on the DEC high- / speed paper tape reader peripheral, which is where the PiDP-8/I's / automatic paper tape mounting feature attaches any tape images it / finds via USB. / / Therefore, you cannot use this RIM loader if you want to use the / PiDP-8/I's automatic media attachment mechanism. It is included / here mainly for documentation at the moment, but also in case / someone works out a way to build the simulator so that it can / conditionally load tapes from an emulated ASR-33. / / Raw disassembly done from the octal values by Bernhard Baehr's PDP-8/E / Simulator. Comments and labels by Warren Young. Original copyright / by Digital Equipment Corporation: this program appeared in DEC manuals / and was printed on the front panel of every PDP-8/I. / / SIMH: echo Installing the RIM loader for the ASR 33 paper tape reader... / SIMH: set df disabled *7755 HLT / nonstandard: auto-halt on SIMH startup / normal RIM loader entry point, 7756 NEXT, KCC / clear PTR flag RBYTE1, KSF / loop until PTR is ready JMP RBYTE1 KRB / read first byte in CLL RTL / shift it left by 2, clearing link as well RTL / and 2 more again SPA / if top bit of AC is set... JMP RBYTE1 / ...AC contains the addr's value RTL / ...else rotate it another 2 positions RBYTE2, KSF / wait for next character JMP RBYTE2 KRS / read second byte in SNL / if link is set... DCA I BYTE / ...it's the value's address GOTVAL, DCA BYTE / ...else it's the value at that addr JMP NEXT / go round again, getting next value from PTR BYTE, 0 $ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | / hs-rim-loader.pal / / Load paper tapes in RIM format from the DEC high-speed PTR. / / This routine differs from that printed in DEC's manuals in that it / starts with a HLT instruction so that when you [re]start SIMH with / IF=1, running this program, the processor auto-halts, giving the user / the opportunity to attach a paper tape via DF or ATTACH, then start / the processor at 7756 as normal. / / The RIM loader code printed on the front panel of the PDP-8/I differs / because it is for the the paper tape reader built into a Teletype / Model 33 ASR. See asr33-rim-loader.pal for that other implementation, / including more information about it. / / Raw disassembly done from the octal values by Bernhard Baehr's PDP-8/E / Simulator. Comments and labels by Warren Young. Original copyright / by Digital Equipment Corporation: this program appeared in many DEC / manuals printed throughout the PDP-8 era variants of which were made / (and thus documented) from 1965 to 1979. / / SIMH: echo Installing the RIM loader for the DEC high-speed tape reader... / SIMH: set df disabled / SIMH: set cpu noidle *7755 HLT / nonstandard: auto-halt on SIMH startup / normal RIM loader entry point, 7756 RFC / clear PTR flag RBYTE1, RSF / loop until PTR is ready JMP RBYTE1 RCC / read first byte in CLL RTL / shift it left by 2, clearing link as well RTL / and 2 more again SPA / if top bit of AC is set... JMP GOTVAL / ...AC contains the addr's value RTL / ...else rotate it another 2 positions RBYTE2, RSF / wait for next character JMP RBYTE2 RCC / read second byte in SNL / if link is set... DCA I BYTE / ...it's the value's address GOTVAL, DCA BYTE / ...else it's the value at that addr JMP RBYTE1 / go round again, getting next value from PTR BYTE, 0 $ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | ######################################################################## # auto.def - Configure file for the PiDP-8/I software build system, # based on autosetup. # # Copyright © 2016-2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## define defaultprefix /opt/pidp8i use cc use cc-lib options { debug-mode => "create a debug build (default is release)" no-lamp-simulator => "use simple LED driver instead of incandescent lamp simulator" serial-mod => "use GPIO drive scheme suitable for Oscar Vermeulen's serial mod method" alt-serial-mod => "use GPIO drive scheme suitable for James L-W's serial mod method" throttle: => "override the throttle values in the boot scripts" } if {[opt-bool alt-serial-mod]} { msg-result "GPIO drive adjusted for James L-W's serial mods to the PiDP-8/I PCB." define PCB_SERIAL_MOD_JLW define PCB_SERIAL_MOD_ANY } if {[opt-bool serial-mod]} { msg-result "GPIO drive adjusted for O. Vermeulen's serial mods to the Pi & PiDP-8/I PCBs." define PCB_SERIAL_MOD_OV define PCB_SERIAL_MOD_ANY } if {[opt-bool debug-mode]} { msg-result "Creating a debuggable build." define BUILDMODE {-O0 -g} } else { msg-result "Creating a release build." define BUILDMODE {-O2} } # High-level definitions set builddir [get-define builddir] set srcdir [get-define srcdir] set cores [exec $srcdir/tools/corecount] # Translate --throttle value to a SIMH command set tv [opt-val throttle] set tvsl [string length $tv] if {($tvsl == 0 && $cores > 1) || $tv == "none"} { define SET_THROTTLE {set nothrottle} set tv "unlimited" } else { # Rewrite symbolic values with values SIMH can understand. See # README-throttle.md for the justification of these values. if {$tv == "single-core" || $tvsl == 0} { # It's a single-core Pi board, so just tell SIMH to take half # the host CPU power, leaving the rest left for background # tasks. We can't use an IPS value here for several reasons. # See README-throttle.md for details. set tv "50%" } elseif {$tv == "pdp8e"} { set tv "416k" } elseif {$tv == "pdp8i" || $tv == "pdp8a"} { set tv "333k" } elseif {$tv == "pdp8l" || $tv == "pdp8"} { set tv "313k" } elseif {$tv == "ha6120"} { set tv "182k" } elseif {$tv == "im6100a"} { set tv "200k" } elseif {$tv == "im6100"} { set tv "100k" } elseif {$tv == "im6100c"} { set tv "83k" } elseif {$tv == "pdp8s"} { set tv "63k" } elseif {$tv == "human"} { set tv "1/100" } elseif {$tv == "trace"} { set tv "1/1000" } # else, assume --throttle was given a legal SIMH throttle value if {[string first "/" $tv] > -1} { # Assume the ratio given will push us below 1 kIPS, where ILS # fails badly because of the simulator's sleeping behavior, so # disable the ILS feature if we were going to build it. set cores 1 } define SET_THROTTLE "set throttle $tv" } msg-result "Simulator CPU throttle set to $tv" # Swap the incandescent lamp simulator feature out for the original LED # driving method on single-core hosts. The user can force this on # multi-core hosts via --no-lamp-simulator. if {($cores < 2) || [opt-bool no-lamp-simulator]} { msg-result "Driving PiDP-8/I front panel LEDs using low-CPU-usage method." define LED_DRIVER_MODULE n define ILS_MODE 0 } else { msg-result "Driving PiDP-8/I front panel LEDs using incandescent lamp simulator." define LED_DRIVER_MODULE i define ILS_MODE 1 } # Check for headers, functions, etc. whose absence we can work around cc-check-includes time.h cc-check-function-in-lib clock_gettime rt cc-check-functions clock_nanosleep nanosleep usleep cc-check-functions sched_yield # Ensure we have the libncurses development files installed here, else # pidp8i-test won't build. if {![cc-check-includes curses.h]} { user-error "Could not find curses.h. Try installing libncurses-dev." } elseif {![cc-check-function-in-lib initscr ncurses]} { user-error "Could not find initscr() in libncurses." } # We need to find an install(1) type program that supports -D. The # Raspberry Pi OSes typically used with the PiDB-8/I board do have this, # but this package also runs on non-Linux OSes (e.g. for testing on a # desktop Mac) so make sure we've got a suitable implementation. The # ginstall name is typical on non-Linux systems where GNU Coreutils was # installed alongside the core OS utilities. if {[cc-check-progs ginstall]} { define INSTALL ginstall } elseif {[cc-check-progs install]} { if {[catch {exec install -D -d . >& /dev/null} result] == 0} { define INSTALL install } else { user-error "install(1) does not support -D; install GNU Coreutils." } } else { user-error "No install(1) type program found; install GNU Coreutils." } msg-result "Found GNU install(1) program as [get-define INSTALL]." # Also find GNU readlink in the same way if {[cc-check-progs greadlink]} { set rlprg greadlink } elseif {[cc-check-progs readlink]} { if {[catch {exec readlink -f . >& /dev/null} result] == 0} { set rlprg readlink } else { user-error "readlink(1) does not support -D; install GNU Coreutils." } } else { user-error "No readlink(1) type program found; install GNU Coreutils." } msg-result "Found GNU readlink(1) as $rlprg." # If we have cscope here, we'll use it in the "tags" target define HAVE_PROG_CSCOPE [cc-check-progs cscope] # Canonicalize some paths which may be relative and generate others from them define ABSPREFIX [exec $rlprg -f [get-define prefix]] define BOOTDIR "[get-define ABSPREFIX]/share/boot" define MEDIADIR "[get-define ABSPREFIX]/share/media" # Remember the name and primary group of the user who installed this, since # we want to give that group write privileges to some files when they're # installed, and we want them to own the screen(1) session. set instgrp [exec id -grn] set instusr [exec id -urn] if {$instusr == "root"} { msg-result "Error: This software will not install and run as root." user-error "Reconfigure without sudo!" } define INSTGRP $instgrp define INSTUSR $instusr msg-result "Install group for user-writeable files will be $instgrp." msg-result "Owner of screen(1) session will be $instusr." # Can we use any nonstandard flags here? We don't bother including # flags that both GCC and Clang support. The ones inside the "if" # block are those that Clang will accept in an autosetup test but # then will yell about if you try to use them. The test checks for # an -f sub-option that Clang doesn't currently support even enough # to fool autosetup. cc-check-standards c99 if {![opt-bool debug-mode]} { cc-check-flags -fipa-cp-clone cc-check-flags -fno-strict-overflow cc-check-flags -fpredictive-commoning if ([get-define HAVE_CFLAG_FIPA_CP_CLONE]) { cc-check-flags -fgcse-after-reload cc-check-flags -finline-functions cc-check-flags -fno-unsafe-loop-optimizations } } # Embed this software's Fossil-based version string into gpio-common.c. # Fail hard if we can't get this version string because all supported # configurations require Fossil and work from a Fossil checkout. Don't # fall back on some lame "UNKNOWN" version string because that would # mask a real problem that needs to be diagnosed. set tool "tools/version" set cmd "$srcdir/$tool" set status [catch {exec $cmd} version] if {$status != 0} { # The most likely cause for tools/version to fail is that the repo # file has become disassociated from the local checkout directory. set sql "select value from vvar where name=\"repository\"" set cmd "fossil sql --no-repository $srcdir/.fslckout '$sql'" set status [catch {exec /bin/sh -c $cmd} path] if {$status != 0} { user-error "Fossil doesn't seem to work here. Is it installed?\nCMD: $cmd" } elseif {[file exists $path]} { user-error "$tool failed to get checkout version from $path" } else { user-error "$tool failed: $path does not exist." } } define VERSION $version # Build Deeper Thought if we find it here if {[file exists "[get-define srcdir]/src/deeper.c"]} { set ls [string toupper "[get-define LED_DRIVER_MODULE]ls"] msg-result "Found Deeper Thought; building it against $ls GPIO module" define BUILD_DEEPER_THOUGHT 1 } # Write outputs. # # NOTE: If you change the list of files here, change INFILES in # Makefile.in, too. make-config-header src/config.h \ -auto {ENABLE_* HAVE_* PACKAGE_* SIZEOF_*} \ -bare {ILS_MODE PCB_*} make-template Makefile.in make-template bin/pidp8i.in make-template boot/0.script.in make-template boot/2.script.in make-template boot/3.script.in make-template boot/4.script.in make-template boot/6.script.in make-template boot/7.script.in make-template etc/pidp8i-init.in make-template etc/sudoers.in make-template examples/Makefile.in make-template src/Makefile.in make-template src/gpio-common.c.in make-template src/PDP8/Makefile.in make-template src/PDP8/pidp8i.c.in make-template tools/simh-update.in exec chmod +x "$builddir/tools/simh-update" |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | Unless explicitly stated, all files which form part of autosetup are released under the following license: --------------------------------------------------------------------- autosetup - A build environment "autoconfigurator" Copyright (c) 2010-2011, WorkWare Systems <http://workware.net.au/> Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE WORKWARE SYSTEMS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WORKWARE SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of WorkWare Systems. |
> | 1 | This is autosetup v0.6.6. See http://msteveb.github.com/autosetup/ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 | #!/bin/sh # Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ # All rights reserved # vim:se syntax=tcl: # \ dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@" set autosetup(version) 0.6.6 # Can be set to 1 to debug early-init problems set autosetup(debug) 0 ################################################################## # # Main flow of control, option handling # proc main {argv} { global autosetup define # There are 3 potential directories involved: # 1. The directory containing autosetup (this script) # 2. The directory containing auto.def # 3. The current directory # From this we need to determine: # a. The path to this script (and related support files) # b. The path to auto.def # c. The build directory, where output files are created # This is also complicated by the fact that autosetup may # have been run via the configure wrapper ([getenv WRAPPER] is set) # Here are the rules. # a. This script is $::argv0 # => dir, prog, exe, libdir # b. auto.def is in the directory containing the configure wrapper, # otherwise it is in the current directory. # => srcdir, autodef # c. The build directory is the current directory # => builddir, [pwd] # 'misc' is needed before we can do anything, so set a temporary libdir # in case this is the development version set autosetup(libdir) [file dirname $::argv0]/lib use misc # (a) set autosetup(dir) [realdir [file dirname [realpath $::argv0]]] set autosetup(prog) [file join $autosetup(dir) [file tail $::argv0]] set autosetup(exe) [getenv WRAPPER $autosetup(prog)] if {$autosetup(installed)} { set autosetup(libdir) $autosetup(dir) } else { set autosetup(libdir) [file join $autosetup(dir) lib] } autosetup_add_dep $autosetup(prog) # (b) if {[getenv WRAPPER ""] eq ""} { # Invoked directly set autosetup(srcdir) [pwd] } else { # Invoked via the configure wrapper set autosetup(srcdir) [file-normalize [file dirname $autosetup(exe)]] } set autosetup(autodef) [relative-path $autosetup(srcdir)/auto.def] # (c) set autosetup(builddir) [pwd] set autosetup(argv) $argv set autosetup(cmdline) {} # options is a list of known options set autosetup(options) {} # optset is a dictionary of option values set by the user based on getopt set autosetup(optset) {} # optdefault is a dictionary of default values for options set autosetup(optdefault) {} set autosetup(optionhelp) {} set autosetup(showhelp) 0 # Parse options use getopt # At the is point we don't know what is a valid option # We simply parse anything that looks like an option set autosetup(getopt) [getopt argv] #"=Core Options:" options-add { help:=local => "display help and options. Optionally specify a module name, such as --help=system" version => "display the version of autosetup" ref:=text manual:=text reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'" debug => "display debugging output as autosetup runs" install:=. => "install autosetup to the current or given directory (in the 'autosetup/' subdirectory)" force init:=help => "create initial auto.def, etc. Use --init=help for known types" # Undocumented options option-checking=1 nopager quiet timing conf: } if {[opt-bool version]} { puts $autosetup(version) exit 0 } # autosetup --conf=alternate-auto.def if {[opt-val conf] ne ""} { set autosetup(autodef) [opt-val conf] } # Debugging output (set this early) incr autosetup(debug) [opt-bool debug] incr autosetup(force) [opt-bool force] incr autosetup(msg-quiet) [opt-bool quiet] incr autosetup(msg-timing) [opt-bool timing] # If the local module exists, source it now to allow for # project-local customisations if {[file exists $autosetup(libdir)/local.tcl]} { use local } # Now any auto-load modules foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] { automf_load source $file } if {[opt-val help] ne ""} { incr autosetup(showhelp) use help autosetup_help [opt-val help] } if {[opt-val {manual ref reference}] ne ""} { use help autosetup_reference [opt-val {manual ref reference}] } # Allow combining --install and --init set earlyexit 0 if {[opt-val install] ne ""} { use install autosetup_install [opt-val install] incr earlyexit } if {[opt-val init] ne ""} { use init autosetup_init [opt-val init] incr earlyexit } if {$earlyexit} { exit 0 } if {![file exists $autosetup(autodef)]} { # Check for invalid option first options {} user-error "No auto.def found in \"$autosetup(srcdir)\" (use [file tail $::autosetup(exe)] --init to create one)" } # Parse extra arguments into autosetup(cmdline) foreach arg $argv { if {[regexp {([^=]*)=(.*)} $arg -> n v]} { dict set autosetup(cmdline) $n $v define $n $v } else { user-error "Unexpected parameter: $arg" } } autosetup_add_dep $autosetup(autodef) define CONFIGURE_OPTS "" foreach arg $autosetup(argv) { define-append CONFIGURE_OPTS [quote-if-needed $arg] } define AUTOREMAKE [file-normalize $autosetup(exe)] define-append AUTOREMAKE [get-define CONFIGURE_OPTS] # Log how we were invoked configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]" # Note that auto.def is *not* loaded in the global scope source $autosetup(autodef) # Could warn here if options {} was not specified show-notices if {$autosetup(debug)} { msg-result "Writing all defines to config.log" configlog "================ defines ======================" foreach n [lsort [array names define]] { configlog "define $n $define($n)" } } exit 0 } # @opt-bool ?-nodefault? option ... # # Check each of the named, boolean options and if any have been explicitly enabled # or disabled by the user, return 1 or 0 accordingly. # # If the option was specified more than once, the last value wins. # e.g. With --enable-foo --disable-foo, [opt-bool foo] will return 0 # # If no value was specified by the user, returns the default value for the # first option. If -nodefault is given, this behaviour changes and # -1 is returned instead. # proc opt-bool {args} { set nodefault 0 if {[lindex $args 0] eq "-nodefault"} { set nodefault 1 set args [lrange $args 1 end] } option-check-names {*}$args foreach opt $args { if {[dict exists $::autosetup(optset) $opt]} { return [dict get $::autosetup(optset) $opt] } } if {$nodefault} { return -1 } # Default value is the default for the first option return [dict get $::autosetup(optdefault) [lindex $args 0]] } # @opt-val option-list ?default=""? # # Returns a list containing all the values given for the non-boolean options in 'option-list'. # There will be one entry in the list for each option given by the user, including if the # same option was used multiple times. # If only a single value is required, use something like: # ## lindex [opt-val $names] end # # If no options were set, $default is returned (exactly, not as a list). # proc opt-val {names {default ""}} { option-check-names {*}$names foreach opt $names { if {[dict exists $::autosetup(optset) $opt]} { lappend result {*}[dict get $::autosetup(optset) $opt] } } if {[info exists result]} { return $result } return $default } proc option-check-names {args} { foreach o $args { if {$o ni $::autosetup(options)} { autosetup-error "Request for undeclared option --$o" } } } # Parse the option definition in $opts and update # ::autosetup(setoptions) and ::autosetup(optionhelp) appropriately # proc options-add {opts {header ""}} { global autosetup # First weed out comment lines set realopts {} foreach line [split $opts \n] { if {![string match "#*" [string trimleft $line]]} { append realopts $line \n } } set opts $realopts for {set i 0} {$i < [llength $opts]} {incr i} { set opt [lindex $opts $i] if {[string match =* $opt]} { # This is a special heading lappend autosetup(optionhelp) $opt "" set header {} continue } #puts "i=$i, opt=$opt" regexp {^([^:=]*)(:)?(=)?(.*)$} $opt -> name colon equal value if {$name in $autosetup(options)} { autosetup-error "Option $name already specified" } #puts "$opt => $name $colon $equal $value" # Find the corresponding value in the user options # and set the default if necessary if {[string match "-*" $opt]} { # This is a documentation-only option, like "-C <dir>" set opthelp $opt } elseif {$colon eq ""} { # Boolean option lappend autosetup(options) $name if {$value eq "1"} { set opthelp "--disable-$name" } else { set opthelp "--$name" } # Set the default if {$value eq ""} { set value 0 } dict set autosetup(optdefault) $name $value if {[dict exists $autosetup(getopt) $name]} { # The option was specified by the user. Look at the last value. lassign [lindex [dict get $autosetup(getopt) $name] end] type setvalue if {$type eq "str"} { # Can we convert the value to a boolean? if {$setvalue in {1 enabled yes}} { set setvalue 1 } elseif {$setvalue in {0 disabled no}} { set setvalue 0 } else { user-error "Boolean option $name given as --$name=$setvalue" } } dict set autosetup(optset) $name $setvalue #puts "Found boolean option --$name=$setvalue" } } else { # String option. lappend autosetup(options) $name if {$equal eq "="} { # String option with optional value set opthelp "--$name?=$value?" } else { # String option with required value set opthelp "--$name=$value" } dict set autosetup(optdefault) $name $value # Get the values specified by the user if {[dict exists $autosetup(getopt) $name]} { set listvalue {} foreach pair [dict get $autosetup(getopt) $name] { lassign $pair type setvalue if {$type eq "bool" && $setvalue} { if {$equal ne "="} { user-error "Option --$name requires a value" } # If given as a boolean, use the default value set setvalue $value } lappend listvalue $setvalue } #puts "Found string option --$name=$listvalue" dict set autosetup(optset) $name $listvalue } } # Now create the help for this option if appropriate if {[lindex $opts $i+1] eq "=>"} { set desc [lindex $opts $i+2] #string match \n* $desc if {$header ne ""} { lappend autosetup(optionhelp) $header "" set header "" } # A multi-line description lappend autosetup(optionhelp) $opthelp $desc incr i 2 } } } # @module-options optionlist # # Like 'options', but used within a module. proc module-options {opts} { set header "" if {$::autosetup(showhelp) > 1 && [llength $opts]} { set header "Module Options:" } options-add $opts $header if {$::autosetup(showhelp)} { # Ensure that the module isn't executed on --help # We are running under eval or source, so use break # to prevent further execution #return -code break -level 2 return -code break } } proc max {a b} { expr {$a > $b ? $a : $b} } proc options-wrap-desc {text length firstprefix nextprefix initial} { set len $initial set space $firstprefix foreach word [split $text] { set word [string trim $word] if {$word == ""} { continue } if {$len && [string length $space$word] + $len >= $length} { puts "" set len 0 set space $nextprefix } incr len [string length $space$word] puts -nonewline $space$word set space " " } if {$len} { puts "" } } proc options-show {} { # Determine the max option width set max 0 foreach {opt desc} $::autosetup(optionhelp) { if {[string match =* $opt] || [string match \n* $desc]} { continue } set max [max $max [string length $opt]] } set indent [string repeat " " [expr $max+4]] set cols [getenv COLUMNS 80] catch { lassign [exec stty size] rows cols } incr cols -1 # Now output foreach {opt desc} $::autosetup(optionhelp) { if {[string match =* $opt]} { puts [string range $opt 1 end] continue } puts -nonewline " [format %-${max}s $opt]" if {[string match \n* $desc]} { puts $desc } else { options-wrap-desc [string trim $desc] $cols " " $indent [expr $max + 2] } } } # @options options-spec # # Specifies configuration-time options which may be selected by the user # and checked with opt-val and opt-bool. The format of options-spec follows. # # A boolean option is of the form: # ## name[=0|1] => "Description of this boolean option" # # The default is name=0, meaning that the option is disabled by default. # If name=1 is used to make the option enabled by default, the description should reflect # that with text like "Disable support for ...". # # An argument option (one which takes a parameter) is of the form: # ## name:[=]value => "Description of this option" # # If the name:value form is used, the value must be provided with the option (as --name=myvalue). # If the name:=value form is used, the value is optional and the given value is used as the default # if it is not provided. # # Undocumented options are also supported by omitting the "=> description. # These options are not displayed with --help and can be useful for internal options or as aliases. # # For example, --disable-lfs is an alias for --disable=largefile: # ## lfs=1 largefile=1 => "Disable large file support" # proc options {optlist} { # Allow options as a list or args options-add $optlist "Local Options:" if {$::autosetup(showhelp)} { options-show exit 0 } # Check for invalid options if {[opt-bool option-checking]} { foreach o [dict keys $::autosetup(getopt)] { if {$o ni $::autosetup(options)} { user-error "Unknown option --$o" } } } } proc config_guess {} { if {[file-isexec $::autosetup(dir)/config.guess]} { exec-with-stderr sh $::autosetup(dir)/config.guess if {[catch {exec-with-stderr sh $::autosetup(dir)/config.guess} alias]} { user-error $alias } return $alias } else { configlog "No config.guess, so using uname" string tolower [exec uname -p]-unknown-[exec uname -s][exec uname -r] } } proc config_sub {alias} { if {[file-isexec $::autosetup(dir)/config.sub]} { if {[catch {exec-with-stderr sh $::autosetup(dir)/config.sub $alias} alias]} { user-error $alias } } return $alias } # @define name ?value=1? # # Defines the named variable to the given value. # These (name, value) pairs represent the results of the configuration check # and are available to be checked, modified and substituted. # proc define {name {value 1}} { set ::define($name) $value #dputs "$name <= $value" } # @undefine name # # Undefine the named variable # proc undefine {name} { unset -nocomplain ::define($name) #dputs "$name <= <undef>" } # @define-append name value ... # # Appends the given value(s) to the given 'defined' variable. # If the variable is not defined or empty, it is set to $value. # Otherwise the value is appended, separated by a space. # Any extra values are similarly appended. # If any value is already contained in the variable (as a substring) it is omitted. # proc define-append {name args} { if {[get-define $name ""] ne ""} { # Make a token attempt to avoid duplicates foreach arg $args { if {[string first $arg $::define($name)] == -1} { append ::define($name) " " $arg } } } else { set ::define($name) [join $args] } #dputs "$name += [join $args] => $::define($name)" } # @get-define name ?default=0? # # Returns the current value of the 'defined' variable, or $default # if not set. # proc get-define {name {default 0}} { if {[info exists ::define($name)]} { #dputs "$name => $::define($name)" return $::define($name) } #dputs "$name => $default" return $default } # @is-defined name # # Returns 1 if the given variable is defined. # proc is-defined {name} { info exists ::define($name) } # @all-defines # # Returns a dictionary (name value list) of all defined variables. # # This is suitable for use with 'dict', 'array set' or 'foreach' # and allows for arbitrary processing of the defined variables. # proc all-defines {} { array get ::define } # @get-env name default # # If $name was specified on the command line, return it. # If $name was set in the environment, return it. # Otherwise return $default. # proc get-env {name default} { if {[dict exists $::autosetup(cmdline) $name]} { return [dict get $::autosetup(cmdline) $name] } getenv $name $default } # @env-is-set name # # Returns 1 if the $name was specified on the command line or in the environment. # Note that an empty environment variable is not considered to be set. # proc env-is-set {name} { if {[dict exists $::autosetup(cmdline) $name]} { return 1 } if {[getenv $name ""] ne ""} { return 1 } return 0 } # @readfile filename ?default=""? # # Return the contents of the file, without the trailing newline. # If the file doesn't exist or can't be read, returns $default. # proc readfile {filename {default_value ""}} { set result $default_value catch { set f [open $filename] set result [read -nonewline $f] close $f } return $result } # @writefile filename value # # Creates the given file containing $value. # Does not add an extra newline. # proc writefile {filename value} { set f [open $filename w] puts -nonewline $f $value close $f } proc quote-if-needed {str} { if {[string match {*[\" ]*} $str]} { return \"[string map [list \" \\" \\ \\\\] $str]\" } return $str } proc quote-argv {argv} { set args {} foreach arg $argv { lappend args [quote-if-needed $arg] } join $args } # @suffix suf list # # Takes a list and returns a new list with $suf appended # to each element # ## suffix .c {a b c} => {a.c b.c c.c} # proc suffix {suf list} { set result {} foreach p $list { lappend result $p$suf } return $result } # @prefix pre list # # Takes a list and returns a new list with $pre prepended # to each element # ## prefix jim- {a.c b.c} => {jim-a.c jim-b.c} # proc prefix {pre list} { set result {} foreach p $list { lappend result $pre$p } return $result } # @find-executable name # # Searches the path for an executable with the given name. # Note that the name may include some parameters, e.g. "cc -mbig-endian", # in which case the parameters are ignored. # Returns 1 if found, or 0 if not. # proc find-executable {name} { # Ignore any parameters set name [lindex $name 0] if {$name eq ""} { # The empty string is never a valid executable return 0 } foreach p [split-path] { dputs "Looking for $name in $p" set exec [file join $p $name] if {[file-isexec $exec]} { dputs "Found $name -> $exec" return 1 } } return 0 } # @find-an-executable ?-required? name ... # # Given a list of possible executable names, # searches for one of these on the path. # # Returns the name found, or "" if none found. # If the first parameter is '-required', an error is generated # if no executable is found. # proc find-an-executable {args} { set required 0 if {[lindex $args 0] eq "-required"} { set args [lrange $args 1 end] incr required } foreach name $args { if {[find-executable $name]} { return $name } } if {$required} { if {[llength $args] == 1} { user-error "failed to find: [join $args]" } else { user-error "failed to find one of: [join $args]" } } return "" } # @configlog msg # # Writes the given message to the configuration log, config.log # proc configlog {msg} { if {![info exists ::autosetup(logfh)]} { set ::autosetup(logfh) [open config.log w] } puts $::autosetup(logfh) $msg } # @msg-checking msg # # Writes the message with no newline to stdout. # proc msg-checking {msg} { if {$::autosetup(msg-quiet) == 0} { maybe-show-timestamp puts -nonewline $msg set ::autosetup(msg-checking) 1 } } # @msg-result msg # # Writes the message to stdout. # proc msg-result {msg} { if {$::autosetup(msg-quiet) == 0} { maybe-show-timestamp puts $msg set ::autosetup(msg-checking) 0 show-notices } } # @msg-quiet command ... # # msg-quiet evaluates it's arguments as a command with output # from msg-checking and msg-result suppressed. # # This is useful if a check needs to run a subcheck which isn't # of interest to the user. proc msg-quiet {args} { incr ::autosetup(msg-quiet) set rc [uplevel 1 $args] incr ::autosetup(msg-quiet) -1 return $rc } # Will be overridden by 'use misc' proc error-stacktrace {msg} { return $msg } proc error-location {msg} { return $msg } ################################################################## # # Debugging output # proc dputs {msg} { if {$::autosetup(debug)} { puts $msg } } ################################################################## # # User and system warnings and errors # # Usage errors such as wrong command line options # @user-error msg # # Indicate incorrect usage to the user, including if required components # or features are not found. # autosetup exits with a non-zero return code. # proc user-error {msg} { show-notices puts stderr "Error: $msg" puts stderr "Try: '[file tail $::autosetup(exe)] --help' for options" exit 1 } # @user-notice msg # # Output the given message to stderr. # proc user-notice {msg} { lappend ::autosetup(notices) $msg } # Incorrect usage in the auto.def file. Identify the location. proc autosetup-error {msg} { autosetup-full-error [error-location $msg] } # Like autosetup-error, except $msg is the full error message. proc autosetup-full-error {msg} { show-notices puts stderr $msg exit 1 } proc show-notices {} { if {$::autosetup(msg-checking)} { puts "" set ::autosetup(msg-checking) 0 } flush stdout if {[info exists ::autosetup(notices)]} { puts stderr [join $::autosetup(notices) \n] unset ::autosetup(notices) } } proc maybe-show-timestamp {} { if {$::autosetup(msg-timing) && $::autosetup(msg-checking) == 0} { puts -nonewline [format {[%6.2f] } [expr {([clock millis] - $::autosetup(start)) % 10000 / 1000.0}]] } } proc autosetup_version {} { return "autosetup v$::autosetup(version)" } ################################################################## # # Directory/path handling # proc realdir {dir} { set oldpwd [pwd] cd $dir set pwd [pwd] cd $oldpwd return $pwd } # Follow symlinks until we get to something which is not a symlink proc realpath {path} { while {1} { if {[catch { set path [file readlink $path] }]} { # Not a link break } } return $path } # Convert absolute path, $path into a path relative # to the given directory (or the current dir, if not given). # proc relative-path {path {pwd {}}} { set diff 0 set same 0 set newf {} set prefix {} set path [file-normalize $path] if {$pwd eq ""} { set pwd [pwd] } else { set pwd [file-normalize $pwd] } if {$path eq $pwd} { return . } # Try to make the filename relative to the current dir foreach p [split $pwd /] f [split $path /] { if {$p ne $f} { incr diff } elseif {!$diff} { incr same } if {$diff} { if {$p ne ""} { # Add .. for sibling or parent dir lappend prefix .. } if {$f ne ""} { lappend newf $f } } } if {$same == 1 || [llength $prefix] > 3} { return $path } file join [join $prefix /] [join $newf /] } # Add filename as a dependency to rerun autosetup # The name will be normalised (converted to a full path) # proc autosetup_add_dep {filename} { lappend ::autosetup(deps) [file-normalize $filename] } ################################################################## # # Library module support # # @use module ... # # Load the given library modules. # e.g. 'use cc cc-shared' # # Note that module 'X' is implemented in either 'autosetup/X.tcl' # or 'autosetup/X/init.tcl' # # The latter form is useful for a complex module which requires additional # support file. In this form, '$::usedir' is set to the module directory # when it is loaded. # proc use {args} { foreach m $args { if {[info exists ::libmodule($m)]} { continue } set ::libmodule($m) 1 if {[info exists ::modsource($m)]} { automf_load eval $::modsource($m) } else { set sources [list $::autosetup(libdir)/${m}.tcl $::autosetup(libdir)/${m}/init.tcl] set found 0 foreach source $sources { if {[file exists $source]} { incr found break } } if {$found} { # For the convenience of the "use" source, point to the directory # it is being loaded from set ::usedir [file dirname $source] automf_load source $source autosetup_add_dep $source } else { autosetup-error "use: No such module: $m" } } } } # Load module source in the global scope by executing the given command proc automf_load {args} { if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} { autosetup-full-error [error-dump $msg $opts $::autosetup(debug)] } } # Initial settings set autosetup(exe) $::argv0 set autosetup(istcl) 1 set autosetup(start) [clock millis] set autosetup(installed) 0 set autosetup(msg-checking) 0 set autosetup(msg-quiet) 0 # Embedded modules are inserted below here set autosetup(installed) 1 # ----- module asciidoc-formatting ----- set modsource(asciidoc-formatting) { # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ # All rights reserved # Module which provides text formatting # asciidoc format use formatting proc para {text} { regsub -all "\[ \t\n\]+" [string trim $text] " " } proc title {text} { underline [para $text] = nl } proc p {text} { puts [para $text] nl } proc code {text} { foreach line [parse_code_block $text] { puts " $line" } nl } proc codelines {lines} { foreach line $lines { puts " $line" } nl } proc nl {} { puts "" } proc underline {text char} { regexp "^(\[ \t\]*)(.*)" $text -> indent words puts $text puts $indent[string repeat $char [string length $words]] } proc section {text} { underline "[para $text]" - nl } proc subsection {text} { underline "$text" ~ nl } proc bullet {text} { puts "* [para $text]" } proc indent {text} { puts " :: " puts [para $text] } proc defn {first args} { set sep "" if {$first ne ""} { puts "${first}::" } else { puts " :: " } set defn [string trim [join $args \n]] regsub -all "\n\n" $defn "\n ::\n" defn puts $defn } } # ----- module formatting ----- set modsource(formatting) { # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ # All rights reserved # Module which provides common text formatting # This is designed for documenation which looks like: # code {...} # or # code { # ... # ... # } # In the second case, we need to work out the indenting # and strip it from all lines but preserve the remaining indenting. # Note that all lines need to be indented with the same initial # spaces/tabs. # # Returns a list of lines with the indenting removed. # proc parse_code_block {text} { # If the text begins with newline, take the following text, # otherwise just return the original if {![regexp "^\n(.*)" $text -> text]} { return [list [string trim $text]] } # And trip spaces off the end set text [string trimright $text] set min 100 # Examine each line to determine the minimum indent foreach line [split $text \n] { if {$line eq ""} { # Ignore empty lines for the indent calculation continue } regexp "^(\[ \t\]*)" $line -> indent set len [string length $indent] if {$len < $min} { set min $len } } # Now make a list of lines with this indent removed set lines {} foreach line [split $text \n] { lappend lines [string range $line $min end] } # Return the result return $lines } } # ----- module getopt ----- set modsource(getopt) { # Copyright (c) 2006 WorkWare Systems http://www.workware.net.au/ # All rights reserved # Simple getopt module # Parse everything out of the argv list which looks like an option # Everything which doesn't look like an option, or is after --, is left unchanged # Understands --enable-xxx and --with-xxx as synonyms for --xxx to enable the boolean option xxx. # Understands --disable-xxx and --without-xxx to disable the boolean option xxx. # # The returned value is a dictionary keyed by option name # Each value is a list of {type value} ... where type is "bool" or "str". # The value for a boolean option is 0 or 1. The value of a string option is the value given. proc getopt {argvname} { upvar $argvname argv set nargv {} set opts {} for {set i 0} {$i < [llength $argv]} {incr i} { set arg [lindex $argv $i] #dputs arg=$arg if {$arg eq "--"} { # End of options incr i lappend nargv {*}[lrange $argv $i end] break } if {[regexp {^--([^=][^=]+)=(.*)$} $arg -> name value]} { # --name=value dict lappend opts $name [list str $value] } elseif {[regexp {^--(enable-|disable-|with-|without-)?([^=]*)$} $arg -> prefix name]} { if {$prefix in {enable- with- ""}} { set value 1 } else { set value 0 } dict lappend opts $name [list bool $value] } else { lappend nargv $arg } } #puts "getopt: argv=[join $argv] => [join $nargv]" #array set getopt $opts #parray getopt set argv $nargv return $opts } } # ----- module help ----- set modsource(help) { # Copyright (c) 2010 WorkWare Systems http://workware.net.au/ # All rights reserved # Module which provides usage, help and the command reference proc autosetup_help {what} { use_pager puts "Usage: [file tail $::autosetup(exe)] \[options\] \[settings\]\n" puts "This is [autosetup_version], a build environment \"autoconfigurator\"" puts "See the documentation online at http://msteveb.github.com/autosetup/\n" if {$what eq "local"} { if {[file exists $::autosetup(autodef)]} { # This relies on auto.def having a call to 'options' # which will display options and quit source $::autosetup(autodef) } else { options-show } } else { incr ::autosetup(showhelp) if {[catch {use $what}]} { user-error "Unknown module: $what" } else { options-show } } exit 0 } # If not already paged and stdout is a tty, pipe the output through the pager # This is done by reinvoking autosetup with --nopager added proc use_pager {} { if {![opt-bool nopager] && [getenv PAGER ""] ne "" && [isatty? stdin] && [isatty? stdout]} { if {[catch { exec [info nameofexecutable] $::argv0 --nopager {*}$::argv |& {*}[getenv PAGER] >@stdout <@stdin 2>@stderr } msg opts] == 1} { if {[dict get $opts -errorcode] eq "NONE"} { # an internal/exec error puts stderr $msg exit 1 } } exit 0 } } # Outputs the autosetup references in one of several formats proc autosetup_reference {{type text}} { use_pager switch -glob -- $type { wiki {use wiki-formatting} ascii* {use asciidoc-formatting} md - markdown {use markdown-formatting} default {use text-formatting} } title "[autosetup_version] -- Command Reference" section {Introduction} p { See http://msteveb.github.com/autosetup/ for the online documentation for 'autosetup' } p { 'autosetup' provides a number of built-in commands which are documented below. These may be used from 'auto.def' to test for features, define variables, create files from templates and other similar actions. } automf_command_reference exit 0 } proc autosetup_output_block {type lines} { if {[llength $lines]} { switch $type { code { codelines $lines } p { p [join $lines] } list { foreach line $lines { bullet $line } nl } } } } # Generate a command reference from inline documentation proc automf_command_reference {} { lappend files $::autosetup(prog) lappend files {*}[lsort [glob -nocomplain $::autosetup(libdir)/*.tcl]] section "Core Commands" set type p set lines {} set cmd {} foreach file $files { set f [open $file] while {![eof $f]} { set line [gets $f] # Find lines starting with "# @*" and continuing through the remaining comment lines if {![regexp {^# @(.*)} $line -> cmd]} { continue } # Synopsis or command? if {$cmd eq "synopsis:"} { section "Module: [file rootname [file tail $file]]" } else { subsection $cmd } set lines {} set type p # Now the description while {![eof $f]} { set line [gets $f] if {![regexp {^#(#)? ?(.*)} $line -> hash cmd]} { break } if {$hash eq "#"} { set t code } elseif {[regexp {^- (.*)} $cmd -> cmd]} { set t list } else { set t p } #puts "hash=$hash, oldhash=$oldhash, lines=[llength $lines], cmd=$cmd" if {$t ne $type || $cmd eq ""} { # Finish the current block autosetup_output_block $type $lines set lines {} set type $t } if {$cmd ne ""} { lappend lines $cmd } } autosetup_output_block $type $lines } close $f } } } # ----- module init ----- set modsource(init) { # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ # All rights reserved # Module to help create auto.def and configure proc autosetup_init {type} { set help 0 if {$type in {? help}} { incr help } elseif {![dict exists $::autosetup(inittypes) $type]} { puts "Unknown type, --init=$type" incr help } if {$help} { puts "Use one of the following types (e.g. --init=make)\n" foreach type [lsort [dict keys $::autosetup(inittypes)]] { lassign [dict get $::autosetup(inittypes) $type] desc # XXX: Use the options-show code to wrap the description puts [format "%-10s %s" $type $desc] } return } lassign [dict get $::autosetup(inittypes) $type] desc script puts "Initialising $type: $desc\n" # All initialisations happens in the top level srcdir cd $::autosetup(srcdir) uplevel #0 $script } proc autosetup_add_init_type {type desc script} { dict set ::autosetup(inittypes) $type [list $desc $script] } # This is for in creating build-system init scripts # # If the file doesn't exist, create it containing $contents # If the file does exist, only overwrite if --force is specified. # proc autosetup_check_create {filename contents} { if {[file exists $filename]} { if {!$::autosetup(force)} { puts "I see $filename already exists." return } else { puts "I will overwrite the existing $filename because you used --force." } } else { puts "I don't see $filename, so I will create it." } writefile $filename $contents } } # ----- module install ----- set modsource(install) { # Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/ # All rights reserved # Module which can install autosetup proc autosetup_install {dir} { if {[catch { cd $dir file mkdir autosetup set f [open autosetup/autosetup w] set publicmodules [glob $::autosetup(libdir)/*.auto] # First the main script, but only up until "CUT HERE" set in [open $::autosetup(dir)/autosetup] while {[gets $in buf] >= 0} { if {$buf ne "##-- CUT HERE --##"} { puts $f $buf continue } # Insert the static modules here # i.e. those which don't contain @synopsis: puts $f "set autosetup(installed) 1" foreach file [lsort [glob $::autosetup(libdir)/*.tcl]] { set buf [readfile $file] if {[string match "*\n# @synopsis:*" $buf]} { lappend publicmodules $file continue } set modname [file rootname [file tail $file]] puts $f "# ----- module $modname -----" puts $f "\nset modsource($modname) \{" puts $f $buf puts $f "\}\n" } } close $in close $f exec chmod 755 autosetup/autosetup # Install public modules foreach file $publicmodules { autosetup_install_file $file autosetup } # Install support files foreach file {config.guess config.sub jimsh0.c find-tclsh test-tclsh LICENSE} { autosetup_install_file $::autosetup(dir)/$file autosetup } exec chmod 755 autosetup/config.sub autosetup/config.guess autosetup/find-tclsh writefile autosetup/README.autosetup \ "This is [autosetup_version]. See http://msteveb.github.com/autosetup/\n" } error]} { user-error "Failed to install autosetup: $error" } puts "Installed [autosetup_version] to autosetup/" # Now create 'configure' if necessary autosetup_create_configure } proc autosetup_create_configure {} { if {[file exists configure]} { if {!$::autosetup(force)} { # Could this be an autosetup configure? if {![string match "*\nWRAPPER=*" [readfile configure]]} { puts "I see configure, but not created by autosetup, so I won't overwrite it." puts "Remove it or use --force to overwrite." return } } else { puts "I will overwrite the existing configure because you used --force." } } else { puts "I don't see configure, so I will create it." } writefile configure \ {#!/bin/sh dir="`dirname "$0"`/autosetup" WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@" } catch {exec chmod 755 configure} } # Append the contents of $file to filehandle $f proc autosetup_install_append {f file} { set in [open $file] puts $f [read $in] close $in } proc autosetup_install_file {file dir} { if {![file exists $file]} { error "Missing installation file '$file'" } writefile [file join $dir [file tail $file]] [readfile $file]\n } if {$::autosetup(installed)} { user-error "autosetup can only be installed from development source, not from installed copy" } } # ----- module markdown-formatting ----- set modsource(markdown-formatting) { # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ # All rights reserved # Module which provides text formatting # markdown format (kramdown syntax) use formatting proc para {text} { regsub -all "\[ \t\n\]+" [string trim $text] " " text regsub -all {([^a-zA-Z])'([^']*)'} $text {\1**`\2`**} text regsub -all {^'([^']*)'} $text {**`\1`**} text regsub -all {(http[^ \t\n]*)} $text {[\1](\1)} text return $text } proc title {text} { underline [para $text] = nl } proc p {text} { puts [para $text] nl } proc codelines {lines} { puts "~~~~~~~~~~~~" foreach line $lines { puts $line } puts "~~~~~~~~~~~~" nl } proc code {text} { puts "~~~~~~~~~~~~" foreach line [parse_code_block $text] { puts $line } puts "~~~~~~~~~~~~" nl } proc nl {} { puts "" } proc underline {text char} { regexp "^(\[ \t\]*)(.*)" $text -> indent words puts $text puts $indent[string repeat $char [string length $words]] } proc section {text} { underline "[para $text]" - nl } proc subsection {text} { puts "### `$text`" nl } proc bullet {text} { puts "* [para $text]" } proc defn {first args} { puts "^" set defn [string trim [join $args \n]] if {$first ne ""} { puts "**${first}**" puts -nonewline ": " regsub -all "\n\n" $defn "\n: " defn } puts "$defn" } } # ----- module misc ----- set modsource(misc) { # Copyright (c) 2007-2010 WorkWare Systems http://www.workware.net.au/ # All rights reserved # Module containing misc procs useful to modules # Largely for platform compatibility set autosetup(istcl) [info exists ::tcl_library] set autosetup(iswin) [string equal windows $tcl_platform(platform)] if {$autosetup(iswin)} { # mingw/windows separates $PATH with semicolons # and doesn't have an executable bit proc split-path {} { split [getenv PATH .] {;} } proc file-isexec {exec} { # Basic test for windows. We ignore .bat if {[file isfile $exec] || [file isfile $exec.exe]} { return 1 } return 0 } } else { # unix separates $PATH with colons and has and executable bit proc split-path {} { split [getenv PATH .] : } proc file-isexec {exec} { file executable $exec } } # Assume that exec can return stdout and stderr proc exec-with-stderr {args} { exec {*}$args 2>@1 } if {$autosetup(istcl)} { # Tcl doesn't have the env command proc getenv {name args} { if {[info exists ::env($name)]} { return $::env($name) } if {[llength $args]} { return [lindex $args 0] } return -code error "environment variable \"$name\" does not exist" } proc isatty? {channel} { dict exists [fconfigure $channel] -xchar } } else { if {$autosetup(iswin)} { # On Windows, backslash convert all environment variables # (Assume that Tcl does this for us) proc getenv {name args} { string map {\\ /} [env $name {*}$args] } } else { # Jim on unix is simple alias getenv env } proc isatty? {channel} { set tty 0 catch { # isatty is a recent addition to Jim Tcl set tty [$channel isatty] } return $tty } } # In case 'file normalize' doesn't exist # proc file-normalize {path} { if {[catch {file normalize $path} result]} { if {$path eq ""} { return "" } set oldpwd [pwd] if {[file isdir $path]} { cd $path set result [pwd] } else { cd [file dirname $path] set result [file join [pwd] [file tail $path]] } cd $oldpwd } return $result } # If everything is working properly, the only errors which occur # should be generated in user code (e.g. auto.def). # By default, we only want to show the error location in user code. # We use [info frame] to achieve this, but it works differently on Tcl and Jim. # # This is designed to be called for incorrect usage in auto.def, via autosetup-error # proc error-location {msg} { if {$::autosetup(debug)} { return -code error $msg } # Search back through the stack trace for the first error in a .def file for {set i 1} {$i < [info level]} {incr i} { if {$::autosetup(istcl)} { array set info [info frame -$i] } else { lassign [info frame -$i] info(caller) info(file) info(line) } if {[string match *.def $info(file)]} { return "[relative-path $info(file)]:$info(line): Error: $msg" } #puts "Skipping $info(file):$info(line)" } return $msg } # If everything is working properly, the only errors which occur # should be generated in user code (e.g. auto.def). # By default, we only want to show the error location in user code. # We use [info frame] to achieve this, but it works differently on Tcl and Jim. # # This is designed to be called for incorrect usage in auto.def, via autosetup-error # proc error-stacktrace {msg} { if {$::autosetup(debug)} { return -code error $msg } # Search back through the stack trace for the first error in a .def file for {set i 1} {$i < [info level]} {incr i} { if {$::autosetup(istcl)} { array set info [info frame -$i] } else { lassign [info frame -$i] info(caller) info(file) info(line) } if {[string match *.def $info(file)]} { return "[relative-path $info(file)]:$info(line): Error: $msg" } #puts "Skipping $info(file):$info(line)" } return $msg } # Given the return from [catch {...} msg opts], returns an appropriate # error message. A nice one for Jim and a less-nice one for Tcl. # If 'fulltrace' is set, a full stack trace is provided. # Otherwise a simple message is provided. # # This is designed for developer errors, e.g. in module code or auto.def code # # proc error-dump {msg opts fulltrace} { if {$::autosetup(istcl)} { if {$fulltrace} { return "Error: [dict get $opts -errorinfo]" } else { return "Error: $msg" } } else { lassign $opts(-errorinfo) p f l if {$f ne ""} { set result "$f:$l: Error: " } append result "$msg\n" if {$fulltrace} { append result [stackdump $opts(-errorinfo)] } # Remove the trailing newline string trim $result } } } # ----- module text-formatting ----- set modsource(text-formatting) { # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ # All rights reserved # Module which provides text formatting use formatting proc wordwrap {text length {firstprefix ""} {nextprefix ""}} { set len 0 set space $firstprefix foreach word [split $text] { set word [string trim $word] if {$word == ""} { continue } if {$len && [string length $space$word] + $len >= $length} { puts "" set len 0 set space $nextprefix } incr len [string length $space$word] # Use man-page conventions for highlighting 'quoted' and *quoted* # single words. # Use x^Hx for *bold* and _^Hx for 'underline'. # # less and more will both understand this. # Pipe through 'col -b' to remove them. if {[regexp {^'(.*)'([^a-zA-Z0-9_]*)$} $word -> bareword dot]} { regsub -all . $bareword "_\b&" word append word $dot } elseif {[regexp {^[*](.*)[*]([^a-zA-Z0-9_]*)$} $word -> bareword dot]} { regsub -all . $bareword "&\b&" word append word $dot } puts -nonewline $space$word set space " " } if {$len} { puts "" } } proc title {text} { underline [string trim $text] = nl } proc p {text} { wordwrap $text 80 nl } proc codelines {lines} { foreach line $lines { puts " $line" } nl } proc nl {} { puts "" } proc underline {text char} { regexp "^(\[ \t\]*)(.*)" $text -> indent words puts $text puts $indent[string repeat $char [string length $words]] } proc section {text} { underline "[string trim $text]" - nl } proc subsection {text} { underline "$text" ~ nl } proc bullet {text} { wordwrap $text 76 " * " " " } proc indent {text} { wordwrap $text 76 " " " " } proc defn {first args} { if {$first ne ""} { underline " $first" ~ } foreach p $args { if {$p ne ""} { indent $p } } } } # ----- module wiki-formatting ----- set modsource(wiki-formatting) { # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ # All rights reserved # Module which provides text formatting # wiki.tcl.tk format output use formatting proc joinlines {text} { set lines {} foreach l [split [string trim $text] \n] { lappend lines [string trim $l] } join $lines } proc p {text} { puts [joinlines $text] puts "" } proc title {text} { puts "*** [joinlines $text] ***" puts "" } proc codelines {lines} { puts "======" foreach line $lines { puts " $line" } puts "======" } proc code {text} { puts "======" foreach line [parse_code_block $text] { puts " $line" } puts "======" } proc nl {} { } proc section {text} { puts "'''$text'''" puts "" } proc subsection {text} { puts "''$text''" puts "" } proc bullet {text} { puts " * [joinlines $text]" } proc indent {text} { puts " : [joinlines $text]" } proc defn {first args} { if {$first ne ""} { indent '''$first''' } foreach p $args { p $p } } } ################################################################## # # Entry/Exit # if {$autosetup(debug)} { main $argv } if {[catch {main $argv} msg opts] == 1} { show-notices autosetup-full-error [error-dump $msg $opts $::autosetup(debug)] if {!$autosetup(debug)} { puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace" } exit 1 } |
> > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/ # All rights reserved # @synopsis: # # The 'cc-db' module provides a knowledge based of system idiosyncrasies # In general, this module can always be included use cc module-options {} # openbsd needs sys/types.h to detect some system headers cc-include-needs sys/socket.h sys/types.h cc-include-needs netinet/in.h sys/types.h |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | # Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/ # All rights reserved # @synopsis: # # Provides a library of common tests on top of the 'cc' module. use cc module-options {} # @cc-check-lfs # # The equivalent of the AC_SYS_LARGEFILE macro # # defines 'HAVE_LFS' if LFS is available, # and defines '_FILE_OFFSET_BITS=64' if necessary # # Returns 1 if 'LFS' is available or 0 otherwise # proc cc-check-lfs {} { cc-check-includes sys/types.h msg-checking "Checking if -D_FILE_OFFSET_BITS=64 is needed..." set lfs 1 if {[msg-quiet cc-with {-includes sys/types.h} {cc-check-sizeof off_t}] == 8} { msg-result no } elseif {[msg-quiet cc-with {-includes sys/types.h -cflags -D_FILE_OFFSET_BITS=64} {cc-check-sizeof off_t}] == 8} { define _FILE_OFFSET_BITS 64 msg-result yes } else { set lfs 0 msg-result none } define-feature lfs $lfs return $lfs } # @cc-check-endian # # The equivalent of the AC_C_BIGENDIAN macro # # defines 'HAVE_BIG_ENDIAN' if endian is known to be big, # or 'HAVE_LITTLE_ENDIAN' if endian is known to be little. # # Returns 1 if determined, or 0 if not. # proc cc-check-endian {} { cc-check-includes sys/types.h sys/param.h set rc 0 msg-checking "Checking endian..." cc-with {-includes {sys/types.h sys/param.h}} { if {[cctest -code { #if !defined(BIG_ENDIAN) || !defined(BYTE_ORDER) #error unknown #elif BYTE_ORDER != BIG_ENDIAN #error little #endif }]} { define-feature big-endian msg-result "big" set rc 1 } elseif {[cctest -code { #if !defined(LITTLE_ENDIAN) || !defined(BYTE_ORDER) #error unknown #elif BYTE_ORDER != LITTLE_ENDIAN #error big #endif }]} { define-feature little-endian msg-result "little" set rc 1 } else { msg-result "unknown" } } return $rc } # @cc-check-flags flag ?...? # # Checks whether the given C/C++ compiler flags can be used. Defines feature # names prefixed with 'HAVE_CFLAG' and 'HAVE_CXXFLAG' respectively, and # appends working flags to '-cflags' and 'CFLAGS' or 'CXXFLAGS'. proc cc-check-flags {args} { set result 1 array set opts [cc-get-settings] switch -exact -- $opts(-lang) { c++ { set lang C++ set prefix CXXFLAG } c { set lang C set prefix CFLAG } default { autosetup-error "cc-check-flags failed with unknown language: $opts(-lang)" } } foreach flag $args { msg-checking "Checking whether the $lang compiler accepts $flag..." if {[cctest -cflags $flag]} { msg-result yes define-feature $prefix$flag cc-with [list -cflags [list $flag]] define-append ${prefix}S $flag } else { msg-result no set result 0 } } return $result } # @cc-check-standards ver ?...? # # Checks whether the C/C++ compiler accepts one of the specified '-std=$ver' # options, and appends the first working one to '-cflags' and 'CFLAGS' or # 'CXXFLAGS'. proc cc-check-standards {args} { array set opts [cc-get-settings] foreach std $args { if {[cc-check-flags -std=$std]} { return $std } } return "" } # Checks whether $keyword is usable as alignof proc cctest_alignof {keyword} { msg-checking "Checking for $keyword..." if {[cctest -code [subst -nobackslashes { printf("minimum alignment is %d == %d\n", ${keyword}(char), ${keyword}('x')); }]]} then { msg-result ok define-feature $keyword } else { msg-result "not found" } } # @cc-check-c11 # # Checks for several C11/C++11 extensions and their alternatives. Currently # checks for '_Static_assert', '_Alignof', '__alignof__', '__alignof'. proc cc-check-c11 {} { msg-checking "Checking for _Static_assert..." if {[cctest -code { _Static_assert(1, "static assertions are available"); }]} then { msg-result ok define-feature _Static_assert } else { msg-result "not found" } cctest_alignof _Alignof cctest_alignof __alignof__ cctest_alignof __alignof } # @cc-check-alloca # # The equivalent of the AC_FUNC_ALLOCA macro # # Checks for the existence of alloca # defines HAVE_ALLOCA and returns 1 if it exists proc cc-check-alloca {} { cc-check-some-feature alloca { cctest -includes alloca.h -code { alloca (2 * sizeof (int)); } } } # @cc-signal-return-type # # The equivalent of the AC_TYPE_SIGNAL macro # # defines RETSIGTYPE to int or void proc cc-signal-return-type {} { msg-checking "Checking return type of signal handlers..." cc-with {-includes {sys/types.h signal.h}} { if {[cctest -code {return *(signal (0, 0)) (0) == 1;}]} { set type int } else { set type void } define RETSIGTYPE $type msg-result $type } } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ # All rights reserved # @synopsis: # # The 'cc-shared' module provides support for shared libraries and shared objects. # It defines the following variables: # ## SH_CFLAGS Flags to use compiling sources destined for a shared library ## SH_LDFLAGS Flags to use linking (creating) a shared library ## SH_SOPREFIX Prefix to use to set the soname when creating a shared library ## SH_SOEXT Extension for shared libs ## SH_SOEXTVER Format for versioned shared libs - %s = version ## SHOBJ_CFLAGS Flags to use compiling sources destined for a shared object ## SHOBJ_LDFLAGS Flags to use linking a shared object, undefined symbols allowed ## SHOBJ_LDFLAGS_R - as above, but all symbols must be resolved ## SH_LINKFLAGS Flags to use linking an executable which will load shared objects ## LD_LIBRARY_PATH Environment variable which specifies path to shared libraries ## STRIPLIBFLAGS Arguments to strip a dynamic library module-options {} # Defaults: gcc on unix define SHOBJ_CFLAGS -fpic define SHOBJ_LDFLAGS -shared define SH_CFLAGS -fpic define SH_LDFLAGS -shared define SH_LINKFLAGS -rdynamic define SH_SOEXT .so define SH_SOEXTVER .so.%s define SH_SOPREFIX -Wl,-soname, define LD_LIBRARY_PATH LD_LIBRARY_PATH define STRIPLIBFLAGS --strip-unneeded # Note: This is a helpful reference for identifying the toolchain # http://sourceforge.net/apps/mediawiki/predef/index.php?title=Compilers switch -glob -- [get-define host] { *-*-darwin* { define SHOBJ_CFLAGS "-dynamic -fno-common" define SHOBJ_LDFLAGS "-bundle -undefined dynamic_lookup" define SHOBJ_LDFLAGS_R -bundle define SH_CFLAGS -dynamic define SH_LDFLAGS -dynamiclib define SH_LINKFLAGS "" define SH_SOEXT .dylib define SH_SOEXTVER .%s.dylib define SH_SOPREFIX -Wl,-install_name, define LD_LIBRARY_PATH DYLD_LIBRARY_PATH define STRIPLIBFLAGS -x } *-*-ming* - *-*-cygwin - *-*-msys { define SHOBJ_CFLAGS "" define SHOBJ_LDFLAGS -shared define SH_CFLAGS "" define SH_LDFLAGS -shared define SH_LINKFLAGS "" define SH_SOEXT .dll define SH_SOEXTVER .dll define SH_SOPREFIX "" define LD_LIBRARY_PATH PATH } sparc* { if {[msg-quiet cc-check-decls __SUNPRO_C]} { msg-result "Found sun stdio compiler" # sun stdio compiler # XXX: These haven't been fully tested. define SHOBJ_CFLAGS -KPIC define SHOBJ_LDFLAGS "-G" define SH_CFLAGS -KPIC define SH_LINKFLAGS -Wl,-export-dynamic define SH_SOPREFIX -Wl,-h, } else { # sparc has a very small GOT table limit, so use -fPIC define SH_CFLAGS -fPIC define SHOBJ_CFLAGS -fPIC } } *-*-solaris* { if {[msg-quiet cc-check-decls __SUNPRO_C]} { msg-result "Found sun stdio compiler" # sun stdio compiler # XXX: These haven't been fully tested. define SHOBJ_CFLAGS -KPIC define SHOBJ_LDFLAGS "-G" define SH_CFLAGS -KPIC define SH_LINKFLAGS -Wl,-export-dynamic define SH_SOPREFIX -Wl,-h, } } *-*-hpux { # XXX: These haven't been tested define SHOBJ_CFLAGS "+O3 +z" define SHOBJ_LDFLAGS -b define SH_CFLAGS +z define SH_LINKFLAGS -Wl,+s define LD_LIBRARY_PATH SHLIB_PATH } *-*-haiku { define SHOBJ_CFLAGS "" define SHOBJ_LDFLAGS -shared define SH_CFLAGS "" define SH_LDFLAGS -shared define SH_LINKFLAGS "" define SH_SOPREFIX "" define LD_LIBRARY_PATH LIBRARY_PATH } microblaze* { # Microblaze generally needs -fPIC rather than -fpic define SHOBJ_CFLAGS -fPIC define SH_CFLAGS -fPIC } } if {![is-defined SHOBJ_LDFLAGS_R]} { define SHOBJ_LDFLAGS_R [get-define SHOBJ_LDFLAGS] } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 | # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ # All rights reserved # @synopsis: # # The 'cc' module supports checking various 'features' of the C or C++ # compiler/linker environment. Common commands are cc-check-includes, # cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-template. # # The following environment variables are used if set: # ## CC - C compiler ## CXX - C++ compiler ## CCACHE - Set to "none" to disable automatic use of ccache ## CFLAGS - Additional C compiler flags ## CXXFLAGS - Additional C++ compiler flags ## LDFLAGS - Additional compiler flags during linking ## LIBS - Additional libraries to use (for all tests) ## CROSS - Tool prefix for cross compilation # # The following variables are defined from the corresponding # environment variables if set. # ## CPPFLAGS ## LINKFLAGS ## CC_FOR_BUILD ## LD use system module-options {} # Note that the return code is not meaningful proc cc-check-something {name code} { uplevel 1 $code } # Checks for the existence of the given function by linking # proc cctest_function {function} { cctest -link 1 -declare "extern void $function\(void);" -code "$function\();" } # Checks for the existence of the given type by compiling proc cctest_type {type} { cctest -code "$type _x;" } # Checks for the existence of the given type/structure member. # e.g. "struct stat.st_mtime" proc cctest_member {struct_member} { # split at the first dot regexp {^([^.]+)[.](.*)$} $struct_member -> struct member cctest -code "static $struct _s; return sizeof(_s.$member);" } # Checks for the existence of the given define by compiling # proc cctest_define {name} { cctest -code "#ifndef $name\n#error not defined\n#endif" } # Checks for the existence of the given name either as # a macro (#define) or an rvalue (such as an enum) # proc cctest_decl {name} { cctest -code "#ifndef $name\n(void)$name;\n#endif" } # @cc-check-sizeof type ... # # Checks the size of the given types (between 1 and 32, inclusive). # Defines a variable with the size determined, or "unknown" otherwise. # e.g. for type 'long long', defines SIZEOF_LONG_LONG. # Returns the size of the last type. # proc cc-check-sizeof {args} { foreach type $args { msg-checking "Checking for sizeof $type..." set size unknown # Try the most common sizes first foreach i {4 8 1 2 16 32} { if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} { set size $i break } } msg-result $size set define [feature-define-name $type SIZEOF_] define $define $size } # Return the last result get-define $define } # Checks for each feature in $list by using the given script. # # When the script is evaluated, $each is set to the feature # being checked, and $extra is set to any additional cctest args. # # Returns 1 if all features were found, or 0 otherwise. proc cc-check-some-feature {list script} { set ret 1 foreach each $list { if {![check-feature $each $script]} { set ret 0 } } return $ret } # @cc-check-includes includes ... # # Checks that the given include files can be used proc cc-check-includes {args} { cc-check-some-feature $args { set with {} if {[dict exists $::autosetup(cc-include-deps) $each]} { set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]] msg-quiet cc-check-includes {*}$deps foreach i $deps { if {[have-feature $i]} { lappend with $i } } } if {[llength $with]} { cc-with [list -includes $with] { cctest -includes $each } } else { cctest -includes $each } } } # @cc-include-needs include required ... # # Ensures that when checking for 'include', a check is first # made for each 'required' file, and if found, it is #included proc cc-include-needs {file args} { foreach depfile $args { dict set ::autosetup(cc-include-deps) $file $depfile 1 } } # @cc-check-types type ... # # Checks that the types exist. proc cc-check-types {args} { cc-check-some-feature $args { cctest_type $each } } # @cc-check-defines define ... # # Checks that the given preprocessor symbol is defined proc cc-check-defines {args} { cc-check-some-feature $args { cctest_define $each } } # @cc-check-decls name ... # # Checks that each given name is either a preprocessor symbol or rvalue # such as an enum. Note that the define used is HAVE_DECL_xxx # rather than HAVE_xxx proc cc-check-decls {args} { set ret 1 foreach name $args { msg-checking "Checking for $name..." set r [cctest_decl $name] define-feature "decl $name" $r if {$r} { msg-result "ok" } else { msg-result "not found" set ret 0 } } return $ret } # @cc-check-functions function ... # # Checks that the given functions exist (can be linked) proc cc-check-functions {args} { cc-check-some-feature $args { cctest_function $each } } # @cc-check-members type.member ... # # Checks that the given type/structure members exist. # A structure member is of the form "struct stat.st_mtime" proc cc-check-members {args} { cc-check-some-feature $args { cctest_member $each } } # @cc-check-function-in-lib function libs ?otherlibs? # # Checks that the given function can be found in one of the libs. # # First checks for no library required, then checks each of the libraries # in turn. # # If the function is found, the feature is defined and lib_$function is defined # to -l$lib where the function was found, or "" if no library required. # In addition, -l$lib is prepended to the LIBS define. # # If additional libraries may be needed for linking, they should be specified # as $extralibs as "-lotherlib1 -lotherlib2". # These libraries are not automatically added to LIBS. # # Returns 1 if found or 0 if not. # proc cc-check-function-in-lib {function libs {otherlibs {}}} { msg-checking "Checking libs for $function..." set found 0 cc-with [list -libs $otherlibs] { if {[cctest_function $function]} { msg-result "none needed" define lib_$function "" incr found } else { foreach lib $libs { cc-with [list -libs -l$lib] { if {[cctest_function $function]} { msg-result -l$lib define lib_$function -l$lib # prepend to LIBS define LIBS "-l$lib [get-define LIBS]" incr found break } } } } } if {$found} { define [feature-define-name $function] } else { msg-result "no" } return $found } # @cc-check-tools tool ... # # Checks for existence of the given compiler tools, taking # into account any cross compilation prefix. # # For example, when checking for "ar", first AR is checked on the command # line and then in the environment. If not found, "${host}-ar" or # simply "ar" is assumed depending upon whether cross compiling. # The path is searched for this executable, and if found AR is defined # to the executable name. # Note that even when cross compiling, the simple "ar" is used as a fallback, # but a warning is generated. This is necessary for some toolchains. # # It is an error if the executable is not found. # proc cc-check-tools {args} { foreach tool $args { set TOOL [string toupper $tool] set exe [get-env $TOOL [get-define cross]$tool] if {[find-executable {*}$exe]} { define $TOOL $exe continue } if {[find-executable {*}$tool]} { msg-result "Warning: Failed to find $exe, falling back to $tool which may be incorrect" define $TOOL $tool continue } user-error "Failed to find $exe" } } # @cc-check-progs prog ... # # Checks for existence of the given executables on the path. # # For example, when checking for "grep", the path is searched for # the executable, 'grep', and if found GREP is defined as "grep". # # If the executable is not found, the variable is defined as false. # Returns 1 if all programs were found, or 0 otherwise. # proc cc-check-progs {args} { set failed 0 foreach prog $args { set PROG [string toupper $prog] msg-checking "Checking for $prog..." if {![find-executable $prog]} { msg-result no define $PROG false incr failed } else { msg-result ok define $PROG $prog } } expr {!$failed} } # Adds the given settings to $::autosetup(ccsettings) and # returns the old settings. # proc cc-add-settings {settings} { if {[llength $settings] % 2} { autosetup-error "settings list is missing a value: $settings" } set prev [cc-get-settings] # workaround a bug in some versions of jimsh by forcing # conversion of $prev to a list llength $prev array set new $prev foreach {name value} $settings { switch -exact -- $name { -cflags - -includes { # These are given as lists lappend new($name) {*}$value } -declare { lappend new($name) $value } -libs { # Note that new libraries are added before previous libraries set new($name) [list {*}$value {*}$new($name)] } -link - -lang - -nooutput { set new($name) $value } -source - -sourcefile - -code { # XXX: These probably are only valid directly from cctest set new($name) $value } default { autosetup-error "unknown cctest setting: $name" } } } cc-store-settings [array get new] return $prev } proc cc-store-settings {new} { set ::autosetup(ccsettings) $new } proc cc-get-settings {} { return $::autosetup(ccsettings) } # Similar to cc-add-settings, but each given setting # simply replaces the existing value. # # Returns the previous settings proc cc-update-settings {args} { set prev [cc-get-settings] cc-store-settings [dict merge $prev $args] return $prev } # @cc-with settings ?{ script }? # # Sets the given 'cctest' settings and then runs the tests in 'script'. # Note that settings such as -lang replace the current setting, while # those such as -includes are appended to the existing setting. # # If no script is given, the settings become the default for the remainder # of the auto.def file. # ## cc-with {-lang c++} { ## # This will check with the C++ compiler ## cc-check-types bool ## cc-with {-includes signal.h} { ## # This will check with the C++ compiler, signal.h and any existing includes. ## ... ## } ## # back to just the C++ compiler ## } # # The -libs setting is special in that newer values are added *before* earlier ones. # ## cc-with {-libs {-lc -lm}} { ## cc-with {-libs -ldl} { ## cctest -libs -lsocket ... ## # libs will be in this order: -lsocket -ldl -lc -lm ## } ## } proc cc-with {settings args} { if {[llength $args] == 0} { cc-add-settings $settings } elseif {[llength $args] > 1} { autosetup-error "usage: cc-with settings ?script?" } else { set save [cc-add-settings $settings] set rc [catch {uplevel 1 [lindex $args 0]} result info] cc-store-settings $save if {$rc != 0} { return -code [dict get $info -code] $result } return $result } } # @cctest ?settings? # # Low level C compiler checker. Compiles and or links a small C program # according to the arguments and returns 1 if OK, or 0 if not. # # Supported settings are: # ## -cflags cflags A list of flags to pass to the compiler ## -includes list A list of includes, e.g. {stdlib.h stdio.h} ## -declare code Code to declare before main() ## -link 1 Don't just compile, link too ## -lang c|c++ Use the C (default) or C++ compiler ## -libs liblist List of libraries to link, e.g. {-ldl -lm} ## -code code Code to compile in the body of main() ## -source code Compile a complete program. Ignore -includes, -declare and -code ## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file] ## -nooutput 1 Treat any compiler output (e.g. a warning) as an error # # Unless -source or -sourcefile is specified, the C program looks like: # ## #include <firstinclude> /* same for remaining includes in the list */ ## ## declare-code /* any code in -declare, verbatim */ ## ## int main(void) { ## code /* any code in -code, verbatim */ ## return 0; ## } # # Any failures are recorded in 'config.log' # proc cctest {args} { set src conftest__.c set tmp conftest__ # Easiest way to merge in the settings cc-with $args { array set opts [cc-get-settings] } if {[info exists opts(-sourcefile)]} { set opts(-source) [readfile [get-define srcdir]/$opts(-sourcefile) "#error can't find $opts(-sourcefile)"] } if {[info exists opts(-source)]} { set lines $opts(-source) } else { foreach i $opts(-includes) { if {$opts(-code) ne "" && ![feature-checked $i]} { # Compiling real code with an unchecked header file # Quickly (and silently) check for it now # Remove all -includes from settings before checking set saveopts [cc-update-settings -includes {}] msg-quiet cc-check-includes $i cc-store-settings $saveopts } if {$opts(-code) eq "" || [have-feature $i]} { lappend source "#include <$i>" } } lappend source {*}$opts(-declare) lappend source "int main(void) {" lappend source $opts(-code) lappend source "return 0;" lappend source "}" set lines [join $source \n] } # Build the command line set cmdline {} lappend cmdline {*}[get-define CCACHE] switch -exact -- $opts(-lang) { c++ { lappend cmdline {*}[get-define CXX] {*}[get-define CXXFLAGS] } c { lappend cmdline {*}[get-define CC] {*}[get-define CFLAGS] } default { autosetup-error "cctest called with unknown language: $opts(-lang)" } } if {$opts(-link)} { lappend cmdline {*}[get-define LDFLAGS] } else { set tmp conftest__.o lappend cmdline -c } lappend cmdline {*}$opts(-cflags) {*}[get-define cc-default-debug ""] lappend cmdline $src -o $tmp {*}$opts(-libs) if {$opts(-link)} { lappend cmdline {*}[get-define LIBS] } # At this point we have the complete command line and the # complete source to be compiled. Get the result from cache if # we can if {[info exists ::cc_cache($cmdline,$lines)]} { msg-checking "(cached) " set ok $::cc_cache($cmdline,$lines) if {$::autosetup(debug)} { configlog "From cache (ok=$ok): [join $cmdline]" configlog "============" configlog $lines configlog "============" } return $ok } writefile $src $lines\n set ok 1 set err [catch {exec-with-stderr {*}$cmdline} result errinfo] if {$err || ($opts(-nooutput) && [string length $result])} { configlog "Failed: [join $cmdline]" configlog $result configlog "============" configlog "The failed code was:" configlog $lines configlog "============" set ok 0 } elseif {$::autosetup(debug)} { configlog "Compiled OK: [join $cmdline]" configlog "============" configlog $lines configlog "============" } file delete $src file delete $tmp # cache it set ::cc_cache($cmdline,$lines) $ok return $ok } # @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?bare-patterns=SIZEOF_*? # # Deprecated - see make-config-header proc make-autoconf-h {file {autopatterns {HAVE_*}} {barepatterns {SIZEOF_* HAVE_DECL_*}}} { user-notice "*** make-autoconf-h is deprecated -- use make-config-header instead" make-config-header $file -auto $autopatterns -bare $barepatterns } # @make-config-header outfile ?-auto patternlist? ?-bare patternlist? ?-none patternlist? ?-str patternlist? ... # # Examines all defined variables which match the given patterns # and writes an include file, $file, which defines each of these. # Variables which match '-auto' are output as follows: # - defines which have the value "0" are ignored. # - defines which have integer values are defined as the integer value. # - any other value is defined as a string, e.g. "value" # Variables which match '-bare' are defined as-is. # Variables which match '-str' are defined as a string, e.g. "value" # Variables which match '-none' are omitted. # # Note that order is important. The first pattern which matches is selected # Default behaviour is: # # -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none * # # If the file would be unchanged, it is not written. proc make-config-header {file args} { set guard _[string toupper [regsub -all {[^a-zA-Z0-9]} [file tail $file] _]] file mkdir [file dirname $file] set lines {} lappend lines "#ifndef $guard" lappend lines "#define $guard" # Add some defaults lappend args -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* foreach n [lsort [dict keys [all-defines]]] { set value [get-define $n] set type [calc-define-output-type $n $args] switch -exact -- $type { -bare { # Just output the value unchanged } -none { continue } -str { set value \"[string map [list \\ \\\\ \" \\\"] $value]\" } -auto { # Automatically determine the type if {$value eq "0"} { lappend lines "/* #undef $n */" continue } if {![string is integer -strict $value]} { set value \"[string map [list \\ \\\\ \" \\\"] $value]\" } } "" { continue } default { autosetup-error "Unknown type in make-config-header: $type" } } lappend lines "#define $n $value" } lappend lines "#endif" set buf [join $lines \n] write-if-changed $file $buf { msg-result "Created $file" } } proc calc-define-output-type {name spec} { foreach {type patterns} $spec { foreach pattern $patterns { if {[string match $pattern $name]} { return $type } } } return "" } # Initialise some values from the environment or commandline or default settings foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS {CFLAGS "-g -O2"}} { lassign $i var default define $var [get-env $var $default] } if {[env-is-set CC]} { # Set by the user, so don't try anything else set try [list [get-env CC ""]] } else { # Try some reasonable options set try [list [get-define cross]cc [get-define cross]gcc] } define CC [find-an-executable {*}$try] if {[get-define CC] eq ""} { user-error "Could not find a C compiler. Tried: [join $try ", "]" } define CPP [get-env CPP "[get-define CC] -E"] # XXX: Could avoid looking for a C++ compiler until requested # Note that if CXX isn't found, we just set it to "false". It might not be needed. if {[env-is-set CXX]} { define CXX [find-an-executable -required [get-env CXX ""]] } else { define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++ false] } # CXXFLAGS default to CFLAGS if not specified define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]] # May need a CC_FOR_BUILD, so look for one define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false] if {[get-define CC] eq ""} { user-error "Could not find a C compiler. Tried: [join $try ", "]" } define CCACHE [find-an-executable [get-env CCACHE ccache]] # Initial cctest settings cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0} set autosetup(cc-include-deps) {} msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS]" if {[get-define CXX] ne "false"} { msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS]" } msg-result "Build C compiler...[get-define CC_FOR_BUILD]" # On Darwin, we prefer to use -g0 to avoid creating .dSYM directories # but some compilers may not support it, so test here. switch -glob -- [get-define host] { *-*-darwin* { if {[cctest -cflags {-g0}]} { define cc-default-debug -g0 } } } if {![cc-check-includes stdlib.h]} { user-error "Compiler does not work. See config.log" } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 | #! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2014 Free Software Foundation, Inc. timestamp='2014-11-04' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see <http://www.gnu.org/licenses/>. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches to <config-patches@gnu.org>. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include <features.h> #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include <stdio.h> /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <sys/systemcfg.h> main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include <stdlib.h> #include <unistd.h> int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <unistd.h> int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` echo ${UNAME_MACHINE}-pc-isc$UNAME_REL elif /bin/uname -X 2>/dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says <Richard.M.Bartel@ccMail.Census.GOV> echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes <hewes@openmarket.com>. # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac cat >&2 <<EOF $0: unable to guess system type This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD and http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD If the version you run ($0) is already up to date, please send the following data and any information you think might be pertinent to <config-patches@gnu.org> in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 | #! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2014 Free Software Foundation, Inc. timestamp='2014-12-03' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see <http://www.gnu.org/licenses/>. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to <config-patches@gnu.org>. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: |
> > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # Copyright (c) 2012 WorkWare Systems http://www.workware.net.au/ # All rights reserved # Auto-load module for 'make' build system integration use init autosetup_add_init_type make {Simple "make" build system} { autosetup_check_create auto.def \ {# Initial auto.def created by 'autosetup --init=make' use cc # Add any user options here options { } make-config-header config.h make-template Makefile.in } if {![file exists Makefile.in]} { puts "Note: I don't see Makefile.in. You will probably need to create one." } } |
> > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/bin/sh # Looks for a suitable tclsh or jimsh in the PATH # If not found, builds a bootstrap jimsh from source d=`dirname "$0"` { "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0 PATH="$PATH:$d"; export PATH for tclsh in jimsh tclsh tclsh8.5 tclsh8.6; do { $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0 done echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0" for cc in ${CC_FOR_BUILD:-cc} gcc; do { $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue "$d/jimsh0" "$d/test-tclsh" && exit 0 done echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc." echo false |
more than 10,000 changes
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | # Copyright (c) 2016 WorkWare Systems http://www.workware.net.au/ # All rights reserved # @synopsis: # # The 'pkg-config' module allows package information to be found via pkg-config # # If not cross-compiling, the package path should be determined automatically # by pkg-config. # If cross-compiling, the default package path is the compiler sysroot. # If the C compiler doesn't support -print-sysroot, the path can be supplied # by the --sysroot option or by defining SYSROOT. # # PKG_CONFIG may be set to use an alternative to pkg-config use cc module-options { sysroot:dir => "Override compiler sysroot for pkg-config search path" } # @pkg-config-init ?required? # # Initialises the pkg-config system. Unless required is set to 0, # it is a fatal error if the pkg-config # This command will normally be called automatically as required, # but it may be invoked explicitly if lack of pkg-config is acceptable. # # Returns 1 if ok, or 0 if pkg-config not found/usable (only if required=0) # proc pkg-config-init {{required 1}} { if {[is-defined HAVE_PKG_CONFIG]} { return [get-define HAVE_PKG_CONFIG] } set found 0 define PKG_CONFIG [get-env PKG_CONFIG pkg-config] msg-checking "Checking for pkg-config..." if {[catch {exec [get-define PKG_CONFIG] --version} version]} { msg-result "[get-define PKG_CONFIG] (not found)" if {$required} { user-error "No usable pkg-config" } } else { msg-result $version define PKG_CONFIG_VERSION $version set found 1 if {[opt-val sysroot] ne ""} { define SYSROOT [file-normalize [opt-val sysroot]] msg-result "Using specified sysroot [get-define SYSROOT]" } elseif {[get-define build] ne [get-define host]} { if {[catch {exec-with-stderr [get-define CC] -print-sysroot} result errinfo] == 0} { # Use the compiler sysroot, if there is one define SYSROOT $result msg-result "Found compiler sysroot $result" } else { set msg "pkg-config: Cross compiling, but no compiler sysroot and no --sysroot supplied" if {$required} { user-error $msg } else { msg-result $msg } set found 0 } } if {[is-defined SYSROOT]} { set sysroot [get-define SYSROOT] # XXX: It's possible that these should be set only when invoking pkg-config global env set env(PKG_CONFIG_DIR) "" # Do we need to try /usr/local as well or instead? set env(PKG_CONFIG_LIBDIR) $sysroot/usr/lib/pkgconfig:$sysroot/usr/share/pkgconfig set env(PKG_CONFIG_SYSROOT_DIR) $sysroot } } define HAVE_PKG_CONFIG $found return $found } # @pkg-config module ?requirements? # # Use pkg-config to find the given module meeting the given requirements. # e.g. # ## pkg-config pango >= 1.37.0 # # If found, returns 1 and sets HAVE_PKG_PANGO to 1 along with: # ## PKG_PANGO_VERSION to the found version ## PKG_PANGO_LIBS to the required libs (--libs-only-l) ## PKG_PANGO_LDFLAGS to the required linker flags (--libs-only-L) ## PKG_PANGO_CFLAGS to the required compiler flags (--cflags) # # If not found, returns 0. # proc pkg-config {module args} { set ok [pkg-config-init] msg-checking "Checking for $module $args..." if {!$ok} { msg-result "no pkg-config" return 0 } if {[catch {exec [get-define PKG_CONFIG] --modversion "$module $args"} version]} { msg-result "not found" configlog "pkg-config --modversion $module $args: $version" return 0 } msg-result $version set prefix [feature-define-name $module PKG_] define HAVE_${prefix} define ${prefix}_VERSION $version define ${prefix}_LIBS [exec pkg-config --libs-only-l $module] define ${prefix}_LDFLAGS [exec pkg-config --libs-only-L $module] define ${prefix}_CFLAGS [exec pkg-config --cflags $module] return 1 } # @pkg-config-get module setting # # Convenience access to the results of pkg-config # # For example, [pkg-config-get pango CFLAGS] returns # the value of PKG_PANGO_CFLAGS, or "" if not defined. proc pkg-config-get {module name} { set prefix [feature-define-name $module PKG_] get-define ${prefix}_${name} "" } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ # All rights reserved # @synopsis: # # This module supports common system interrogation and options # such as --host, --build, --prefix, and setting srcdir, builddir, and EXEEXT # # It also support the 'feature' naming convention, where searching # for a feature such as sys/type.h defines HAVE_SYS_TYPES_H # # It defines the following variables, based on --prefix unless overridden by the user: # ## datadir ## sysconfdir ## sharedstatedir ## localstatedir ## infodir ## mandir ## includedir # Do "define defaultprefix myvalue" to set the default prefix *before* the first "use" set defaultprefix [get-define defaultprefix /usr/local] module-options [subst -noc -nob { host:host-alias => {a complete or partial cpu-vendor-opsys for the system where the application will run (defaults to the same value as --build)} build:build-alias => {a complete or partial cpu-vendor-opsys for the system where the application will be built (defaults to the result of running config.guess)} prefix:dir => {the target directory for the build (defaults to '$defaultprefix')} # These (hidden) options are supported for autoconf/automake compatibility exec-prefix: bindir: sbindir: includedir: mandir: infodir: libexecdir: datadir: libdir: sysconfdir: sharedstatedir: localstatedir: maintainer-mode=0 dependency-tracking=0 }] # Returns 1 if exists, or 0 if not # proc check-feature {name code} { msg-checking "Checking for $name..." set r [uplevel 1 $code] define-feature $name $r if {$r} { msg-result "ok" } else { msg-result "not found" } return $r } # @have-feature name ?default=0? # # Returns the value of the feature if defined, or $default if not. # See 'feature-define-name' for how the feature name # is translated into the define name. # proc have-feature {name {default 0}} { get-define [feature-define-name $name] $default } # @define-feature name ?value=1? # # Sets the feature 'define' to the given value. # See 'feature-define-name' for how the feature name # is translated into the define name. # proc define-feature {name {value 1}} { define [feature-define-name $name] $value } # @feature-checked name # # Returns 1 if the feature has been checked, whether true or not # proc feature-checked {name} { is-defined [feature-define-name $name] } # @feature-define-name name ?prefix=HAVE_? # # Converts a name to the corresponding define, # e.g. sys/stat.h becomes HAVE_SYS_STAT_H. # # Converts * to P and all non-alphanumeric to underscore. # proc feature-define-name {name {prefix HAVE_}} { string toupper $prefix[regsub -all {[^a-zA-Z0-9]} [regsub -all {[*]} $name p] _] } # If $file doesn't exist, or it's contents are different than $buf, # the file is written and $script is executed. # Otherwise a "file is unchanged" message is displayed. proc write-if-changed {file buf {script {}}} { set old [readfile $file ""] if {$old eq $buf && [file exists $file]} { msg-result "$file is unchanged" } else { writefile $file $buf\n uplevel 1 $script } } # @make-template template ?outfile? # # Reads the input file <srcdir>/$template and writes the output file $outfile. # If $outfile is blank/omitted, $template should end with ".in" which # is removed to create the output file name. # # Each pattern of the form @define@ is replaced with the corresponding # define, if it exists, or left unchanged if not. # # The special value @srcdir@ is substituted with the relative # path to the source directory from the directory where the output # file is created, while the special value @top_srcdir@ is substituted # with the relative path to the top level source directory. # # Conditional sections may be specified as follows: ## @if name == value ## lines ## @else ## lines ## @endif # # Where 'name' is a defined variable name and @else is optional. # If the expression does not match, all lines through '@endif' are ignored. # # The alternative forms may also be used: ## @if name ## @if name != value # # Where the first form is true if the variable is defined, but not empty or 0 # # Currently these expressions can't be nested. # proc make-template {template {out {}}} { set infile [file join $::autosetup(srcdir) $template] if {![file exists $infile]} { user-error "Template $template is missing" } # Define this as late as possible define AUTODEPS $::autosetup(deps) if {$out eq ""} { if {[file ext $template] ne ".in"} { autosetup-error "make_template $template has no target file and can't guess" } set out [file rootname $template] } set outdir [file dirname $out] # Make sure the directory exists file mkdir $outdir # Set up srcdir and top_srcdir to be relative to the target dir define srcdir [relative-path [file join $::autosetup(srcdir) $outdir] $outdir] define top_srcdir [relative-path $::autosetup(srcdir) $outdir] set mapping {} foreach {n v} [array get ::define] { lappend mapping @$n@ $v } set result {} foreach line [split [readfile $infile] \n] { if {[info exists cond]} { set l [string trimright $line] if {$l eq "@endif"} { unset cond continue } if {$l eq "@else"} { set cond [expr {!$cond}] continue } if {$cond} { lappend result $line } continue } if {[regexp {^@if\s+(\w+)(.*)} $line -> name expression]} { lassign $expression equal value set varval [get-define $name ""] if {$equal eq ""} { set cond [expr {$varval ni {"" 0}}] } else { set cond [expr {$varval eq $value}] if {$equal ne "=="} { set cond [expr {!$cond}] } } continue } lappend result $line } writefile $out [string map $mapping [join $result \n]]\n msg-result "Created [relative-path $out] from [relative-path $template]" } # build/host tuples and cross-compilation prefix set build [opt-val build] define build_alias $build if {$build eq ""} { define build [config_guess] } else { define build [config_sub $build] } set host [opt-val host] define host_alias $host if {$host eq ""} { define host [get-define build] set cross "" } else { define host [config_sub $host] set cross $host- } define cross [get-env CROSS $cross] set prefix [opt-val prefix $defaultprefix] # These are for compatibility with autoconf define target [get-define host] define prefix $prefix define builddir $autosetup(builddir) define srcdir $autosetup(srcdir) # Allow this to come from the environment define top_srcdir [get-env top_srcdir [get-define srcdir]] # autoconf supports all of these set exec_prefix [opt-val exec-prefix $prefix] define exec_prefix $exec_prefix foreach {name defpath} { bindir /bin sbindir /sbin libexecdir /libexec libdir /lib } { define $name [opt-val $name $exec_prefix$defpath] } foreach {name defpath} { datadir /share sysconfdir /etc sharedstatedir /com localstatedir /var infodir /share/info mandir /share/man includedir /include } { define $name [opt-val $name $prefix$defpath] } define SHELL [get-env SHELL [find-an-executable sh bash ksh]] # Windows vs. non-Windows switch -glob -- [get-define host] { *-*-ming* - *-*-cygwin - *-*-msys { define-feature windows define EXEEXT .exe } default { define EXEEXT "" } } # Display msg-result "Host System...[get-define host]" msg-result "Build System...[get-define build]" |
> > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # A small Tcl script to verify that the chosen # interpreter works. Sometimes we might e.g. pick up # an interpreter for a different arch. # Outputs the full path to the interpreter if {[catch {info version} version] == 0} { # This is Jim Tcl if {$version >= 0.72} { # Ensure that regexp works regexp (a.*?) a puts [info nameofexecutable] exit 0 } } elseif {[catch {info tclversion} version] == 0} { if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} { puts [info nameofexecutable] exit 0 } } exit 1 |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | # Copyright (c) 2016 WorkWare Systems http://www.workware.net.au/ # All rights reserved # Auto-load module for 'tmake' build system integration use init autosetup_add_init_type tmake "Tcl-based tmake build system" { autosetup_check_create auto.def \ {# Initial auto.def created by 'autosetup --init=tmake' # vim:set syntax=tcl: use cc cc-lib cc-db cc-shared use tmake # Add any user options here # Really want a --configure that takes over the rest of the command line options { } cc-check-tools ar ranlib set objdir [get-env BUILDDIR objdir] make-config-header $objdir/include/autoconf.h make-tmake-settings $objdir/settings.conf {[A-Z]*} } autosetup_check_create project.spec \ {# Initial project.spec created by 'autosetup --init=tmake' # vim:set syntax=tcl: define? DESTDIR _install # XXX If configure creates additional/different files than include/autoconf.h # that should be reflected here # We use [set AUTOREMAKE] here to avoid rebuilding settings.conf # if the AUTOREMAKE command changes Depends {settings.conf include/autoconf.h} auto.def -msg {note Configuring...} -do { run [set AUTOREMAKE] >$build/config.out } -onerror {puts [readfile $build/config.out]} -fatal Clean config.out DistClean --source config.log DistClean settings.conf include/autoconf.h # If not configured, configure with default options # Note that it is expected that configure will normally be run # separately. This is just a convenience for a host build define? AUTOREMAKE configure TOPBUILDDIR=$TOPBUILDDIR --conf=auto.def Load settings.conf # e.g. for up autoconf.h IncludePaths include ifconfig CONFIGURED # Hmmm, but should we turn off AutoSubDirs? #AutoSubDirs off } if {![file exists build.spec]} { puts "Note: I don't see build.spec. Try running: tmake --genie" } } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | # Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/ # All rights reserved # @synopsis: # # The 'tmake' module makes it easy to support the tmake build system. # # The following variables are set: # ## CONFIGURED - to indicate that the project is configured use system module-options {} define CONFIGURED # @make-tmake-settings outfile patterns ... # # Examines all defined variables which match the given patterns (defaults to "*") # and writes a tmake-compatible .conf file defining those variables. # For example, if ABC is "3 monkeys" and ABC matches a pattern, then the file will include: # ## define ABC {3 monkeys} # # If the file would be unchanged, it is not written. # # Typical usage is: # # make-tmake-settings [get-env BUILDDIR objdir]/settings.conf {[A-Z]*} proc make-tmake-settings {file args} { file mkdir [file dirname $file] set lines {} if {[llength $args] == 0} { set args * } foreach n [lsort [dict keys [all-defines]]] { foreach p $args { if {[string match $p $n]} { set value [get-define $n] lappend lines "define $n [list $value]" break } } } set buf [join $lines \n] write-if-changed $file $buf { msg-result "Created $file" } } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #!/bin/sh ######################################################################## # pidp8i.in - Attach the current terminal to the screen(1) session # started by the SysV init script in etc/pidp8i-ini. # # Copyright © 2015-2017 Oscar Vermeulen and Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## if [ "$USER" != "@INSTUSR@" ] ; then exec su -c "$0" @INSTUSR@ ; fi procs=`screen -ls pidp8i | egrep '[0-9]+\.pidp8i' | wc -l` if [ $procs -ne 0 ]; then echo Joining simulator session already in progress... screen -r else cat <<ERROR Either the simulator isn't running, or it isn't running under a screen(1) session owned by @INSTUSR@. Did you start it via the init script? ERROR fi |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ; This script initializes a populated OS/8 environment on an ; RK05 cartridge disk pack. That's 10 whole megabytes, so big ; the OS requires that you split it into two partitions in order ; to address the whole disk! Thus the "RKB0:" references you ; will find in tutorials, as that refers to the second half ("B") ; of the first ("0") RK05 cartridge disk. The default location ; the OS uses is formally called "RKA0:", alias "SYS:". ; ; See 3.script if you want to load OS/8 via DECtape instead. ; ; This file is read on simulator startup when the IF switches are ; set to 0, so it defines the default starting environment for the ; simulator. ; ; If you need to soft-restart the simulator back into OS/8 from some ; other state -- that is, you initially started the simulator with ; IF != 0 -- you can set IF = 7 and toggle the Sing_Step switch on ; and back off, which restarts the simulator with 7.script, which in ; turn loads this one. This somewhat clumsy arrangement is required ; because toggling Sing_Step with IF = 0 must not be made to restart ; the simulator, else there would be no way to use Sing_Step for any ; of its other functions. See the PiDP-8/I instructions for details. ; reset echo Loading OS/8 from the RK05 cartridge disk... set cpu 32k set cpu noidle set df disabled @SET_THROTTLE@ att rk0 @MEDIADIR@/os8/os8.rk05 boot rk0 |
> > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 | ; This script initializes a populated TSS/8 environment on an ; RS08 fixed-head hard disk drive (384 kB!) controlled by the ; RF08 disk controller. ; echo Loading TSS/8 from the RS08 fixed-head disk... load @MEDIADIR@/tss8/tss8_init.bin set rf enabled set df disabled set cpu noidle @SET_THROTTLE@ attach rf @MEDIADIR@/tss8/tss8_rf.dsk attach ttix 4000 run 24200 |
> > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 | ; Loads OS/8 from DECtape, as opposed to the RK05 based environment ; in 0.script. ; echo Loading OS/8 from DECtape... set df disabled set dt disabled set td enabled set cpu noidle @SET_THROTTLE@ attach td0 @MEDIADIR@/os8/os8.tu56 boot td0 |
> > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ; This script loads Spacewar! directly into core, without a supporting ; OS. ; echo Spacewar! echo echo Keyboard controls from the VC8E program: echo echo Player 1 Player 2 Command echo 1 9 fire weapon echo 2 0 rotate CCW echo 3 - rotate CW echo 4 = thrusters echo echo Press both rotate keys simulatenously to warp into hyperspace. echo echo Press Ctrl-E to pause the simulator and return to the SimH echo command prompt, where you can say "quit", "help" and other echo things. See the SimH manual for details. echo l @MEDIADIR@/spacewar/spacewar.bin set cpu noidle @SET_THROTTLE@ set df disabled at ttix 2222 set ttox0 8b g 200 |
> > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 | ; This script loads ETOS V5B from the RK05 cartridge disk drive. ; echo Loading ETOS from the RK05 cartridge disk drive... reset set cpu 32k set cpu noidle @SET_THROTTLE@ set df disabled set tsc enabled attach ttix 4000 att rk0 @MEDIADIR@/etos/etosv5b-demo.rk05 boot -d rk0 |
> > | 1 2 | echo Restarting the PiDP-8/I into its default operating environment... do @BOOTDIR@/0.script |
> > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | On startup, scanswitch passes the script number to run on to pidp8, based on the IF switch settings. Standard boot scripts: IF switches filename description ---------------------------------------------------------------------- 000 0.script : OS/8 on 32K PDP-8 with RK05 disk cartridge 001 1.script : RIM Loader installed at 7756 010 2.script : TSS/8 011 3.script : OS/8 on DECtape. This uses SLOW td0, not dt0 100 4.script : spacewar! with vc8e output on localhost:2222 101 5.script : (empty) 110 6.script : ETOS Multi-user on OS/8 boot disk 111 7.script : OS/8. Same as 0.script. ---------------------------------------------------------------------- Default initial startup script - when no IF switches are set is 0.script |
> > > | 1 2 3 | #!/bin/sh dir="`dirname "$0"`/autosetup" WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@" |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | The Raspbian OS images you can downlod from [the PiDP-8/I development site][1] install to an SD card in the same way as the [official Raspbian images][2]. Follow the [installation guide][3] published by the Raspberry Pi Foundation. You will need to use a 2 GB or larger SD card. The contents of the Zip file are: | File Name | Description |-------------------------------- | `README.md` | this file | `pidp8i-*.img` | the OS image, based on Raspbian Jessie Lite | `MANIFEST.txt` | SHA 256 hash and file size for the OS image file One small difference between these OS images and the ones that come from the Raspberry Pi Foundation is that mine have already booted once, so they won't automatically expand to fill your SD card's space. Simply run `sudo raspi-config` after your first boot and select the **Expand Filesystem** option, then reboot. Another difference is the default user name and password: * **username:** `pidp8i` * **password:** `edsonDeCastro1968` You will be made to change that password on first login. Remember, [the S in IoT stands for Security.][5] If we want security, we have to see to it ourselves! If you do not want your PiDP-8/I to be secure, see my other guide, "[How to Run a Nekkid PiDP-8/I][6]." [1]: https://tangentsoft.com/pidp8i/ [2]: https://raspberrypi.org/downloads/raspbian/ [3]: https://raspberrypi.org/documentation/installation/installing-images/ [4]: https://en.wikipedia.org/wiki/Internet_of_things [5]: http://www.testandverification.com/iot/s-iot-stands-security/ [6]: https://tangentsoft.com/pidp8i/wiki?name=How+to+Run+a+Naked+PiDP-8/I |
cannot compute difference between binary files
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | /*********************************************************************** led-decay.cpp - Proof of concept for an LED brightness decay algorithm that simulates the appearance of incandescent light bulbs when fed a stream of samples over a given time period. Copyright © 2016 Warren Young Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the names of the authors above shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from those authors. ***********************************************************************/ #include <iostream> #include <vector> using namespace std; typedef vector<bool> vb; typedef vb::const_iterator vbc; // Keeping n samples. To think about this concretely, imagine that it // is 1 sample per millisecond over 0.1 sec, but realize that this is // scaleable, so that how long 1/n seconds is doesn't affect the math. static const size_t n = 100; // Decay function is 1 - x^2, meaning the most recent event is // considered 100%, with older events having increasingly lesser effect // on the overall brightness until we hit 0% consideration at the end of // the sample set. // // We need to scale that so that the total area under the decay // function's curve is 1, so that if we feed a 50% duty cycle in, we // get 50% out, but if we skew the 1s toward the front of the sample // set (i.e. closer to "now"), we get greater brightness than if they // are skewed toward the past. // // The Pi ships with Mathematica, which answers this question with: // // Solve[Integrate[z * (1 - x^2), {x, 0, 1}] == 1, z] // // We get z = 1.5. // // If you want a different decay function, it needs to substitute for // the 1 - x^2 bit. It needs to start at 1 and decay to 0 over the // range [0 <= x <= 1]. Run that through Mathematica to find the // resulting value of z that gives a total of 1 over the sample span. static double f(double x, bool v) { return v ? (1.5 * (1 - x * x)) : 0; } // Given n bits representing the state of the LED at time x=1/n, return // the total of applications of f on each bit. Order is most recent // event first, so it takes the strongest effect. static double cdf(const vb& vl) { double t = 0; for (size_t i = 0; i < n; ++i) { // We divide each f() return by n because it represents only 1/n // of the total area under the curve. This is a crude form of // numeric integration. t += f(i / double(n), vl[i]) / n; } return t; } // Generate a series of sampled LED values, then run those sample sets // through the above and show what brightness level that would generate. int main() { vb values(n); values.clear(); for (size_t i = 0; i < n; ++i) { values.push_back(true); } cout << "100% duty cycle: CDF = " << cdf(values) << endl; values.clear(); for (size_t i = 0; i < n; ++i) { values.push_back(i % 2 == 0); } cout << "50% duty cycle: CDF = " << cdf(values) << endl; values.clear(); for (size_t i = 0; i < n; ++i) { values.push_back(i % 4 == 0); } cout << "25% duty cycle: CDF = " << cdf(values) << endl; values.clear(); for (size_t i = 0; i < n; ++i) { values.push_back(i % 10 == 0); } cout << "10% duty cycle: CDF = " << cdf(values) << endl; values.assign(n, false); for (size_t i = 0; i < n / 2; ++i) { values[i] = true; } cout << "First half 'on': CDF = " << cdf(values) << endl; values.assign(n, false); for (size_t i = n / 2; i < n; ++i) { values[i] = true; } cout << "Second half 'on': CDF = " << cdf(values) << endl; values.assign(n, false); values[0] = true; cout << "1ms spike at the start: CDF = " << cdf(values) << endl; values.assign(n, false); values[n - 1] = true; cout << "1ms spike at the end: CDF = " << cdf(values) << endl; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | # PCB Test Program ## Compiling and Installing `pidp8i-test` is a simple program to test [Oscar Vermeulen's PiDP-8/I Kit][project] during construction. It is built and installed alongside the other software with the normal `make` process. ## Running It If you are building the software on the Pi for the first time, log out of your user account after installing it, then back in so that the install script's changes to your user's `PATH` take effect. Thereafter, simply give these commands: $ sudo systemctl stop pidp8i $ pidp8i-test The first command ensures that the modified PDP-8 simulator is stopped during the test, since only one program can be talking to the switch and LED array at a given time. (This also applies to other programs like [Deeper Thought 2][dt2].) ## Test Procedure You can at any time hit Ctrl-C to stop the test. The test proceeds as follows: * All On test: It turns on all LEDs for 5 seconds. * All Off test: It turns off all LEDs for 5 seconds. * Row test: It turns on one full row of LEDs and pauses for 5 seconds, then switches to the next row. There are eight rows of LEDs of up to 12 LEDs each. * Column test: It then turns on one full column of LEDs and pauses for 5 seconds, then switches to the next column. There are 12 columns of LEDs with up to 8 LEDs each. (Some of the LEDs positions in a column are sometimes rather chaotic, it will require intimate knowledge of the schematic to verify. It's somewhat of a useless test but it might turn up an assembly error for someone.) * Switch test: It then goes into a single LED chase pattern and starts looking at switches. This loop is infinite. Every time it detects a change in the switch positions it prints out the full Octal bit pattern for the three switch banks. No attempt is made to name the actual switch that has been flipped. The goal is to verify switch functionality, not to debug the design of the circuit or the driver. When running this test, if you get a new line printed with a single bit change when you flip a single switch, the switch in question is working. If you get no output printed or multiple bits changed in the output printed something is wrong. If for some reason you need to decode the output bits to physical switches they appear as follows: | A | B | C |------------------- | 4000 | 0000 | 0000 The first twelve bits (labelled A) is the Switch Register. The bits left to right correspond to the SR switches also left to right. So above the SR1 switch is toggled down, ie 1. Every other SR switch is up, ie 0. The leftmost 6 bits (labelled B) are the 3 DF switches followed by the 3 IF switches. Again left to right. The rest of the bits are unused in the B section. The leftmost 8 bits (labelled C) are the remaining 8 switches starting at "START" and ending at "SING INST". Again Left to right. ## License This document is licensed under the same terms as the associated [`src/test.c` program][program]. [project]: http://obsolescence.wix.com/obsolescence#!pidp-8 [dt2]: https://github.com/VentureKing/Deeper-Thought-2 [program]: https://tangentsoft.com/pidp8i/doc/trunk/src/test.c |
cannot compute difference between binary files
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="673.51404" height="613.08057" viewBox="0 0 673.51405 613.08058" id="svg2" version="1.1" inkscape:version="0.91 r13725" sodipodi:docname="vtedit-keypad.svg" inkscape:export-filename="/usr/local/src/pidp8i/trunk/doc/vtedit-keypad.png" inkscape:export-xdpi="80.18" inkscape:export-ydpi="80.18"> <title id="title4295">VTEDIT Keypad Diagram</title> <defs id="defs4"> <linearGradient inkscape:collect="always" id="linearGradient4138"> <stop style="stop-color:#dbb56a;stop-opacity:0.70833331" offset="0" id="stop4140" /> <stop style="stop-color:#f0e6da;stop-opacity:1" offset="1" id="stop4142" /> </linearGradient> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4144" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" gradientUnits="userSpaceOnUse" gradientTransform="translate(-72.931483,8.918583)" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4254" gradientUnits="userSpaceOnUse" gradientTransform="translate(39.142981,8.918583)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4272" gradientUnits="userSpaceOnUse" gradientTransform="translate(151.21744,8.918583)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4324" gradientUnits="userSpaceOnUse" gradientTransform="translate(-72.931483,120.43745)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4326" gradientUnits="userSpaceOnUse" gradientTransform="translate(39.142981,120.43745)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4328" gradientUnits="userSpaceOnUse" gradientTransform="translate(151.21744,120.43745)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4380" gradientUnits="userSpaceOnUse" gradientTransform="translate(-72.931483,231.9563)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4382" gradientUnits="userSpaceOnUse" gradientTransform="translate(39.142981,231.9563)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4384" gradientUnits="userSpaceOnUse" gradientTransform="translate(151.21744,231.9563)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4434" gradientUnits="userSpaceOnUse" gradientTransform="translate(263.2919,8.761662)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4436" gradientUnits="userSpaceOnUse" gradientTransform="translate(263.2919,120.1236)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4438" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,0,0,2.1178002,263.2919,83.80932)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4504" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.1255986,0,0,1,-190.0452,343.47519)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4508" gradientUnits="userSpaceOnUse" gradientTransform="translate(151.21744,343.47519)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4611" gradientUnits="userSpaceOnUse" gradientTransform="translate(-72.931483,-102.60028)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4613" gradientUnits="userSpaceOnUse" gradientTransform="translate(39.142981,-102.60028)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4615" gradientUnits="userSpaceOnUse" gradientTransform="translate(151.21744,-102.60028)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> <linearGradient inkscape:collect="always" xlink:href="#linearGradient4138" id="linearGradient4617" gradientUnits="userSpaceOnUse" gradientTransform="translate(263.2919,-102.60028)" x1="153.5432" y1="135.14371" x2="154.55334" y2="231.10818" /> </defs> <sodipodi:namedview id="base" pagecolor="#fcfaf0" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="1" inkscape:pageshadow="2" inkscape:zoom="1.4" inkscape:cx="237.26909" inkscape:cy="345.9566" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" inkscape:window-width="2560" inkscape:window-height="1391" inkscape:window-x="0" inkscape:window-y="1" inkscape:window-maximized="1" showguides="true" inkscape:guide-bbox="true" units="px" fit-margin-top="32" fit-margin-left="32" fit-margin-right="32" fit-margin-bottom="32" /> <metadata id="metadata7"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title>VTEDIT Keypad Diagram</dc:title> <cc:license rdf:resource="https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md" /> <dc:date>December 2016</dc:date> <dc:creator> <cc:Agent> <dc:title>Warren Young</dc:title> </cc:Agent> </dc:creator> <dc:contributor> <cc:Agent> <dc:title>This graphical diagram was created based on an ASCII diagram that came with the version of VTEDIT patched for VT100/ANSI terminals.</dc:title> </cc:Agent> </dc:contributor> <dc:rights> <cc:Agent> <dc:title>see ../SIMH-LICENSE.md</dc:title> </cc:Agent> </dc:rights> <dc:language>Englis</dc:language> <dc:subject> <rdf:Bag> <rdf:li>VTEDIT</rdf:li> <rdf:li>PDP-8</rdf:li> <rdf:li>diagram</rdf:li> <rdf:li>keypad</rdf:li> </rdf:Bag> </dc:subject> <dc:description>Diagram showing the function of the keypad keys when pressed in the version of VTEDIT patched for VT100/ANSI terminals.</dc:description> </cc:Work> </rdf:RDF> </metadata> <g inkscape:groupmode="layer" id="layer5" inkscape:label="key caps" style="display:inline" transform="translate(17.282791,22)"> <rect transform="translate(-14.897034,-18.012959)" style="opacity:1;fill:url(#linearGradient4144);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect4136" width="98.994949" height="100.0051" x="31.114243" y="141.03181" ry="10.357149" rx="11.25" /> <rect transform="translate(-14.897034,-18.012959)" rx="11.25" ry="10.357149" y="141.03181" x="143.18871" height="100.0051" width="98.994949" id="rect4240" style="opacity:1;fill:url(#linearGradient4254);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> <rect transform="translate(-14.897034,-18.012959)" style="opacity:1;fill:url(#linearGradient4272);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect4258" width="98.994949" height="100.0051" x="255.26317" y="141.03181" ry="10.357149" rx="11.25" /> <rect transform="translate(-14.897034,-18.012959)" rx="11.25" ry="10.357149" y="252.55069" x="31.114243" height="100.0051" width="98.994949" id="rect4278" style="opacity:1;fill:url(#linearGradient4324);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> <rect transform="translate(-14.897034,-18.012959)" style="opacity:1;fill:url(#linearGradient4326);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect4294" width="98.994949" height="100.0051" x="143.18871" y="252.55069" ry="10.357149" rx="11.25" /> <rect transform="translate(-14.897034,-18.012959)" rx="11.25" ry="10.357149" y="252.55069" x="255.26317" height="100.0051" width="98.994949" id="rect4310" style="opacity:1;fill:url(#linearGradient4328);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> <rect transform="translate(-14.897034,-18.012959)" style="opacity:1;fill:url(#linearGradient4380);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect4334" width="98.994949" height="100.0051" x="31.114243" y="364.06955" ry="10.357149" rx="11.25" /> <rect transform="translate(-14.897034,-18.012959)" rx="11.25" ry="10.357149" y="364.06955" x="143.18871" height="100.0051" width="98.994949" id="rect4350" style="opacity:1;fill:url(#linearGradient4382);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> <rect transform="translate(-14.897034,-18.012959)" style="opacity:1;fill:url(#linearGradient4384);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect4366" width="98.994949" height="100.0051" x="255.26317" y="364.06955" ry="10.357149" rx="11.25" /> <rect transform="translate(-14.897034,-18.012959)" rx="11.25" ry="10.357149" y="140.87489" x="367.33762" height="100.0051" width="98.994949" id="rect4388" style="opacity:1;fill:url(#linearGradient4434);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> <rect transform="translate(-14.897034,-18.012959)" style="opacity:1;fill:url(#linearGradient4436);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect4404" width="98.994949" height="100.0051" x="367.33762" y="252.23683" ry="10.357149" rx="11.25" /> <rect transform="translate(-14.897034,-18.012959)" rx="11.25" ry="10.35715" y="363.59879" x="367.33762" height="211.79082" width="98.994949" id="rect4420" style="opacity:1;fill:url(#linearGradient4438);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3.00000024;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> <rect transform="translate(-14.897034,-18.012959)" rx="11.249999" ry="10.357149" y="475.58841" x="31.114243" height="100.0051" width="210.42351" id="rect4442" style="opacity:1;fill:url(#linearGradient4504);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:2.99999976;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> <rect transform="translate(-14.897034,-18.012959)" rx="11.25" ry="10.357149" y="475.58844" x="255.26317" height="100.0051" width="98.994949" id="rect4474" style="opacity:1;fill:url(#linearGradient4508);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> <rect transform="translate(-14.897034,-18.012959)" rx="11.25" ry="10.357149" y="29.512959" x="31.114243" height="100.0051" width="98.994949" id="rect4549" style="opacity:1;fill:url(#linearGradient4611);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> <rect transform="translate(-14.897034,-18.012959)" style="opacity:1;fill:url(#linearGradient4613);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect4565" width="98.994949" height="100.0051" x="143.18871" y="29.512959" ry="10.357149" rx="11.25" /> <rect transform="translate(-14.897034,-18.012959)" rx="11.25" ry="10.357149" y="29.512959" x="255.26317" height="100.0051" width="98.994949" id="rect4581" style="opacity:1;fill:url(#linearGradient4615);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> <rect transform="translate(-14.897034,-18.012959)" style="opacity:1;fill:url(#linearGradient4617);fill-opacity:1;fill-rule:nonzero;stroke:#eee0ca;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect4597" width="98.994949" height="100.0051" x="367.33762" y="29.512959" ry="10.357149" rx="11.25" /> </g> <g inkscape:groupmode="layer" id="layer6" inkscape:label="key labels" style="display:inline" transform="translate(17.282791,22)"> <flowRoot xml:space="preserve" id="flowRoot4217" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(-86.06075,-4.043613)"><flowRegion id="flowRegion4219"><rect id="rect4221" width="86.785713" height="87.678574" x="110" y="137.71935" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara id="flowPara4223" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">7</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4227">Open</flowPara><flowPara id="flowPara4623" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Line◆</flowPara></flowRoot> <flowRoot transform="translate(26.013714,-4.043613)" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="flowRoot4242" xml:space="preserve"><flowRegion id="flowRegion4244"><rect y="137.71935" x="110" height="87.678574" width="86.785713" id="rect4246" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4248">8</flowPara><flowPara id="flowPara4252" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Page◆</flowPara></flowRoot> <flowRoot xml:space="preserve" id="flowRoot4260" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(138.08818,-4.043613)"><flowRegion id="flowRegion4262"><rect id="rect4264" width="86.785713" height="87.678574" x="110" y="137.71935" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara id="flowPara4266" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">9</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4270">Mark/</flowPara><flowPara id="flowPara4629" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Quote◆</flowPara></flowRoot> <flowRoot transform="translate(-86.06075,107.47526)" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="flowRoot4280" xml:space="preserve"><flowRegion id="flowRegion4282"><rect y="137.71935" x="110" height="87.678574" width="86.785713" id="rect4284" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4286">4</flowPara><flowPara id="flowPara4290" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Up</flowPara><flowPara id="flowPara4633" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Line◆</flowPara></flowRoot> <flowRoot xml:space="preserve" id="flowRoot4296" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(26.013714,107.47526)"><flowRegion id="flowRegion4298"><rect id="rect4300" width="86.785713" height="87.678574" x="110" y="137.71935" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara id="flowPara4302" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">5</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4306">Delete</flowPara><flowPara id="flowPara4637" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Char◆</flowPara></flowRoot> <flowRoot transform="translate(138.08818,107.47526)" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="flowRoot4312" xml:space="preserve"><flowRegion id="flowRegion4314"><rect y="137.71935" x="110" height="87.678574" width="86.785713" id="rect4316" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4318">6</flowPara><flowPara id="flowPara4322" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Delete/</flowPara><flowPara id="flowPara4641" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Restore</flowPara></flowRoot> <flowRoot xml:space="preserve" id="flowRoot4336" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(-86.06075,218.99411)"><flowRegion id="flowRegion4338"><rect id="rect4340" width="86.785713" height="87.678574" x="110" y="137.71935" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara id="flowPara4342" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">1</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4344">Top of</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4346">Page◆•</flowPara></flowRoot> <flowRoot transform="translate(26.013714,218.99411)" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="flowRoot4352" xml:space="preserve"><flowRegion id="flowRegion4354"><rect y="137.71935" x="110" height="87.678574" width="86.785713" id="rect4356" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4358">2</flowPara><flowPara id="flowPara4360" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Bottom</flowPara><flowPara id="flowPara4362" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">of Page</flowPara></flowRoot> <flowRoot xml:space="preserve" id="flowRoot4368" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(138.08818,218.99411)"><flowRegion id="flowRegion4370"><rect id="rect4372" width="86.785713" height="87.678574" x="110" y="137.71935" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara id="flowPara4374" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">3</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4376">Start</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4378">of Line</flowPara></flowRoot> <flowRoot transform="translate(250.16264,-4.200534)" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="flowRoot4390" xml:space="preserve"><flowRegion id="flowRegion4392"><rect y="137.71935" x="110" height="87.678574" width="86.785713" id="rect4394" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4396">-</flowPara><flowPara id="flowPara4398" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Search</flowPara><flowPara id="flowPara4400" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Arg◆</flowPara></flowRoot> <flowRoot xml:space="preserve" id="flowRoot4406" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(250.16264,107.16141)"><flowRegion id="flowRegion4408"><rect id="rect4410" width="86.785713" height="87.678574" x="110" y="137.71935" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara id="flowPara4412" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">,</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4414">End of</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4416">Line</flowPara></flowRoot> <flowRoot transform="translate(250.16264,276.73764)" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="flowRoot4422" xml:space="preserve"><flowRegion id="flowRegion4424"><rect y="137.71935" x="110" height="87.678574" width="86.785713" id="rect4426" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4428">Enter</flowPara><flowPara id="flowPara4430" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Search</flowPara><flowPara id="flowPara4432" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Arg◆</flowPara></flowRoot> <flowRoot transform="translate(-33.203607,330.513)" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="flowRoot4444" xml:space="preserve"><flowRegion id="flowRegion4446"><rect y="137.71935" x="110" height="87.678574" width="86.785713" id="rect4448" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4450">0</flowPara><flowPara id="flowPara4454" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Down</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4523">Line◆</flowPara></flowRoot> <flowRoot transform="translate(138.08818,330.513)" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="flowRoot4476" xml:space="preserve"><flowRegion id="flowRegion4478"><rect y="137.71935" x="110" height="87.678574" width="86.785713" id="rect4480" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4482">.</flowPara><flowPara id="flowPara4484" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Search</flowPara><flowPara id="flowPara4486" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Again◆</flowPara></flowRoot> <flowRoot transform="translate(-86.06075,-115.56247)" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="flowRoot4551" xml:space="preserve"><flowRegion id="flowRegion4553"><rect y="137.71935" x="110" height="87.678574" width="86.785713" id="rect4555" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4557">PF1</flowPara><flowPara id="flowPara4559" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Save</flowPara><flowPara id="flowPara4561" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Text◆•</flowPara></flowRoot> <flowRoot xml:space="preserve" id="flowRoot4567" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(26.013714,-115.56247)"><flowRegion id="flowRegion4569"><rect id="rect4571" width="86.785713" height="87.678574" x="110" y="137.71935" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara id="flowPara4573" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">PF2</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4575">TECO</flowPara><flowPara style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4577">Cmd◆</flowPara></flowRoot> <flowRoot transform="translate(138.08818,-115.56247)" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="flowRoot4583" xml:space="preserve"><flowRegion id="flowRegion4585"><rect y="137.71935" x="110" height="87.678574" width="86.785713" id="rect4587" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4589">PF3</flowPara><flowPara id="flowPara4591" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Paste</flowPara><flowPara id="flowPara4593" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1">Text</flowPara></flowRoot> <flowRoot xml:space="preserve" id="flowRoot4599" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(250.16264,-115.56247)"><flowRegion id="flowRegion4601"><rect id="rect4603" width="86.785713" height="87.678574" x="110" y="137.71935" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" /></flowRegion><flowPara style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:22.5px;font-family:Verdana;-inkscape-font-specification:Verdana;text-align:center;text-anchor:middle;fill:#422b00;fill-opacity:1" id="flowPara4609">PF4</flowPara></flowRoot> </g> <g inkscape:label="KEY" inkscape:groupmode="layer" id="layer1" transform="translate(2.3857574,3.9870415)" style="display:inline"> <text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="153.57143" y="180.93362" id="text4213" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4215" x="153.57143" y="180.93362" /></text> <text xml:space="preserve" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="503.61438" y="56.824276" id="text4643" sodipodi:linespacing="125%"><tspan sodipodi:role="line" x="503.61438" y="56.824276" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:20px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" id="tspan4701">KEY</tspan></text> <text sodipodi:linespacing="125%" id="text5371" y="183.68143" x="503.61438" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" xml:space="preserve"><tspan id="tspan5385" dy="1" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.5px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" y="183.68143" x="503.61438" sodipodi:role="line">• command</tspan><tspan id="tspan5387" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.5px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" y="205.55643" x="503.61438" sodipodi:role="line"> operates</tspan><tspan id="tspan5389" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.5px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" y="227.43143" x="503.61438" sodipodi:role="line"> from Dot to</tspan><tspan id="tspan5391" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.5px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" y="249.30643" x="503.61438" sodipodi:role="line"> Mark if Mark</tspan><tspan id="tspan5393" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.5px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" y="271.18143" x="503.61438" sodipodi:role="line"> is set</tspan></text> <text xml:space="preserve" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:Verdana;-inkscape-font-specification:Verdana;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#422b00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="503.61438" y="88.967133" id="text5395" sodipodi:linespacing="125%"><tspan sodipodi:role="line" x="503.61438" y="88.967133" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.5px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" id="tspan5399">◆ takes opt arg</tspan><tspan sodipodi:role="line" x="503.61438" y="111.48743" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.5px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" id="tspan5401"> as: ESC [-]</tspan><tspan sodipodi:role="line" x="503.61438" y="133.36243" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.5px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" id="tspan5403"> <digits></tspan><tspan sodipodi:role="line" x="503.61438" y="155.23743" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.5px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" id="tspan5405"> <key(s)></tspan><tspan sodipodi:role="line" x="503.61438" y="177.11243" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.5px;font-family:Verdana;-inkscape-font-specification:Verdana;fill:#422b00;fill-opacity:1" id="tspan5417" /></text> </g> </svg> |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | #!/bin/sh ### BEGIN INIT INFO # Provides: pidp8i # Required-Start: $syslog # Required-Stop: $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 6 # Short-Description:PiDP-8/I simulator # Description: The PiDP-8/I simulator is a modified version of # the SimH PDP-8 simulator for the PiDP-8/I front # panel project for the Raspberry Pi. ### END INIT INFO ######################################################################## # Init script for Oscar Vermeulen's PiDP-8/I emulator front panel. # # Original author: Mark G Thomas <mark@misty.com> 2015-05-09 # # Copyright © 2015 Mark G Thomas # Copyright © 2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## PATH=/sbin:/usr/sbin:/bin:/usr/bin umask 022 . /lib/lsb/init-functions prefix="@ABSPREFIX@" sim="$prefix/bin/pidp8i-sim" scanswitch="$prefix/libexec/scanswitch" # Requires screen utility for detached pidp8i console functionality. test -x /usr/bin/screen || ( echo "screen not found" && exit 0 ) # Also check for other needed binaries test -x $scanswitch || ( echo "$scanswitch not found" && exit 0 ) test -x $sim || ( echo "$sim not found" && exit 0 ) # Check if pidp8i is already runnning under screen. # is_running() { procs=`screenu -ls pidp8i | egrep '[0-9]+\.pidp8i' | wc -l` test $procs -gt 0 && return 0 || return 1 } # Wrapper around screen(1) to drop privileges and pass given args screenu() { if [ "$USER" = "@INSTUSR@" ] then /usr/bin/screen $* else su -c "/usr/bin/screen $*" @INSTUSR@ fi } do_start() { if is_running ; then echo "PiDP-8/I is already running, not starting again." >&2 exit 0 fi # Regenerate SSH host keys if this is the first run on a fresh image if [ ! -f /etc/ssh/ssh_host_ecdsa_key -a -x /usr/sbin/dpkg-reconfigure ] then log_daemon_msg "Regenerating SSH host keys..." "pidp8i" /usr/sbin/dpkg-reconfigure openssh-server fi $scanswitch >/dev/null 2>&1 script=$? if [ $script -eq 8 ]; then echo "PiDP-8/I STOP switch detected, aborting." >&2 exit 0 elif [ $script -lt 8 ]; then bscript="@BOOTDIR@/""$script"".script" echo "Booting from $bscript..." else echo "Bad return value $script from $scanswitch!" exit 1 fi # We want SIMH to have a sensible working directory: somewhere the # user can write files and which makes sense when giving SIMH # commands involving file paths. This default is chosen because it # satisfies both criteria, plus it makes tools/mk-os8-rk05s happy. # If you change the default here, change that script as well. cd "$prefix/share/media" log_daemon_msg "Starting PiDP-8/I simulator" "pidp8i" screenu -dmS pidp8i "$sim" $bscript status=$? log_end_msg $status return $status } do_stop() { if ! is_running ; then echo "PiDP-8/I is already stopped." >&2 status=1 else log_daemon_msg "Stopping PiDP-8/I simulator" "pidp8i" screenu -S pidp8i -X quit status=$? log_end_msg $status fi return $status } case "$1" in start) do_start ;; stop) do_stop ;; restart) do_stop do_start ;; status) screenu -ls pidp8i | egrep '[0-9]+\.pidp8i' ;; *) log_action_msg "Usage: /etc/init.d/pidp8i {start|stop|restart|status}" || true exit 1 esac exit 0 |
> > | 1 2 | @INSTUSR@ ALL=NOPASSWD: /bin/systemctl poweroff @INSTUSR@ ALL=NOPASSWD: /bin/systemctl reboot |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | ######################################################################## # Makefile.in - Processed by autosetup's configure script to generate # an intermediate GNU make(1) file for building the PiDP-8/I software # from within its examples/ subdirectory. # # The resulting Makefile will redirect simple "make" calls to the top # level as well as the major top-level targets (e.g. "make clean") but # purposefully will not redirect anything like an installation or "run # the system" type target. Its only purpose is to help out those who # are working on the examples from within this directory. If you need # to work on the wider system, do it from the project's top level. # # If you are seeing this at the top of a file called Makefile and you # intend to make edits, do that in Makefile.in. Saying "make" will then # re-build Makefile from that modified Makefile.in before proceeding to # do the "make" operation. # # Copyright © 2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## all clean ctags distclean tags reconfig: cd @builddir@; make $@ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | # Example Programs ## What's Provided The `examples` directory holds short example programs for your PiDP-8/I, plus a number of subroutines you may find helpful in writing your own programs: | Example | What It Does ----------------------------- | `add.pal` | 2 + 3 = 5 The simplest program here; used below as a meta-example | `hello.pal` | writes "HELLO, WORLD!" to the console; tests PRINTS subroutine | `pep001.*` | Project Euler Problem #1 solutions, various languages | `routines/decprt` | prints an unsigned 12-bit decimal integer to the console | `routines/prints` | prints an ASCIIZ string stored as a series of 8-bit bytes to the console The `pep001.*` files are a case study series in solving a simple problem, which lets you compare the solutions along several axes. Some are much longer than others, but some will run faster and/or take less memory. It is interesting to compare them. There are writeups on each of these: * [**`pep001.pal`**][pal] — PAL8 Assembly Language * [**`pep001.bas`**][bas] — OS/8 BASIC [pal]: https://tangentsoft.com/pidp8i/wiki?name=PEP001.PA [bas]: https://tangentsoft.com/pidp8i/wiki?name=PEP001.BA ## How to Use the BASIC Examples To use the example BASIC program, simply transcribe it into OS/8 BASIC: .R BASIC NEW OR OLD--NEW FILE NAME--PAL001.BA READY 10 FOR I = 1 TO 999 10 FOR I = 1 TO 999 20 A = I / 3 \ B = I / 5 30 IF INT(A) = A GOTO 60 40 IF INT(B) = B GOTO 60 50 GOTO 70 60 T = T + I 70 NEXT I 80 PRINT "TOTAL: "; T 90 END SAVE READY RUN PAL001 BA 4A TOTAL: xxxxxxx READY BYE If you're SSH'd into the PiDP-8/I, "transcribing" is simply a matter of cut-and-paste into the terminal window. I've obscured the output on purpose, since I don't want this page to be a spoiler for the Project Euler site. If you get a 2-letter code from BASIC in response to your `RUN` command, it means you have an error in the program. See the BASIC section of the OS/8 Handbook for a decoding guide. ## How to Use the Assembly Language Examples For each PAL8 assembly program in `examples/*.pal`, there are two additional files: | Extension | Meaning ----------------------------- | `*.pal` | the PAL8 assembly source code for the program | `*.lst` | the human-readable assembler output | `*.pt` | the machine-readable assembler output (RIM format) There are three ways to run these on your PiDP-8/I, each starting with one of the above three files: 1. Transcribe the assembly program text to a file within a PDP-8 operating system and assemble it inside the simulator. 2. Toggle the program in from the front panel. I can recommend this method only for very short programs. 3. Copy the `*.pt` file to a USB stick and use the PiDP-8/I's [automatic media mounting feature][howto]. This is the fastest method. I cover each of these options below, in the same order as the list above. ## Option 1: Transcribing the Assembly Code into an OS/8 Session To transcribe [`examples/add.pal`][pal] into the OS/8 simulation on a PiDP-8/I: .R EDIT *ADD.PA< #A ← append to ADD.PA *0200 CLA CLL MAIN, TAD A TAD B DCA C HLT A, 2 B, 3 C, ← hit Ctrl-L to leave text edit mode #E ← saves program text to disk .PAL ADD-LS ERRORS DETECTED: 0 LINKS GENERATED: 0 .DIR ADD.* /A ADD .PA 1 ADD .BN 1 ADD .LS 1 399 FREE BLOCKS If you see some cryptic line from the assembler like `DE C` instead of the `ERRORS DETECTED: 0` bit, an error has occurred. Table 3-3 in my copy the OS/8 Handbook explains these. You will also have an `ADD.ER` file explaining what happened. You can instead say `EXE ADD` to assemble and execute that program in a single step, but beware that because the program halts the processor, your OS/8 session also halts. If you take the opportunity as intended to examine memory location `C` — 0207 — pressing `Start` to resume will cause the processor to try executing the instruction at 0210, and who knows what that will do? Even if you pass up the opportunity to examine `C`, pressing `Start` immediately after the halt will do the same, except that we know what it will do: it will try to execute the 0002 value stored at `A` as an instruction! (I believe it means `AND` the accumulator with memory location 2.) The solution to these problems is simple: .EDIT ADD ← don't need "R" because file exists #R ← read first page in; isn't automatic! #4D ← get rid of that pesky DCA line #5I ← insert above "A" def'n, now on line 5 JMP 7600 ← Ctrl-L again to exit edit mode #E ← save and exit .EXE ADD As before, the processor stops, but this time because we didn't move the result from the accumulator to memory location `C`, we can see the answer on the accumulator line on the front panel. Pressing `Start` this time continues to the next instruction which re-enters OS/8. Much nicer! As you can see, this option is the most educational, as it matches the working experience of PDP-8 assembly language programmers back in the day. The tools may differ — the user may prefer `TECO` over `EDIT` or MACRO-8 over PAL8 — but the idea is the same regardless. If you have the finished assembly code already on your computer and are SSH'd into the PiDP-8/I machine, there is a shortcut for all of the above. At the OS/8 command line, say: .R PIP *ADD.PA<TTY: Now you can simply copy the assembly language text in your desktop PC's text editor, paste it into the SSH window, and then hit Ctrl-Z to tell `PIP` that the text input from the terminal (`TTY:`) is finished. This is not only a smidge simpler than doing the same thing via `EDIT`, it also avoids a certain limitation of `EDIT` that starts to bite you once your program text exceeds about 5,600 characters. ## Option 2: Toggling a Programs in Via the Front Panel After building the PiDP-8/I software, each of the `examples/*.pal` files is assembled by `palbart` which writes out a human-readable listing file to `obj/*.lst`, named after the source file. Take [`obj/add.lst`][lst] as an example, in which you will find three columns of numbers on the code-bearing lines: 10 00200 7300 11 00201 1205 12 00202 1206 13 00203 3207 14 00204 7402 16 00205 0002 17 00206 0003 The first number refers to the corresponding line number in [`add.pal`][pal], the second is a PDP-8 memory address, and the third is the value stored at that address. To toggle the `add` program in, press `Stop` to halt the processor, then twiddle the switches like so: | Set SR Switches To... | Then Toggle... |------------------------------------------------ | 000 010 000 000 | `Load Add` | 111 011 000 000 | `Dep` | 001 010 000 101 | `Dep` | 001 010 000 110 | `Dep` | 011 010 000 111 | `Dep` | 111 100 000 010 | `Dep` | 000 000 000 010 | `Dep` | 000 000 000 011 | `Dep` To run it, repeat the first step in the table above, loading the program's starting address (0200) first into the switch register (SR) and then into the PDP-8's program counter (PC) via `Load Add`. Then toggle `Start` to run the program. If you then: If you then toggle 000 010 000 111 into SR, press `Load Add` followed by `Exam`, you should see 000 000 000 101 in the third row of lights, the bit pattern for five at memory location 0207, that being the correct answer for "2 + 3" in the expected location, which is what we expected `add.pal` to do. You could load that address back up again and `Dep` a different value into that location, then start the program over again at 0200 to observe that this memory location does, indeed, get overwritten with 0005. We only need one `Load Add` operation in the table above because all of the memory addresses in this program are sequential; there are no jumps in the values in the second column. Not all programs are that way, so pay attention! Beware that this program does not contain an explicit value for memory location 0207 at the start, but it does overwrite this location with the answer, since location `C` is defined as having the address just after the last value you entered via SR above, 0206. That is the source of the "07" in the lower two digits of the fourth instruction, 3207. ## Option 3: Loading a Program from Paper Tape The `palbart` assembly process described above also produces paper tape output files in RIM format in `bin/*.pt`. The simplest way to load these assembly examples into your PiDP-8/I is to copy each such file to a USB stick, one file per stick. Then, load the paper tape into the simulated PDP-8/I's core memory. The following is distilled from the [How to Use the PiDP-8/I][howto] section of the PiDP-8/I documentation: 1. Set the IF switches (first white group) to 001, and toggle `Sing Step` to reboot the simulator into the high-speed RIM loader. If the simulator wasn't already running, restarting the simulator with IF=1 will achieve the same end as toggling `Sing Step` while it's running. Reset the IF switches to 0. 2. Insert the USB stick containing the `*.pt` file you want to load into the Pi. 3. Set the DF switches (first brown group) to 001, then toggle `Sing Step` again. This attaches the tape to the high-speed paper tape reader peripheral within the PDP-8 simulator. Set DF back to 0. 4. Set the switch register (SR) to 7756 (111 111 101 110) then press `Load Add`, then `Start`. 5. Hit `Stop`, then reset SR to 0200 (000 010 000 000), that being the starting location of these example programs. Press `Load Add`, then `Start` to run the program. There is an SVG template for USB stick labels in the distribution under the [`labels/`][label] directory, for use if you find yourself creating long-lived USB sticks. See [`labels/README.md`][lread] for more information. ## License Copyright © 2016-2017 by Warren Young. This document is licensed under the terms of [the SIMH license][sl]. [lst]: https://tangentsoft.com/pidp8i/doc/trunk/examples/add.lst [pal]: https://tangentsoft.com/pidp8i/doc/trunk/examples/add.pal [label]: https://tangentsoft.com/pidp8i/dir?ci=trunk&name=labels [lread]: https://tangentsoft.com/pidp8i/doc/trunk/labels/README.md [howto]: http://obsolescence.wixsite.com/obsolescence/how-to-use-the-pidp-8 [sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | / ac-mq-blinker.pal - Rapidly modify AC and MQ / / This program twiddles AC and MQ rapidly, with a small amount of delay / between each update so the lights aren't just a solid blur. / / While this program runs at full speed, only AC and MQ appear to a / human to really change. PC also changes, of course, but since the / program spends so much of its time in the delay loop at the top, it / appears to be stuck at PC=1. / / It also modifies MB rapidly, but the pattern we use means it looks / like the lamps aren't changing, but are all on, dimmed by varying / amounts. / / From: http://dustyoldcomputers.com/pdp8/pdp8i/testprogs/acmqblinker.html / / SIMH: set throttle 30k / SIMH: set df disabled / SIMH: set cpu noidle / / Copyright © 2000 Robert Krten / / Permission is hereby granted, free of charge, to any person obtaining a / copy of this software and associated documentation files (the "Software"), / to deal in the Software without restriction, including without limitation / the rights to use, copy, modify, merge, publish, distribute, sublicense, / and/or sell copies of the Software, and to permit persons to whom the / Software is furnished to do so, subject to the following conditions: / / The above copyright notice and this permission notice shall be included in / all copies or substantial portions of the Software. / / THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR / IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, / FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL / THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER / LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING / FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER / DEALINGS IN THE SOFTWARE. / / Except as contained in this notice, the names of the authors above shall / not be used in advertising or otherwise to promote the sale, use or other / dealings in this Software without prior written authorization from those / authors. //////////////////////////////////////////////////////////////////////// PAGE 0 loop, ISZ delay / create a delay JMP loop CLA / clear AC so we can load it TAD value / get value MQL / stash AC into MQ TAD value / fetch value again CMA / complement AC ISZ value / get to next value NOP / ignore possible "skip" from ISZ JMP loop / and do it all again *20 / skip over the autoincrement registers delay, 0 value, 0 $ |
> > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | / add.pal - Add two numbers and halt, with sum in location 0207 / / This is a more space-efficient alternative to the program given at: / / http://mrhowson.edublogs.org/2016/11/27/pidp-8i-second-toggle-some-assembly-code/ PAGE 1 / code starts at core page 1; must avoid page 0 CLA CLL / clear AC and Link; two OPRs, one instruction! TAD A / add A to AC, which is zero, so "load A" TAD B / add B to AC DCA C / store sum in AC at C HLT / halt program A, 2 / set "A" variable to 2 B, 3 / and "B" to 3 C, / "C" result variable lives immediately past B, / and has no initial value because it is always / overwritten with the answer $ |
> > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | / bit-rotate.pal - Bit rotation and HLT demo / / This example demonstrates the bit rotation and HLT instructions of the / processor. It is meant to be run with the simulator in free-running / mode, since the embedded HLT instruction lets you see the state of AC / after each rotation. There are two HLT instructions so that you can / see the initial 1 value, and then see it change after each rotation. PAGE 1 CLA CLL IAC / clear link and AC, then bump AC: AC=1 HLT / let user see initial AC=1 value LOOP, RAL / rotate AC left HLT / and halt again JMP LOOP / on CONT, around it goes... $ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | / HELLO - "Hello, World!" program for PAL8 assembly, which also / happens to test the PRINTS routine, included inline below. / / Created by Warren Young of tangentsoft.com, 2016.11.30 / / Copyright © 2016 Warren Young / / Permission is hereby granted, free of charge, to any person obtaining a / copy of this software and associated documentation files (the "Software"), / to deal in the Software without restriction, including without limitation / the rights to use, copy, modify, merge, publish, distribute, sublicense, / and/or sell copies of the Software, and to permit persons to whom the / Software is furnished to do so, subject to the following conditions: / / The above copyright notice and this permission notice shall be included in / all copies or substantial portions of the Software. / / THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR / IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, / FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL / THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER / LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING / FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER / DEALINGS IN THE SOFTWARE. / / Except as contained in this notice, the names of the authors above shall / not be used in advertising or otherwise to promote the sale, use or other / dealings in this Software without prior written authorization from those / authors. //////////////////////////////////////////////////////////////////////// //// MAIN ///////////////////////////////////////////////////////////// PAGE 1 CLA TLS / send null character to terminal to prepare it TAD (HWSTR) JMS PRINTS HLT // "HELLO, WORLD!\r\n" in octal ASCIIZ HWSTR, 110; 105; 114; 114; 117; / HELLO 54; / comma 40; / space 127; 117; 122; 114; 104; / WORLD 41; / bang 15; 12; / CRLF 0 / null string terminator //// PRINTS //////////////////////////////////////////////////////////// PRINTS,0 DCA SADDR / save AC as string address PSNEXT, TAD I SADDR / load next character SNA JMP I PRINTS / found the null terminator; leave TSF / wait for terminal to be ready JMP .-1 TLS / write character to the terminal CLA / increment string address pointer TAD SADDR IAC DCA SADDR JMP PSNEXT / look at next character SADDR, 0 //// END /////////////////////////////////////////////////////////////// $ |
> > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 | 1 REM Copyright (c) 2016 by Warren Young 2 REM Released under the terms of ../SIMH-LICENSE.md 3 REM ------------------------------------------------------------------ 10 FOR I = 1 TO 999 20 A = I / 3 \ B = I / 5 30 IF INT(A) = A GOTO 60 40 IF INT(B) = B GOTO 60 50 GOTO 70 60 T = T + I 70 NEXT I 80 PRINT "TOTAL: "; T 90 END |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | / Project Euler Problem #1, Multiples of 3 and 5: / / If we list all the natural numbers below 10 that are multiples of / 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. / Find the sum of all the multiples of 3 or 5 below 1000. / / Initial solution by Warren Young of tangentsoft.com, 2016.11.30 / Optimized by Rick Murphy of the mailing list, 2016.12.04 / / Copyright © 2016-2017 Warren Young and Rick Murphy / / Permission is hereby granted, free of charge, to any person obtaining a / copy of this software and associated documentation files (the "Software"), / to deal in the Software without restriction, including without limitation / the rights to use, copy, modify, merge, publish, distribute, sublicense, / and/or sell copies of the Software, and to permit persons to whom the / Software is furnished to do so, subject to the following conditions: / / The above copyright notice and this permission notice shall be included in / all copies or substantial portions of the Software. / / THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR / IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, / FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL / THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER / LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING / FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER / DEALINGS IN THE SOFTWARE. / / Except as contained in this notice, the names of the authors above shall / not be used in advertising or otherwise to promote the sale, use or other / dealings in this Software without prior written authorization from those / authors. //////////////////////////////////////////////////////////////////////// //// DIY Assembler Instructions //////////////////////////////////////// / Our assembler doesn't know the EAE instructions, so teach it DVI=7407 / integer divide .+1 into {AC:MQ}, answer in MQ / Combined microcoded instruction aliases CLR=CLA CLL / clear both AC and L AC3=CLA CLL CML IAC RAL / set AC to 3 //// MAIN ////////////////////////////////////////////////////////////// / Program entry point. We purposely reinitialize global variables and / processor state in case we're restarting this program in-core. PAGE 1 MAIN, AC3 / start with 3, because we know 1 & 2 can't work DCA CURR DCA STOTAL / reset total to 0 TAD (ANSWER-1) / write "ANSWER: " to the terminal JMS PRINTS //// MLCORE //////////////////////////////////////////////////////////// / The core of the main loop. MAIN just inits the globals and falls / through to us. MLCORE, AC3 / try dividing 3 into CURR first JMS ISMOD0 SNA CLA / if ISMOD0 left AC = 0, CURR divided evenly by JMP NXITER / 3, so skip 5 lest we count multiples of 15 2x TAD (5) / no good; try dividing 5 into CURR instead JMS ISMOD0 NXITER, CLA / loop cleanup TAD CURR CIA TAD MAX / = 0 if CURR == MAX SNA CLA / if so, leave calculation loop JMP MLDONE ISZ CURR / CURR still < MAX, so increment CURR; never skips TAD STOTAL / if STOTAL is getting too big, print... CIA / a subtotal and zero STOTAL so we don't... TAD STMAX / overflow the 12-bit limit SNL JMP MLCORE / STMAX - STOTAL > 0 so re-enter loop core JMS SHOWST / exceeded threshold, so display subtotal and " + " DCA STOTAL / take advantage of free zero left by SHOWST TAD (PLUS-1) JMS PRINTS JMP MLCORE MLDONE, JMS SHOWST / done; show answer TAD (CRLF-1) / don't need CLA; SHOWST left AC = 0 JMS PRINTS / End program gracefully, either re-entering OS/8 if we can see / that its entry point looks sane, or halting with the answer in / AC so the user can see the answer on the front panel. OS8ENT, / 7600, OS/8's entry point, happens to also be... ENDG, 7600 / ...the group 2 variant of CLA; yes, we know, yuck! TAD I OS8ENT TAD OS8INS1 / add its negative SNA CLA / if it's zero'd out, then... JMP I OS8ENT / re-enter OS/8 TAD STOTAL / else not running under OS/8... HLT / so halt with STOTAL displayed in AC lights OS8INS1,-4207 / first OS/8 instruction at entry point, negated //// ISMOD0 //////////////////////////////////////////////////////////// / If passed AC divides evenly into CURR (in C-speak, CURR % AC == 0) / add CURR to STOTAL and return 0 in AC. Else, return nonzero in AC and / leave STOTAL untouched. ISMOD0, 0 DCA DIVISOR / Divide CURR by DIVISOR, passed as AC TAD CURR / load CURR into just-cleared AC MQL DVI / move CURR to MQ, divide by DIVISOR... DIVISOR,0 / ...quotient in MQ, remainder in AC SZA JMP I ISMOD0 / remainder nonzero, so leave early / Division left AC empty, so CURR divides evenly by DIVISOR! TAD CURR / don't need to clear AC; prior test says AC == 0 TAD STOTAL DCA STOTAL JMP I ISMOD0 //// SHOWST //////////////////////////////////////////////////////////// / Write STOTAL value to terminal in decimal. We purposely do not follow / it with anything, as our callers variously follow it with " + " or a / CRLF pair. Leaves AC = 0 because DECRPT does. SHOWST, 0 CLR TAD STOTAL JMS DECPRT / print answer on console, in decimal JMP I SHOWST / and done //// TYPE ////////////////////////////////////////////////////////////// / Send a character out to the terminal. Shared core of PRINTS and / DECPRT. TYPE, 0 TSF JMP .-1 TLS CLA JMP I TYPE //// PRINTS //////////////////////////////////////////////////////////// / Write an ASCIIZ string to the terminal. Expects to receive the / address of the string - 1 in AC. (The -1 hassle saves an instruction / or two in our use of an autoincrement register.) Uses the autoinc / register at location 10. SADDR=10 / autoinc register for walking the string PRINTS, 0 DCA SADDR / save AC as string address PSNEXT, TAD I SADDR / load next character SNA JMP I PRINTS / found the null terminator; leave JMS TYPE / Print that character JMP PSNEXT / look at next character //// DECPRT //////////////////////////////////////////////////////////// / Decimal number printer; variant of examples/routines/decprt.pal / Leaves AC = 0. DECPRT, 0 DCA VALUE /SAVE INPUT DCA DIGIT /CLEAR TAD CNTRZA DCA CNTRZB /SET COUNTER TO FOUR TAD ADDRZA DCA ARROW /SET TABLE POINTER SKP DCA VALUE /SAVE CLL TAD VALUE ARROW, TAD TENPWR /SUBTRACT POWER OF TEN SZL ISZ DIGIT /DEVELOP BCD DIGIT SZL JMP ARROW-3 /LOOP CLA /HAVE BCD DIGIT TAD DIGIT /GET DIGIT TAD K260 /MAKE IT ASCII JMS TYPE DCA DIGIT /CLEAR ISZ ARROW /UPDATE POINTER ISZ CNTRZB /DONE ALL FOUR? JMP ARROW-1 /NO: CONTINUE JMP I DECPRT /YES: EXIT ADDRZA, TAD TENPWR CNTRZA, -4 TENPWR, -1750 /ONE THOUSAND -0144 /ONE HUNDRED -0012 /TEN -0001 /ONE K260, 260 VALUE, 0 DIGIT, 0 CNTRZB, 0 //// Global Variables ////////////////////////////////////////////////// CURR, 0 / current number we're checking STOTAL, 0 / subtotal, printed and reset occasionally //// Constants ///////////////////////////////////////////////////////// DECIMAL MAX, 999 / check natural numbers CURR to MAX; must be < 2048! STMAX, 1024 / subtotal max; avoids overflow of 12-bit signed int OCTAL CRLF, 15;12;0 / ASCII character values, zero-terminated PLUS, 40;53;40;0 ANSWER, 101;116;123;127;105;122;72;40;0 //// END /////////////////////////////////////////////////////////////// / Assembler-generated constants will appear below this in the list file $ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | /COPYRIGHT 1971, DIGITAL EQUIPMENT CORPORATION /MAYNARD, MASSACHUSETTS /DIGITAL 8-22-U /UNSIGNED DECIMAL PRINT /CALL WITH NUMBER TO BE TYPED IN C(AC) /RETURN TO LOCATION FOLLOWING THE JMS DECPRT, 0 DCA VALUE /SAVE INPUT DCA DIGIT /CLEAR TAD CNTRZA DCA CNTRZB /SET COUNTER TO FOUR TAD ADDRZA DCA ARROW /SET TABLE POINTER SKP DCA VALUE /SAVE CLL TAD VALUE ARROW, TAD TENPWR /SUBTRACT POWER OF TEN SZL ISZ DIGIT /DEVELOP BCD DIGIT SZL JMP ARROW-3 /LOOP CLA /HAVE BCD DIGIT TAD DIGIT /GET DIGIT TAD K260 /MAKE IT ASCII TSF /OR TAD DIGIT JMP .-1 /JMS TDIGIT(SEE 8-19-U) TLS /TYPE DIGIT CLA DCA DIGIT /CLEAR ISZ ARROW /UPDATE POINTER ISZ CNTRZB /DONE ALL FOUR? JMP ARROW-1 /NO: CONTINUE JMP I DECPRT /YES: EXIT ADDRZA, TAD TENPWR CNTRZA, -4 TENPWR, -1750 /ONE THOUSAND -0144 /ONE HUNDRED -0012 /TEN -0001 /ONE K260, 260 VALUE, 0 DIGIT, 0 CNTRZB, 0 |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | / PRINTS - Print an ASCIIZ string to the terminal / / It expects to receive the address of the string - 1 in AC. (The -1 / hassle saves an instruction or two in our use of an autoincrement / register.) / / This routine uses the autoinc register at location 10. / / Created by Warren Young of tangentsoft.com, 2016.11.30 / Improved by Rick Murphy of the PiDP-8/I mailing list, 2016.12.03 / / Copyright © 2016 Warren Young and Rick Murphy / / Permission is hereby granted, free of charge, to any person obtaining a / copy of this software and associated documentation files (the "Software"), / to deal in the Software without restriction, including without limitation / the rights to use, copy, modify, merge, publish, distribute, sublicense, / and/or sell copies of the Software, and to permit persons to whom the / Software is furnished to do so, subject to the following conditions: / / The above copyright notice and this permission notice shall be included in / all copies or substantial portions of the Software. / / THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR / IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, / FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL / THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER / LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING / FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER / DEALINGS IN THE SOFTWARE. / / Except as contained in this notice, the names of the authors above shall / not be used in advertising or otherwise to promote the sale, use or other / dealings in this Software without prior written authorization from those / authors. //////////////////////////////////////////////////////////////////////// TYPE, 0 / helper routine for sending a single character TSF JMP .-1 TLS CLA JMP I TYPE SADDR=10 / autoinc register for walking the string PRINTS, 0 DCA SADDR / save AC as string address PSNEXT, TAD I SADDR / load next character SNA JMP I PRINTS / found the null terminator; leave JMS TYPE / print that character JMP PSNEXT / look at next character |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 | EESchema-LIBRARY Version 2.3 Date: 11/05/2015 22:48:50 #encoding utf-8 # # +3.3V # DEF +3.3V #PWR 0 0 Y Y 1 F P F0 "#PWR" 0 -40 30 H I C CNN F1 "+3.3V" 0 110 30 H V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN ALIAS +3,3V DRAW X +3.3V 1 0 0 0 U 30 30 0 0 W N C 0 60 20 0 1 0 N P 3 0 1 0 0 0 0 40 0 40 N ENDDRAW ENDDEF # # +5V # DEF +5V #PWR 0 40 Y Y 1 F P F0 "#PWR" 0 90 20 H I C CNN F1 "+5V" 0 90 30 H V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW X +5V 1 0 0 0 U 20 20 0 0 W N C 0 50 20 0 1 0 N P 4 0 1 0 0 0 0 30 0 30 0 30 N ENDDRAW ENDDEF # # CONN_1 # DEF ~CONN_1 P 0 30 N N 1 F N F0 "P" 80 0 40 H V L CNN F1 "CONN_1" 0 55 30 H I C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW C 0 0 31 0 1 0 N P 2 0 1 0 -30 0 -50 0 N X 1 1 -150 0 100 R 60 60 1 1 P ENDDRAW ENDDEF # # CONN_20X2 # DEF CONN_20X2 P 0 10 Y N 1 F N F0 "P" 0 1050 60 H V C CNN F1 "CONN_20X2" 0 0 50 V V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW S -100 1000 100 -1000 0 1 0 N X P1 1 -400 950 300 R 60 30 1 1 P I X P2 2 400 950 300 L 60 30 1 1 P I X P3 3 -400 850 300 R 60 30 1 1 P I X P4 4 400 850 300 L 60 30 1 1 P I X P5 5 -400 750 300 R 60 30 1 1 P I X P6 6 400 750 300 L 60 30 1 1 P I X P7 7 -400 650 300 R 60 30 1 1 P I X P8 8 400 650 300 L 60 30 1 1 P I X P9 9 -400 550 300 R 60 30 1 1 P I X P10 10 400 550 300 L 60 30 1 1 P I X P20 20 400 50 300 L 60 30 1 1 P I X P30 30 400 -450 300 L 60 30 1 1 P I X P40 40 400 -950 300 L 60 30 1 1 P I X P11 11 -400 450 300 R 60 30 1 1 P I X P21 21 -400 -50 300 R 60 30 1 1 P I X P31 31 -400 -550 300 R 60 30 1 1 P I X P12 12 400 450 300 L 60 30 1 1 P I X P22 22 400 -50 300 L 60 30 1 1 P I X P32 32 400 -550 300 L 60 30 1 1 P I X P13 13 -400 350 300 R 60 30 1 1 P I X P23 23 -400 -150 300 R 60 30 1 1 P I X P33 33 -400 -650 300 R 60 30 1 1 P I X P14 14 400 350 300 L 60 30 1 1 P I X P24 24 400 -150 300 L 60 30 1 1 P I X P34 34 400 -650 300 L 60 30 1 1 P I X P15 15 -400 250 300 R 60 30 1 1 P I X ~ 25 -400 -250 300 R 60 30 1 1 P I X P35 35 -400 -750 300 R 60 30 1 1 P I X P16 16 400 250 300 L 60 30 1 1 P I X P26 26 400 -250 300 L 60 30 1 1 P I X P36 36 400 -750 300 L 60 30 1 1 P I X P17 17 -400 150 300 R 60 30 1 1 P I X P27 27 -400 -350 300 R 60 30 1 1 P I X P37 37 -400 -850 300 R 60 30 1 1 P I X P18 18 400 150 300 L 60 30 1 1 P I X P28 28 400 -350 300 L 60 30 1 1 P I X P38 38 400 -850 300 L 60 30 1 1 P I X P19 19 -400 50 300 R 60 30 1 1 P I X P29 29 -400 -450 300 R 60 30 1 1 P I X P39 39 -400 -950 300 R 60 30 1 1 P I ENDDRAW ENDDEF # # CONN_3 # DEF CONN_3 K 0 40 Y N 1 F N F0 "K" -50 0 50 V V C CNN F1 "CONN_3" 50 0 40 V V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW S -100 150 100 -150 0 1 0 N X P1 1 -350 100 250 R 60 60 1 1 P I X PM 2 -350 0 250 R 60 60 1 1 P I X P3 3 -350 -100 250 R 60 60 1 1 P I ENDDRAW ENDDEF # # CONN_4 # DEF CONN_4 P 0 40 Y N 1 F N F0 "P" -50 0 50 V V C CNN F1 "CONN_4" 50 0 50 V V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW S -100 200 100 -200 0 1 0 N X P1 1 -350 150 250 R 50 50 1 1 P I X P2 2 -350 50 250 R 50 50 1 1 P I X P3 3 -350 -50 250 R 50 50 1 1 P I X P4 4 -350 -150 250 R 50 50 1 1 P I ENDDRAW ENDDEF # # DIODE # DEF DIODE D 0 40 N N 1 F N F0 "D" 0 100 40 H V C CNN F1 "DIODE" 0 -100 40 H V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN $FPLIST D? S* $ENDFPLIST DRAW P 2 0 1 6 50 50 50 -50 N P 3 0 1 0 -50 50 50 0 -50 -50 F X A 1 -200 0 150 R 40 40 1 1 P X K 2 200 0 150 L 40 40 1 1 P ENDDRAW ENDDEF # # GND # DEF ~GND #PWR 0 0 Y Y 1 F P F0 "#PWR" 0 0 30 H I C CNN F1 "GND" 0 -70 30 H I C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW P 4 0 1 0 -50 0 0 -50 50 0 -50 0 N X GND 1 0 0 0 U 30 30 1 1 W N ENDDRAW ENDDEF # # LED # DEF LED D 0 40 Y N 1 F N F0 "D" 0 100 50 H V C CNN F1 "LED" 0 -100 50 H V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN $FPLIST LED-3MM LED-5MM LED-10MM LED-0603 LED-0805 LED-1206 LEDV $ENDFPLIST DRAW P 2 0 1 0 50 50 50 -50 N P 3 0 1 0 -50 50 50 0 -50 -50 F P 3 0 1 0 65 -40 110 -80 105 -55 N P 3 0 1 0 80 -25 125 -65 120 -40 N X A 1 -200 0 150 R 40 40 1 1 P X K 2 200 0 150 L 40 40 1 1 P ENDDRAW ENDDEF # # R # DEF R R 0 0 N Y 1 F N F0 "R" 80 0 40 V V C CNN F1 "R" 7 1 40 V V C CNN F2 "~" -70 0 30 V V C CNN F3 "~" 0 0 30 H V C CNN $FPLIST R? SM0603 SM0805 R?-* SM1206 $ENDFPLIST DRAW S -40 150 40 -150 0 1 12 N X ~ 1 0 250 100 D 60 60 1 1 P X ~ 2 0 -250 100 U 60 60 1 1 P ENDDRAW ENDDEF # # RASPI_MODEL_B_PLUS_GPIO # DEF RASPI_MODEL_B_PLUS_GPIO P 0 10 Y Y 1 F N F0 "P" 0 1050 60 H V C CNN F1 "RASPI_MODEL_B_PLUS_GPIO" 0 0 20 V V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW S -100 1000 100 -1000 0 1 0 N X 3.3v 1 -400 950 300 R 60 30 1 1 w I X 5v 2 400 950 300 L 60 30 1 1 w I X g2 3 -400 850 300 R 60 30 1 1 P I X 5v 4 400 850 300 L 60 30 1 1 P I X g3 5 -400 750 300 R 60 30 1 1 P I X GND 6 400 750 300 L 60 30 1 1 w I X g4 7 -400 650 300 R 60 30 1 1 P I X g14 8 400 650 300 L 60 30 1 1 P I X GND 9 -400 550 300 R 60 30 1 1 P I X g15 10 400 550 300 L 60 30 1 1 P I X GND 20 400 50 300 L 60 30 1 1 P I X GND 30 400 -450 300 L 60 30 1 1 P I X g21 40 400 -950 300 L 60 30 1 1 P I X g17 11 -400 450 300 R 60 30 1 1 P I X g9 21 -400 -50 300 R 60 30 1 1 P I X g6 31 -400 -550 300 R 60 30 1 1 P I X g18 12 400 450 300 L 60 30 1 1 P I X g25 22 400 -50 300 L 60 30 1 1 P I X g12 32 400 -550 300 L 60 30 1 1 P I X g27 13 -400 350 300 R 60 30 1 1 P I X g11 23 -400 -150 300 R 60 30 1 1 P I X g13 33 -400 -650 300 R 60 30 1 1 P I X GND 14 400 350 300 L 60 30 1 1 P I X g8 24 400 -150 300 L 60 30 1 1 P I X GND 34 400 -650 300 L 60 30 1 1 P I X g22 15 -400 250 300 R 60 30 1 1 P I X GND 25 -400 -250 300 R 60 30 1 1 P I X g19 35 -400 -750 300 R 60 30 1 1 P I X g23 16 400 250 300 L 60 30 1 1 P I X g7 26 400 -250 300 L 60 30 1 1 P I X g16 36 400 -750 300 L 60 30 1 1 P I X 3.3v 17 -400 150 300 R 60 30 1 1 P I X n/c 27 -400 -350 300 R 60 30 1 1 P I X g26 37 -400 -850 300 R 60 30 1 1 P I X g24 18 400 150 300 L 60 30 1 1 P I X n/c 28 400 -350 300 L 60 30 1 1 P I X g20 38 400 -850 300 L 60 30 1 1 P I X g10 19 -400 50 300 R 60 30 1 1 P I X g5 29 -400 -450 300 R 60 30 1 1 P I X GND 39 -400 -950 300 R 60 30 1 1 P I ENDDRAW ENDDEF # # SWITCH_INV # DEF SWITCH_INV SW 0 0 N Y 1 F N F0 "SW" -200 150 50 H V C CNN F1 "SWITCH_INV" -150 -150 50 H V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW C -150 0 50 0 0 0 N C 150 -100 50 0 0 0 N C 150 100 50 0 1 0 N P 2 0 1 0 -100 0 150 50 N X 1 1 500 100 300 L 60 60 1 1 P X 2 2 -500 0 300 R 60 60 1 1 P X 3 3 500 -100 300 L 60 60 1 1 P ENDDRAW ENDDEF # # UDN2981A # DEF UDN2981A P 0 40 Y Y 1 F N F0 "P" 0 550 30 H V C CNN F1 "UDN2981A" 0 -550 30 H V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW S -150 500 150 -500 0 1 0 N X IN1 1 -350 400 200 R 40 20 1 1 I I X IN2 2 -350 300 200 R 40 20 1 1 I I X IN3 3 -350 200 200 R 40 20 1 1 I I X IN4 4 -350 100 200 R 40 20 1 1 I I X IN5 5 -350 0 200 R 40 20 1 1 I I X IN6 6 -350 -100 200 R 40 20 1 1 I I X IN7 7 -350 -200 200 R 40 20 1 1 I I X IN8 8 -350 -300 200 R 40 20 1 1 I I X Vs 9 -350 -400 200 R 40 20 1 1 P I X GND 10 350 -400 200 L 40 20 1 1 P I X OUT8 11 350 -300 200 L 40 20 1 1 O I X OUT7 12 350 -200 200 L 40 20 1 1 O I X OUT6 13 350 -100 200 L 40 20 1 1 O I X OUT5 14 350 0 200 L 40 20 1 1 O I X OUT4 15 350 100 200 L 40 20 1 1 O I X OUT3 16 350 200 200 L 40 20 1 1 O I X OUT2 17 350 300 200 L 40 20 1 1 O I X OUT1 18 350 400 200 L 40 20 1 1 O I ENDDRAW ENDDEF # #End Library |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 | Cmp-Mod V01 Created by CvPcb (2013-07-07 BZR 4022)-stable date = 10/05/2015 13:43:50 BeginCmp TimeStamp = /54904DF0; Reference = D1; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /5490504C; Reference = D2; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /54905056; Reference = D3; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /5490505E; Reference = D4; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /54905068; Reference = D5; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /5490506E; Reference = D6; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /549055F9; Reference = D7; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /549055FF; Reference = D8; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /54905605; Reference = D9; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /5490560B; Reference = D10; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /54905611; Reference = D11; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /54905640; Reference = D12; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /54905646; Reference = D13; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /5490564C; Reference = D14; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /54905652; Reference = D15; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /54905658; Reference = D16; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /5490565E; Reference = D17; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /54905664; Reference = D18; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /549070C3; Reference = D19; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /549070C9; Reference = D20; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /549070CF; Reference = D21; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /549070D5; Reference = D22; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /549070DB; Reference = D23; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /549070E1; Reference = D24; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /549070E7; Reference = D25; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /549070ED; Reference = D26; ValeurCmp = 1N4148; IdModule = D2; EndCmp BeginCmp TimeStamp = /548EF5CC; Reference = DAC1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5E5; Reference = DAC2; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5EB; Reference = DAC3; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5F1; Reference = DAC4; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5F7; Reference = DAC5; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5FD; Reference = DAC6; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF603; Reference = DAC7; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF609; Reference = DAC8; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF60F; Reference = DAC9; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF615; Reference = DAC10; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF61B; Reference = DAC11; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF621; Reference = DAC12; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF728; Reference = DAND1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF7E9; Reference = DBREAK1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF7E3; Reference = DCURAD1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF741; Reference = DDCA1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF7D7; Reference = DDEFER1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF6DA; Reference = DDF1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF6F3; Reference = DDF2; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF6F9; Reference = DDF3; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF7D1; Reference = DEXEC1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF7CB; Reference = DFETCH1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF701; Reference = DIF1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF71A; Reference = DIF2; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF720; Reference = DIF3; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF837; Reference = DION1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF783; Reference = DIOT1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF73B; Reference = DISZ1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF77D; Reference = DJMP1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF777; Reference = DJMS1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF686; Reference = DLINK1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF463; Reference = DMA1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF47C; Reference = DMA2; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF482; Reference = DMA3; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF488; Reference = DMA4; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF48E; Reference = DMA5; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF494; Reference = DMA6; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF49A; Reference = DMA7; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF4A0; Reference = DMA8; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF4A6; Reference = DMA9; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF4AC; Reference = DMA10; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF4B2; Reference = DMA11; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF4B8; Reference = DMA12; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF56F; Reference = DMB1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF588; Reference = DMB2; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF58E; Reference = DMB3; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF594; Reference = DMB4; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF59A; Reference = DMB5; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5A0; Reference = DMB6; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5A6; Reference = DMB7; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5AC; Reference = DMB8; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5B2; Reference = DMB9; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5B8; Reference = DMB10; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5BE; Reference = DMB11; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF5C4; Reference = DMB12; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF629; Reference = DMQ1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF642; Reference = DMQ2; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF648; Reference = DMQ3; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF64E; Reference = DMQ4; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF654; Reference = DMQ5; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF65A; Reference = DMQ6; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF660; Reference = DMQ7; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF666; Reference = DMQ8; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF66C; Reference = DMQ9; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF672; Reference = DMQ10; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF678; Reference = DMQ11; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF67E; Reference = DMQ12; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF789; Reference = DOPR1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF83D; Reference = DPAUSE1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /554E5897; Reference = DPAUSE2; ValeurCmp = LED; IdModule = LED-3-StrEight; EndCmp BeginCmp TimeStamp = /548EF34A; Reference = DPC1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF399; Reference = DPC2; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF3AC; Reference = DPC3; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF3B2; Reference = DPC4; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF3B8; Reference = DPC5; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF3BE; Reference = DPC6; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF3C4; Reference = DPC7; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF3CA; Reference = DPC8; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF3D0; Reference = DPC9; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF3D6; Reference = DPC10; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF3DC; Reference = DPC11; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF3E2; Reference = DPC12; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF843; Reference = DRUN1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /554E589D; Reference = DRUN2; ValeurCmp = LED; IdModule = LED-3-StrEight; EndCmp BeginCmp TimeStamp = /548EF6A1; Reference = DSC1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF6BA; Reference = DSC2; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF6C0; Reference = DSC3; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF6C6; Reference = DSC4; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF6CC; Reference = DSC5; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF735; Reference = DTAD1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /548EF7DD; Reference = DWRDCT1; ValeurCmp = LED; IdModule = LED-3-PDP; EndCmp BeginCmp TimeStamp = /54BD85A3; Reference = DZ1; ValeurCmp = ZENER; IdModule = D3; EndCmp BeginCmp TimeStamp = /554F46DF; Reference = J_COL1; ValeurCmp = CONN_3; IdModule = PIN_ARRAY_3X1; EndCmp BeginCmp TimeStamp = /554F46EE; Reference = J_COL2; ValeurCmp = CONN_3; IdModule = PIN_ARRAY_3X1; EndCmp BeginCmp TimeStamp = /54B1CC4A; Reference = M1; ValeurCmp = M; IdModule = 1pin; EndCmp BeginCmp TimeStamp = /54B1CC76; Reference = M2; ValeurCmp = M; IdModule = 1pin; EndCmp BeginCmp TimeStamp = /54B1CC7C; Reference = M3; ValeurCmp = M; IdModule = 1pin; EndCmp BeginCmp TimeStamp = /54B1CC82; Reference = M4; ValeurCmp = M; IdModule = 1pin; EndCmp BeginCmp TimeStamp = /54BD36C6; Reference = M5; ValeurCmp = M; IdModule = 1pin; EndCmp BeginCmp TimeStamp = /54BD36CC; Reference = M6; ValeurCmp = M; IdModule = 1pin; EndCmp BeginCmp TimeStamp = /54BD36D2; Reference = M7; ValeurCmp = M; IdModule = 1pin; EndCmp BeginCmp TimeStamp = /548F13F7; Reference = P1; ValeurCmp = RASPI_MODEL_B_PLUS_GPIO; IdModule = RASPI_BPLUS_MIRRORED; EndCmp BeginCmp TimeStamp = /54B17386; Reference = P2; ValeurCmp = UDN2981A; IdModule = DIP-18__300; EndCmp BeginCmp TimeStamp = /554E0D39; Reference = P3; ValeurCmp = EXPANSION_20X2; IdModule = PIN_ARRAY_20X2; EndCmp BeginCmp TimeStamp = /554E5206; Reference = P5; ValeurCmp = SERIAL 5V TTL; IdModule = PIN_ARRAY_4x1; EndCmp BeginCmp TimeStamp = /5490833D; Reference = R1; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /5490834A; Reference = R2; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /54908350; Reference = R3; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /54908356; Reference = R4; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /5490835C; Reference = R5; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /54908362; Reference = R6; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /54908368; Reference = R7; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /5490836E; Reference = R8; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /54908374; Reference = R9; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /5490837A; Reference = R10; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /54908380; Reference = R11; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /54908386; Reference = R12; ValeurCmp = 390; IdModule = R3; EndCmp BeginCmp TimeStamp = /5490838C; Reference = R_ROW1; ValeurCmp = 1K; IdModule = R3; EndCmp BeginCmp TimeStamp = /5490839E; Reference = R_ROW2; ValeurCmp = 1K; IdModule = R3; EndCmp BeginCmp TimeStamp = /549083A4; Reference = R_ROW3; ValeurCmp = 1K; IdModule = R3; EndCmp BeginCmp TimeStamp = /554E5219; Reference = R_S1; ValeurCmp = 300; IdModule = R3; EndCmp BeginCmp TimeStamp = /554E5233; Reference = R_S2; ValeurCmp = 620; IdModule = R3; EndCmp BeginCmp TimeStamp = /548EFBFD; Reference = SW1; ValeurCmp = DF1; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFC03; Reference = SW2; ValeurCmp = DF2; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFC09; Reference = SW3; ValeurCmp = DF3; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFC0F; Reference = SW4; ValeurCmp = IF1; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFC15; Reference = SW5; ValeurCmp = IF2; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFC1B; Reference = SW6; ValeurCmp = IF3; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFAF8; Reference = SW7; ValeurCmp = SR1; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFB27; Reference = SW8; ValeurCmp = SR2; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFB2D; Reference = SW9; ValeurCmp = SR3; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFB33; Reference = SW10; ValeurCmp = SR4; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFB42; Reference = SW11; ValeurCmp = SR5; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFB48; Reference = SW12; ValeurCmp = SR6; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFB4E; Reference = SW13; ValeurCmp = SR7; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFB54; Reference = SW14; ValeurCmp = SR8; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFB5A; Reference = SW15; ValeurCmp = SR9; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFB60; Reference = SW16; ValeurCmp = SR10; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFB66; Reference = SW17; ValeurCmp = SR11; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EFB6C; Reference = SW18; ValeurCmp = SR12; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EF86F; Reference = SW19; ValeurCmp = START; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EF87C; Reference = SW20; ValeurCmp = LOAD_ADD; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EF882; Reference = SW21; ValeurCmp = DEP; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EF888; Reference = SW22; ValeurCmp = EXAM; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EF88E; Reference = SW23; ValeurCmp = CONT; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EF894; Reference = SW24; ValeurCmp = STOP; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EF89A; Reference = SW25; ValeurCmp = SING_STEP; IdModule = SW_KND2_PDP2; EndCmp BeginCmp TimeStamp = /548EF8A0; Reference = SW26; ValeurCmp = SING_INST; IdModule = SW_KND2_PDP2; EndCmp EndListe |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 | (pcb C:\temp29\PDP8KICAD\PDP8.dsn (parser (string_quote ") (space_in_quoted_tokens on) (host_cad "KiCad's Pcbnew") (host_version "(2013-07-07 BZR 4022)-stable") ) (resolution um 10) (unit um) (structure (layer F.Cu (type signal) (property (index 0) ) ) (layer B.Cu (type signal) (property (index 1) ) ) (boundary (path pcb 0 8500 -64000 288500 -64000 288500 -163000 8500 -163000 8500 -64000) ) (keepout "" (polygon B.Cu 0 288000 -140000 284000 -140000 284000 -156000 288000 -156000)) (keepout "" (polygon F.Cu 0 288000 -140000 284000 -140000 284000 -156000 288000 -156000)) (keepout "" (polygon B.Cu 0 9000 -142000 14000 -142000 14000 -140000 23000 -140000 24000 -141000 24000 -162000 16000 -162000 16000 -157000 15000 -156000 9000 -156000)) (keepout "" (polygon F.Cu 0 9000 -142000 14000 -142000 14000 -140000 23000 -140000 24000 -141000 24000 -162000 16000 -162000 16000 -157000 15000 -156000 9000 -156000)) (keepout "" (polygon F.Cu 0 64500 -111000 66500 -111000 66000 -111500 66000 -112000 66000 -112500 65000 -112500 65250 -111750 65000 -111250 64500 -111000)) (keepout "" (polygon F.Cu 0 65000 -114750 66000 -114750 66000 -115750 65000 -115750 65250 -115250)) (via "Via[0-1]_889:635_um" "Via[0-1]_889:0_um") (rule (width 254) (clearance 254.1) (clearance 254.1 (type default_smd)) (clearance 63.5 (type smd_smd)) ) ) (placement (component R3 (place R9 57920 -102940 back 270 (PN 390)) (place R1 37600 -102940 back 90 (PN 390)) (place R2 40140 -102940 back 90 (PN 390)) (place R3 42680 -102940 back 90 (PN 390)) (place R4 45220 -102940 back 90 (PN 390)) (place R5 47760 -102940 back 90 (PN 390)) (place R6 50300 -102940 back 90 (PN 390)) (place R7 52840 -102940 back 270 (PN 390)) (place R8 55380 -102940 back 270 (PN 390)) (place R10 60460 -102940 back 270 (PN 390)) (place R11 63000 -102940 back 270 (PN 390)) (place R12 65540 -102940 back 270 (PN 390)) (place R_ROW1 78900 -133080 front 0 (PN 1K)) (place R_ROW2 18750 -129500 front 180 (PN 1K)) (place R_ROW3 218600 -133080 front 0 (PN 1K)) (place R_S1 18750 -133000 front 0 (PN 300)) (place R_S2 18750 -136500 front 0 (PN 620)) ) (component "DIP-18__300" (place P2 219050 -100970 back 270 (PN UDN2981A)) ) (component 1pin (place M1 13000 -68000 front 0 (PN M)) (place M2 13000 -159000 front 0 (PN M)) (place M3 285000 -68000 front 0 (PN M)) (place M4 286000 -159000 front 0 (PN M)) (place M5 208000 -68000 front 0 (PN M)) (place M6 285000 -132000 front 0 (PN M)) (place M7 208000 -132000 front 0 (PN M)) ) (component D2 (place D23 249000 -136500 front 0 (PN 1N4148)) (place D24 259000 -136500 front 0 (PN 1N4148)) (place D22 239000 -136500 front 0 (PN 1N4148)) (place D25 269000 -136500 front 0 (PN 1N4148)) (place D26 279000 -136500 front 0 (PN 1N4148)) (place D12 139000 -136500 front 0 (PN 1N4148)) (place D2 39000 -136500 front 0 (PN 1N4148)) (place D3 49000 -136500 front 0 (PN 1N4148)) (place D4 59000 -136500 front 0 (PN 1N4148)) (place D5 69000 -136500 front 0 (PN 1N4148)) (place D6 79000 -136500 front 0 (PN 1N4148)) (place D7 89000 -136500 front 0 (PN 1N4148)) (place D8 99000 -136500 front 0 (PN 1N4148)) (place D9 109000 -136500 front 0 (PN 1N4148)) (place D10 119000 -136500 front 0 (PN 1N4148)) (place D11 129000 -136500 front 0 (PN 1N4148)) (place D1 29000 -136500 front 0 (PN 1N4148)) (place D13 149000 -136500 front 0 (PN 1N4148)) (place D14 159000 -136500 front 0 (PN 1N4148)) (place D15 169000 -136500 front 0 (PN 1N4148)) (place D16 179000 -136500 front 0 (PN 1N4148)) (place D17 189000 -136500 front 0 (PN 1N4148)) (place D18 199000 -136500 front 0 (PN 1N4148)) (place D19 209000 -136500 front 0 (PN 1N4148)) (place D20 219000 -136500 front 0 (PN 1N4148)) (place D21 229000 -136500 front 0 (PN 1N4148)) ) (component RASPI_BPLUS_MIRRORED (place P1 64000 -124000 back 0 (PN RASPI_MODEL_B_PLUS_GPIO)) ) (component D3 (place DZ1 219000 -117000 front 0 (PN ZENER)) ) (component "LED-3-PDP" (place DMB9 169000 -99800 front 0 (PN LED)) (place DMB10 179000 -99800 front 0 (PN LED)) (place DMB11 189000 -99800 front 0 (PN LED)) (place DMB12 199000 -99800 front 0 (PN LED)) (place DAC1 89000 -114400 front 0 (PN LED)) (place DAC2 99000 -114400 front 0 (PN LED)) (place DAC3 109000 -114400 front 0 (PN LED)) (place DAC4 119000 -114400 front 0 (PN LED)) (place DAC5 129000 -114400 front 0 (PN LED)) (place DAC6 139000 -114400 front 0 (PN LED)) (place DAC7 149000 -114400 front 0 (PN LED)) (place DAC8 159000 -114400 front 0 (PN LED)) (place DAC9 169000 -114400 front 0 (PN LED)) (place DAC10 179000 -114400 front 0 (PN LED)) (place DPC1 89000 -70600 front 0 (PN LED)) (place DAC12 199000 -114400 front 0 (PN LED)) (place DMQ1 89000 -129000 front 0 (PN LED)) (place DMQ2 99000 -129000 front 0 (PN LED)) (place DMQ3 109000 -129000 front 0 (PN LED)) (place DMQ4 119000 -129000 front 0 (PN LED)) (place DMQ5 129000 -129000 front 0 (PN LED)) (place DMQ6 139000 -129000 front 0 (PN LED)) (place DMQ7 149000 -129000 front 0 (PN LED)) (place DMQ8 159000 -129000 front 0 (PN LED)) (place DMQ9 169000 -129000 front 0 (PN LED)) (place DMQ10 179000 -129000 front 0 (PN LED)) (place DMQ11 189000 -129000 front 0 (PN LED)) (place DMQ12 199000 -129000 front 0 (PN LED)) (place DLINK1 79000 -114400 front 0 (PN LED)) (place DSC1 29000 -129000 front 0 (PN LED)) (place DAC11 189000 -114400 front 0 (PN LED)) (place DPC2 99000 -70600 front 0 (PN LED)) (place DPC3 109000 -70600 front 0 (PN LED)) (place DPC4 119000 -70600 front 0 (PN LED)) (place DPC5 129000 -70600 front 0 (PN LED)) (place DPC6 139000 -70600 front 0 (PN LED)) (place DPC7 149000 -70600 front 0 (PN LED)) (place DPC8 159000 -70600 front 0 (PN LED)) (place DPC9 169000 -70600 front 0 (PN LED)) (place DPC10 179000 -70600 front 0 (PN LED)) (place DPC11 189000 -70600 front 0 (PN LED)) (place DPC12 199000 -70600 front 0 (PN LED)) (place DMA1 89000 -85200 front 0 (PN LED)) (place DMA2 99000 -85200 front 0 (PN LED)) (place DMA3 109000 -85200 front 0 (PN LED)) (place DMB8 159000 -99800 front 0 (PN LED)) (place DMA5 129000 -85200 front 0 (PN LED)) (place DMA6 139000 -85200 front 0 (PN LED)) (place DMA7 149000 -85200 front 0 (PN LED)) (place DMA8 159000 -85200 front 0 (PN LED)) (place DMA9 169000 -85200 front 0 (PN LED)) (place DMA10 179000 -85200 front 0 (PN LED)) (place DMA11 189000 -85200 front 0 (PN LED)) (place DMA12 199000 -85200 front 0 (PN LED)) (place DMB1 89000 -99800 front 0 (PN LED)) (place DMB2 99000 -99800 front 0 (PN LED)) (place DMB3 109000 -99800 front 0 (PN LED)) (place DMB4 119000 -99800 front 0 (PN LED)) (place DMB5 129000 -99800 front 0 (PN LED)) (place DMB6 139000 -99800 front 0 (PN LED)) (place DMB7 149000 -99800 front 0 (PN LED)) (place DMA4 119000 -85200 front 0 (PN LED)) (place DRUN1 279000 -85200 front 0 (PN LED)) (place DPAUSE1 279000 -77900 front 0 (PN LED)) (place DION1 279000 -70600 front 0 (PN LED)) (place DBREAK1 259000 -107100 front 0 (PN LED)) (place DCURAD1 259000 -99800 front 0 (PN LED)) (place DWRDCT1 259000 -92500 front 0 (PN LED)) (place DDEFER1 259000 -85200 front 0 (PN LED)) (place DEXEC1 259000 -77900 front 0 (PN LED)) (place DFETCH1 259000 -70600 front 0 (PN LED)) (place DOPR1 239000 -121700 front 0 (PN LED)) (place DIOT1 239000 -114400 front 0 (PN LED)) (place DJMP1 239000 -107100 front 0 (PN LED)) (place DJMS1 239000 -99800 front 0 (PN LED)) (place DDCA1 239000 -92500 front 0 (PN LED)) (place DSC2 39000 -129000 front 0 (PN LED)) (place DSC4 59000 -129000 front 0 (PN LED)) (place DSC5 69000 -129000 front 0 (PN LED)) (place DDF1 29000 -70600 front 0 (PN LED)) (place DDF2 39000 -70600 front 0 (PN LED)) (place DDF3 49000 -70600 front 0 (PN LED)) (place DSC3 49000 -129000 front 0 (PN LED)) (place DTAD1 239000 -77900 front 0 (PN LED)) (place DAND1 239000 -70600 front 0 (PN LED)) (place DISZ1 239000 -85200 front 0 (PN LED)) (place DIF2 69000 -70600 front 0 (PN LED)) (place DIF3 79000 -70600 front 0 (PN LED)) (place DIF1 59000 -70600 front 0 (PN LED)) ) (component SW_KND2_PDP2 (place SW6 79000 -159500 front 0 (PN IF3)) (place SW5 69000 -159500 front 0 (PN IF2)) (place SW4 59000 -159500 front 0 (PN IF1)) (place SW3 49000 -159500 front 0 (PN DF3)) (place SW2 39000 -159500 front 0 (PN DF2)) (place SW1 29000 -159500 front 0 (PN DF1)) (place SW18 199000 -159500 front 0 (PN SR12)) (place SW17 189000 -159500 front 0 (PN SR11)) (place SW15 169000 -159500 front 0 (PN SR9)) (place SW14 159000 -159500 front 0 (PN SR8)) (place SW13 149000 -159500 front 0 (PN SR7)) (place SW12 139000 -159500 front 0 (PN SR6)) (place SW19 209000 -159500 front 0 (PN START)) (place SW20 219000 -159500 front 0 (PN LOAD_ADD)) (place SW16 179000 -159500 front 0 (PN SR10)) (place SW22 239000 -159500 front 0 (PN EXAM)) (place SW23 249000 -159500 front 0 (PN CONT)) (place SW24 259000 -159500 front 0 (PN STOP)) (place SW25 269000 -159500 front 0 (PN SING_STEP)) (place SW26 279000 -159500 front 0 (PN SING_INST)) (place SW7 89000 -159500 front 0 (PN SR1)) (place SW8 99000 -159500 front 0 (PN SR2)) (place SW9 109000 -159500 front 0 (PN SR3)) (place SW10 119000 -159500 front 0 (PN SR4)) (place SW11 129000 -159500 front 0 (PN SR5)) (place SW21 229000 -159500 front 0 (PN DEP)) ) (component PIN_ARRAY_4x1 (place P5 11500 -136000 front 270 (PN "SERIAL 5V TTL")) ) (component PIN_ARRAY_20X2 (place P3 253900 -130050 back 180 (PN EXPANSION_20X2)) ) (component "LED-3-StrEight" (place DPAUSE2 259000 -114400 front 0 (PN LED)) (place DRUN2 259000 -121700 front 0 (PN LED)) ) (component PIN_ARRAY_3X1 (place J_COL1 64300 -111800 back 180 (PN CONN_3)) (place J_COL2 64300 -115200 back 180 (PN CONN_3)) ) ) (library (image R3 (outline (path signal 203.2 -3810 0 -3302 0)) (outline (path signal 203.2 3810 0 3302 0)) (outline (path signal 203.2 3302 0 3302 1016)) (outline (path signal 203.2 3302 1016 -3302 1016)) (outline (path signal 203.2 -3302 1016 -3302 -1016)) (outline (path signal 203.2 -3302 -1016 3302 -1016)) (outline (path signal 203.2 3302 -1016 3302 0)) (outline (path signal 203.2 -3302 508 -2794 1016)) (pin Round[A]Pad_1397_um 1 -3810 0) (pin Round[A]Pad_1397_um 2 3810 0) ) (image "DIP-18__300" (outline (path signal 381 -12700 1270 -11430 1270)) (outline (path signal 381 -11430 1270 -11430 -1270)) (outline (path signal 381 -11430 -1270 -12700 -1270)) (outline (path signal 381 -12700 2540 12700 2540)) (outline (path signal 381 12700 2540 12700 -2540)) (outline (path signal 381 12700 -2540 -12700 -2540)) (outline (path signal 381 -12700 -2540 -12700 2540)) (pin Rect[A]Pad_1397x1397_um 1 -10160 -3810) (pin Round[A]Pad_1397_um 2 -7620 -3810) (pin Round[A]Pad_1397_um 3 -5080 -3810) (pin Round[A]Pad_1397_um 4 -2540 -3810) (pin Round[A]Pad_1397_um 5 0 -3810) (pin Round[A]Pad_1397_um 6 2540 -3810) (pin Round[A]Pad_1397_um 7 5080 -3810) (pin Round[A]Pad_1397_um 8 7620 -3810) (pin Round[A]Pad_1397_um 9 10160 -3810) (pin Round[A]Pad_1397_um 10 10160 3810) (pin Round[A]Pad_1397_um 11 7620 3810) (pin Round[A]Pad_1397_um 12 5080 3810) (pin Round[A]Pad_1397_um 13 2540 3810) (pin Round[A]Pad_1397_um 14 0 3810) (pin Round[A]Pad_1397_um 15 -2540 3810) (pin Round[A]Pad_1397_um 16 -5080 3810) (pin Round[A]Pad_1397_um 17 -7620 3810) (pin Round[A]Pad_1397_um 18 -10160 3810) ) (image 1pin (outline (path signal 381 2286 0 2174.11 -706.412 1849.41 -1343.68 1343.68 -1849.41 706.412 -2174.11 0 -2286 -706.412 -2174.11 -1343.68 -1849.41 -1849.41 -1343.68 -2174.11 -706.412 -2286 0 -2174.11 706.412 -1849.41 1343.68 -1343.68 1849.41 -706.412 2174.11 0 2286 706.412 2174.11 1343.68 1849.41 1849.41 1343.68 2174.11 706.412)) (pin Round[A]Pad_4064_um 1 0 0) ) (image D2 (outline (path signal 304.8 -2032 -1016 2032 -1016)) (outline (path signal 304.8 -2032 1016 2032 1016)) (outline (path signal 304.8 2794 0 2032 0)) (outline (path signal 304.8 2032 0 2032 1016)) (outline (path signal 304.8 -2032 1016 -2032 0)) (outline (path signal 304.8 -2032 0 -2794 0)) (outline (path signal 304.8 -2032 0 -2032 -1016)) (outline (path signal 304.8 2032 -1016 2032 0)) (outline (path signal 304.8 1524 1016 1524 -1016)) (outline (path signal 304.8 1270 -1016 1270 1016)) (pin Rect[A]Pad_1397x1397_um 2 3556 0) (pin Round[A]Pad_1397_um 1 -3810 0) ) (image RASPI_BPLUS_MIRRORED (outline (path signal 150 48768 49022 53594 49022)) (outline (path signal 150 53594 49022 53594 38354)) (outline (path signal 150 53594 38354 49784 38354)) (outline (path signal 150 -22000 49008 -22000 52508)) (outline (path signal 150 -16000 49008 -16000 52508)) (outline (path signal 150 -7000 48500 -7000 52500)) (outline (path signal 150 6000 48500 6000 52500)) (outline (path signal 150 49500 11032 54000 11032)) (outline (path signal 150 54000 11032 54000 32)) (outline (path signal 150 54000 32 50000 32)) (outline (path signal 150 49500 28032 54000 28032)) (outline (path signal 150 54000 28032 54000 16532)) (outline (path signal 150 54000 16532 49500 16532)) (outline (path signal 150 -32500 -3500 52500 -3500)) (outline (path signal 150 52500 52500 52500 -3500)) (outline (path signal 150 52500 52500 32000 52500)) (outline (path signal 150 -32500 52500 -32500 -3500)) (outline (path signal 150 -32500 52500 32500 52500)) (outline (path signal 304.8 25400 -2540 -25400 -2540)) (outline (path signal 304.8 25400 2540 -25400 2540)) (outline (path signal 304.8 25400 2540 25400 -2540)) (outline (path signal 304.8 -25400 2540 -25400 -2540)) (pin Rect[A]Pad_1524x1524_um 1 -24130 1270) (pin Round[A]Pad_1524_um 2 -24130 -1270) (pin Round[A]Pad_1524_um 11 -11430 1270) (pin Round[A]Pad_1524_um 4 -21590 -1270) (pin Round[A]Pad_1524_um 13 -8890 1270) (pin Round[A]Pad_1524_um 6 -19050 -1270) (pin Round[A]Pad_1524_um 15 -6350 1270) (pin Round[A]Pad_1524_um 8 -16510 -1270) (pin Round[A]Pad_1524_um 17 -3810 1270) (pin Round[A]Pad_1524_um 10 -13970 -1270) (pin Round[A]Pad_1524_um 19 -1270 1270) (pin Round[A]Pad_1524_um 12 -11430 -1270) (pin Round[A]Pad_1524_um 21 1270 1270) (pin Round[A]Pad_1524_um 14 -8890 -1270) (pin Round[A]Pad_1524_um 23 3810 1270) (pin Round[A]Pad_1524_um 16 -6350 -1270) (pin Round[A]Pad_1524_um 25 6350 1270) (pin Round[A]Pad_1524_um 18 -3810 -1270) (pin Round[A]Pad_1524_um 27 8890 1270) (pin Round[A]Pad_1524_um 20 -1270 -1270) (pin Round[A]Pad_1524_um 29 11430 1270) (pin Round[A]Pad_1524_um 22 1270 -1270) (pin Round[A]Pad_1524_um 31 13970 1270) (pin Round[A]Pad_1524_um 24 3810 -1270) (pin Round[A]Pad_1524_um 26 6350 -1270) (pin Round[A]Pad_1524_um 33 16510 1270) (pin Round[A]Pad_1524_um 28 8890 -1270) (pin Round[A]Pad_1524_um 32 13970 -1270) (pin Round[A]Pad_1524_um 34 16510 -1270) (pin Round[A]Pad_1524_um 36 19050 -1270) (pin Round[A]Pad_1524_um 38 21590 -1270) (pin Round[A]Pad_1524_um 35 19050 1270) (pin Round[A]Pad_1524_um 37 21590 1270) (pin Round[A]Pad_1524_um 3 -21590 1270) (pin Round[A]Pad_1524_um 5 -19050 1270) (pin Round[A]Pad_1524_um 7 -16510 1270) (pin Round[A]Pad_1524_um 9 -13970 1270) (pin Round[A]Pad_1524_um 39 24130 1270) (pin Round[A]Pad_1524_um 40 24130 -1270) (pin Round[A]Pad_1524_um 30 11430 -1270) (pin Round[A]Pad_5700_um H2 -29000 0) (pin Round[A]Pad_5700_um H3 29000 0) (pin Round[A]Pad_5700_um H4 29000 49000) (pin Round[A]Pad_5700_um H1 -29000 49000) ) (image D3 (outline (path signal 304.8 3810 0 3048 0)) (outline (path signal 304.8 3048 0 3048 1016)) (outline (path signal 304.8 3048 1016 -3048 1016)) (outline (path signal 304.8 -3048 1016 -3048 0)) (outline (path signal 304.8 -3048 0 -3810 0)) (outline (path signal 304.8 -3048 0 -3048 -1016)) (outline (path signal 304.8 -3048 -1016 3048 -1016)) (outline (path signal 304.8 3048 -1016 3048 0)) (outline (path signal 304.8 2540 1016 2540 -1016)) (outline (path signal 304.8 2286 -1016 2286 1016)) (pin Rect[A]Pad_1397x1397_um 2 3810 0) (pin Round[A]Pad_1397_um 1 -3810 0) ) (image "LED-3-PDP" (outline (path signal 150 -2400 -1500 -2400 1500)) (outline (path signal 150 1500 -2400 -1500 -2400)) (outline (path signal 150 2400 1500 2400 -1500)) (outline (path signal 150 -1500 2400 1500 2400)) (pin Round[A]Pad_1676.4_um 1 -1270 0) (pin Round[A]Pad_1676.4_um 2 1270 0) ) (image SW_KND2_PDP2 (outline (path signal 150 -4750 -1950 -4750 10350)) (outline (path signal 150 4750 10300 4750 -1950)) (outline (path signal 150 -4750 -1958 4750 -1958)) (outline (path signal 150 -4750 10300 -4750 18900)) (outline (path signal 150 4750 10300 4750 18900)) (outline (path signal 150 4750 18900 -4750 18900)) (outline (path signal 150 4750 10300 -4750 10300)) (pin Oval[A]Pad_5080x2540_um 1 0 0) (pin Oval[A]Pad_5080x2540_um 2 0 5580) (pin Round[A]Pad_4000_um 3 0 15000) ) (image PIN_ARRAY_4x1 (outline (path signal 254 5080 -1270 -5080 -1270)) (outline (path signal 254 5080 1270 -5080 1270)) (outline (path signal 254 -5080 1270 -5080 -1270)) (outline (path signal 254 5080 -1270 5080 1270)) (pin Rect[A]Pad_1524x1524_um 1 -3810 0) (pin Round[A]Pad_1524_um 2 -1270 0) (pin Round[A]Pad_1524_um 3 1270 0) (pin Round[A]Pad_1524_um 4 3810 0) ) (image PIN_ARRAY_20X2 (outline (path signal 304.8 25400 -2540 -25400 -2540)) (outline (path signal 304.8 25400 2540 -25400 2540)) (outline (path signal 304.8 25400 2540 25400 -2540)) (outline (path signal 304.8 -25400 2540 -25400 -2540)) (pin Rect[A]Pad_1524x1524_um 1 -24130 -1270) (pin Round[A]Pad_1524_um 2 -24130 1270) (pin Round[A]Pad_1524_um 11 -11430 -1270) (pin Round[A]Pad_1524_um 4 -21590 1270) (pin Round[A]Pad_1524_um 13 -8890 -1270) (pin Round[A]Pad_1524_um 6 -19050 1270) (pin Round[A]Pad_1524_um 15 -6350 -1270) (pin Round[A]Pad_1524_um 8 -16510 1270) (pin Round[A]Pad_1524_um 17 -3810 -1270) (pin Round[A]Pad_1524_um 10 -13970 1270) (pin Round[A]Pad_1524_um 19 -1270 -1270) (pin Round[A]Pad_1524_um 12 -11430 1270) (pin Round[A]Pad_1524_um 21 1270 -1270) (pin Round[A]Pad_1524_um 14 -8890 1270) (pin Round[A]Pad_1524_um 23 3810 -1270) (pin Round[A]Pad_1524_um 16 -6350 1270) (pin Round[A]Pad_1524_um 25 6350 -1270) (pin Round[A]Pad_1524_um 18 -3810 1270) (pin Round[A]Pad_1524_um 27 8890 -1270) (pin Round[A]Pad_1524_um 20 -1270 1270) (pin Round[A]Pad_1524_um 29 11430 -1270) (pin Round[A]Pad_1524_um 22 1270 1270) (pin Round[A]Pad_1524_um 31 13970 -1270) (pin Round[A]Pad_1524_um 24 3810 1270) (pin Round[A]Pad_1524_um 26 6350 1270) (pin Round[A]Pad_1524_um 33 16510 -1270) (pin Round[A]Pad_1524_um 28 8890 1270) (pin Round[A]Pad_1524_um 32 13970 1270) (pin Round[A]Pad_1524_um 34 16510 1270) (pin Round[A]Pad_1524_um 36 19050 1270) (pin Round[A]Pad_1524_um 38 21590 1270) (pin Round[A]Pad_1524_um 35 19050 -1270) (pin Round[A]Pad_1524_um 37 21590 -1270) (pin Round[A]Pad_1524_um 3 -21590 -1270) (pin Round[A]Pad_1524_um 5 -19050 -1270) (pin Round[A]Pad_1524_um 7 -16510 -1270) (pin Round[A]Pad_1524_um 9 -13970 -1270) (pin Round[A]Pad_1524_um 39 24130 -1270) (pin Round[A]Pad_1524_um 40 24130 1270) (pin Round[A]Pad_1524_um 30 11430 1270) ) (image "LED-3-StrEight" (pin Round[A]Pad_1676.4_um 1 -1270 0) (pin Round[A]Pad_1676.4_um 2 1270 0) ) (image PIN_ARRAY_3X1 (outline (path signal 152.4 -3810 -1270 -3810 1270)) (outline (path signal 152.4 -3810 1270 3810 1270)) (outline (path signal 152.4 3810 1270 3810 -1270)) (outline (path signal 152.4 3810 -1270 -3810 -1270)) (outline (path signal 152.4 -1270 1270 -1270 -1270)) (pin Rect[A]Pad_1524x1524_um 1 -2540 0) (pin Round[A]Pad_1524_um 2 0 0) (pin Round[A]Pad_1524_um 3 2540 0) ) (padstack Round[A]Pad_1397_um (shape (circle F.Cu 1397)) (shape (circle B.Cu 1397)) (attach off) ) (padstack Round[A]Pad_1524_um (shape (circle F.Cu 1524)) (shape (circle B.Cu 1524)) (attach off) ) (padstack Round[A]Pad_1676.4_um (shape (circle F.Cu 1676.4)) (shape (circle B.Cu 1676.4)) (attach off) ) (padstack Round[A]Pad_4000_um (shape (circle F.Cu 4000)) (shape (circle B.Cu 4000)) (attach off) ) (padstack Round[A]Pad_4064_um (shape (circle F.Cu 4064)) (shape (circle B.Cu 4064)) (attach off) ) (padstack Round[A]Pad_5700_um (shape (circle F.Cu 5700)) (shape (circle B.Cu 5700)) (attach off) ) (padstack Oval[A]Pad_5080x2540_um (shape (path F.Cu 2540 -1270 0 1270 0)) (shape (path B.Cu 2540 -1270 0 1270 0)) (attach off) ) (padstack Rect[A]Pad_1397x1397_um (shape (rect F.Cu -698.5 -698.5 698.5 698.5)) (shape (rect B.Cu -698.5 -698.5 698.5 698.5)) (attach off) ) (padstack Rect[A]Pad_1524x1524_um (shape (rect F.Cu -762 -762 762 762)) (shape (rect B.Cu -762 -762 762 762)) (attach off) ) (padstack "Via[0-1]_889:635_um" (shape (circle F.Cu 889)) (shape (circle B.Cu 889)) (attach off) ) (padstack "Via[0-1]_889:0_um" (shape (circle F.Cu 889)) (shape (circle B.Cu 889)) (attach off) ) ) (network (net +3.3V (pins P1-1 P3-6 P3-5) ) (net +5V (pins P1-2 P1-4 DZ1-1 P5-2 P3-1 P3-2) ) (net GND (pins P2-10 P1-6 P1-20 P1-9 P1-39 P1-30 R_S2-1 P5-1 P3-8 P3-7) ) (net "N-0000023" (pins P2-9 DZ1-2) ) (net "N-0000028" (pins R1-2 J_COL1-2) ) (net "N-0000029" (pins R2-2 J_COL2-2) ) (net "N-0000035" (pins R_S1-1 R_S2-2 P5-3) ) (net "N-0000039" (pins R6-2 P1-26) ) (net "N-0000040" (pins R10-1 P1-23) ) (net "N-0000041" (pins R_ROW1-1 P1-36) ) (net "N-0000042" (pins R11-1 P1-32) ) (net "N-0000043" (pins R7-1 P1-24) ) (net "N-0000046" (pins R_ROW3-1 P1-12) ) (net "N-0000048" (pins R12-1 P1-33) ) (net "N-0000049" (pins R5-2 P1-31) ) (net "N-0000050" (pins R4-2 P1-29) ) (net "N-0000053" (pins D6-2 SW6-2) ) (net "N-0000054" (pins R8-1 P1-21) ) (net "N-0000055" (pins R9-1 P1-19) ) (net "N-0000056" (pins R_ROW2-1 P1-11) ) (net "N-0000057" (pins R3-2 P1-7) ) (net "N-0000059" (pins D5-2 SW5-2) ) (net "N-0000060" (pins D4-2 SW4-2) ) (net "N-0000061" (pins D3-2 SW3-2) ) (net "N-0000062" (pins D2-2 SW2-2) ) (net "N-0000063" (pins D1-2 SW1-2) ) (net "N-0000065" (pins D22-2 SW22-2) ) (net "N-0000066" (pins D23-2 SW23-2) ) (net "N-0000067" (pins D24-2 SW24-2) ) (net "N-0000068" (pins D25-2 SW25-2) ) (net "N-0000069" (pins D26-2 SW26-2) ) (net "N-0000070" (pins D21-2 SW21-2) ) (net "N-0000071" (pins D7-2 SW7-2) ) (net "N-0000072" (pins D8-2 SW8-2) ) (net "N-0000073" (pins D9-2 SW9-2) ) (net "N-0000074" (pins D10-2 SW10-2) ) (net "N-0000079" (pins D11-2 SW11-2) ) (net "N-0000085" (pins D19-2 SW19-2) ) (net "N-0000086" (pins D20-2 SW20-2) ) (net "N-0000087" (pins D12-2 SW12-2) ) (net "N-0000088" (pins D13-2 SW13-2) ) (net "N-0000089" (pins D14-2 SW14-2) ) (net "N-0000090" (pins D15-2 SW15-2) ) (net "N-0000091" (pins D16-2 SW16-2) ) (net "N-0000092" (pins D17-2 SW17-2) ) (net "N-0000093" (pins D18-2 SW18-2) ) (net RX (pins P1-10 R_S1-2 J_COL2-3) ) (net SPARE_IO (pins P1-35 P3-15 P3-16) ) (net TX (pins P1-8 P5-4 J_COL1-3) ) (net col1 (pins R1-1 D7-1 D1-1 D19-1 DAC1-2 DPC1-2 DMQ1-2 DMA1-2 DMB1-2 DCURAD1-2 DDF1-2 DAND1-2 P3-17 P3-18) ) (net col10 (pins R10-2 D16-1 DMB10-2 DAC10-2 DMQ10-2 DPC10-2 DMA10-2 DEXEC1-2 DSC5-2 P3-36 P3-35) ) (net col11 (pins R11-2 D17-1 DMB11-2 DMQ11-2 DAC11-2 DPC11-2 DMA11-2 DDEFER1-2 P3-38 P3-37) ) (net col12 (pins R12-2 D18-1 DMB12-2 DAC12-2 DMQ12-2 DPC12-2 DMA12-2 DWRDCT1-2 P3-39 P3-40) ) (net col1a (pins P1-3 J_COL1-1) ) (net col2 (pins R2-1 D2-1 D8-1 D20-1 DAC2-2 DMQ2-2 DPC2-2 DMA2-2 DMB2-2 DBREAK1-2 DDF2-2 DTAD1-2 P3-19 P3-20) ) (net col2a (pins P1-5 J_COL2-1) ) (net col3 (pins R3-1 D3-1 D9-1 D21-1 DAC3-2 DMQ3-2 DPC3-2 DMA3-2 DMB3-2 DION1-2 DDF3-2 DISZ1-2 P3-21 P3-22) ) (net col4 (pins R4-1 D22-1 D4-1 D10-1 DAC4-2 DMQ4-2 DPC4-2 DMB4-2 DMA4-2 DPAUSE1-2 DDCA1-2 DIF1-2 P3-23 P3-24 DPAUSE2-2) ) (net col5 (pins R5-1 D23-1 D5-1 D11-1 DAC5-2 DMQ5-2 DPC5-2 DMA5-2 DMB5-2 DRUN1-2 DJMS1-2 DIF2-2 P3-25 P3-26 DRUN2-2) ) (net col6 (pins R6-1 D24-1 D12-1 D6-1 DAC6-2 DMQ6-2 DSC1-2 DPC6-2 DMA6-2 DMB6-2 DJMP1-2 DIF3-2 P3-27 P3-28) ) (net col7 (pins R7-2 D25-1 D13-1 DAC7-2 DMQ7-2 DLINK1-2 DPC7-2 DMA7-2 DMB7-2 DIOT1-2 DSC2-2 P3-29 P3-30) ) (net col8 (pins R8-2 D26-1 D14-1 DAC8-2 DMQ8-2 DPC8-2 DMB8-2 DMA8-2 DOPR1-2 DSC3-2 P3-31 P3-32) ) (net col9 (pins R9-2 D15-1 DMB9-2 DAC9-2 DMQ9-2 DPC9-2 DMA9-2 DFETCH1-2 DSC4-2 P3-33 P3-34) ) (net led1 (pins P2-18 DPC1-1 DPC2-1 DPC3-1 DPC4-1 DPC5-1 DPC6-1 DPC7-1 DPC8-1 DPC9-1 DPC10-1 DPC11-1 DPC12-1) ) (net led2 (pins P2-17 DMA1-1 DMA2-1 DMA3-1 DMA5-1 DMA6-1 DMA7-1 DMA8-1 DMA9-1 DMA10-1 DMA11-1 DMA12-1 DMA4-1) ) (net led3 (pins P2-16 DMB9-1 DMB10-1 DMB11-1 DMB12-1 DMB8-1 DMB1-1 DMB2-1 DMB3-1 DMB4-1 DMB5-1 DMB6-1 DMB7-1) ) (net led4 (pins P2-15 DAC1-1 DAC2-1 DAC3-1 DAC4-1 DAC5-1 DAC6-1 DAC7-1 DAC8-1 DAC9-1 DAC10-1 DAC12-1 DAC11-1) ) (net led5 (pins P2-14 DMQ1-1 DMQ2-1 DMQ3-1 DMQ4-1 DMQ5-1 DMQ6-1 DMQ7-1 DMQ8-1 DMQ9-1 DMQ10-1 DMQ11-1 DMQ12-1) ) (net led6 (pins P2-13 DWRDCT1-1 DDEFER1-1 DEXEC1-1 DFETCH1-1 DOPR1-1 DIOT1-1 DJMP1-1 DJMS1-1 DDCA1-1 DTAD1-1 DAND1-1 DISZ1-1) ) (net led7 (pins P2-12 DSC1-1 DRUN1-1 DPAUSE1-1 DION1-1 DBREAK1-1 DCURAD1-1 DSC2-1 DSC4-1 DSC5-1 DSC3-1 P3-10 P3-9 DPAUSE2-1 DRUN2-1) ) (net led8 (pins P2-11 DLINK1-1 DDF1-1 DDF2-1 DDF3-1 DIF2-1 DIF3-1 DIF1-1 P3-11 P3-12) ) (net row1 (pins R_ROW1-2 SW18-1 SW17-1 SW15-1 SW14-1 SW13-1 SW12-1 SW16-1 SW7-1 SW8-1 SW9-1 SW10-1 SW11-1) ) (net row2 (pins R_ROW2-2 SW6-1 SW5-1 SW4-1 SW3-1 SW2-1 SW1-1 P3-13 P3-14) ) (net row3 (pins R_ROW3-2 SW19-1 SW20-1 SW22-1 SW23-1 SW24-1 SW25-1 SW26-1 SW21-1) ) (net xled1 (pins P2-1 P1-38) ) (net xled2 (pins P2-2 P1-40) ) (net xled3 (pins P2-3 P1-15) ) (net xled4 (pins P2-4 P1-16) ) (net xled5 (pins P2-5 P1-18) ) (net xled6 (pins P2-6 P1-22) ) (net xled7 (pins P2-7 P1-37) ) (net xled8 (pins P2-8 P1-13) ) (class kicad_default "" +3.3V +5V GND "N-0000023" "N-0000028" "N-0000029" "N-0000035" "N-0000039" "N-0000040" "N-0000041" "N-0000042" "N-0000043" "N-0000046" "N-0000048" "N-0000049" "N-0000050" "N-0000053" "N-0000054" "N-0000055" "N-0000056" "N-0000057" "N-0000059" "N-0000060" "N-0000061" "N-0000062" "N-0000063" "N-0000065" "N-0000066" "N-0000067" "N-0000068" "N-0000069" "N-0000070" "N-0000071" "N-0000072" "N-0000073" "N-0000074" "N-0000079" "N-0000085" "N-0000086" "N-0000087" "N-0000088" "N-0000089" "N-0000090" "N-0000091" "N-0000092" "N-0000093" RX SPARE_IO TX col1 col10 col11 col12 col1a col2 col2a col3 col4 col5 col6 col7 col8 col9 led1 led2 led3 led4 led5 led6 led7 led8 row1 row2 row3 xled1 xled2 xled3 xled4 xled5 xled6 xled7 xled8 (circuit (use_via Via[0-1]_889:635_um) ) (rule (width 254) (clearance 254.1) ) ) ) (wiring ) ) |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 | (kicad_pcb (version 3) (host pcbnew "(2013-07-07 BZR 4022)-stable") (general (links 343) (no_connects 0) (area 8.0964 63.949999 288.550001 163.050001) (thickness 1.6) (drawings 11) (tracks 1226) (zones 0) (modules 174) (nets 80) ) (page A4) (layers (15 F.Cu signal) (0 B.Cu signal) (16 B.Adhes user hide) (17 F.Adhes user hide) (18 B.Paste user hide) (19 F.Paste user hide) (20 B.SilkS user hide) (21 F.SilkS user) (22 B.Mask user hide) (23 F.Mask user hide) (24 Dwgs.User user) (25 Cmts.User user) (26 Eco1.User user) (27 Eco2.User user) (28 Edge.Cuts user) ) (setup (last_trace_width 0.254) (trace_clearance 0.254) (zone_clearance 0.508) (zone_45_only no) (trace_min 0.254) (segment_width 0.2) (edge_width 0.1) (via_size 0.889) (via_drill 0.635) (via_min_size 0.889) (via_min_drill 0.508) (uvia_size 0.508) (uvia_drill 0.127) (uvias_allowed no) (uvia_min_size 0.508) (uvia_min_drill 0.127) (pcb_text_width 0.3) (pcb_text_size 1.5 1.5) (mod_edge_width 0.15) (mod_text_size 1 1) (mod_text_width 0.15) (pad_size 5.08 2.54) (pad_drill 3.45) (pad_to_mask_clearance 0) (aux_axis_origin 0 0) (visible_elements 7FFFEB31) (pcbplotparams (layerselection 284196865) (usegerberextensions true) (excludeedgelayer false) (linewidth 0.150000) (plotframeref false) (viasonmask false) (mode 1) (useauxorigin false) (hpglpennumber 1) (hpglpenspeed 20) (hpglpendiameter 15) (hpglpenoverlay 2) (psnegative false) (psa4output false) (plotreference true) (plotvalue true) (plotothertext true) (plotinvisibletext false) (padsonsilk false) (subtractmaskfromsilk true) (outputformat 1) (mirror false) (drillshape 0) (scaleselection 1) (outputdirectory gerber/)) ) (net 0 "") (net 1 +3.3V) (net 2 +5V) (net 3 GND) (net 4 N-0000029) (net 5 N-0000036) (net 6 N-0000037) (net 7 N-0000038) (net 8 N-0000039) (net 9 N-0000040) (net 10 N-0000041) (net 11 N-0000043) (net 12 N-0000044) (net 13 N-0000045) (net 14 N-0000047) (net 15 N-0000048) (net 16 N-0000049) (net 17 N-0000050) (net 18 N-0000051) (net 19 N-0000052) (net 20 N-0000053) (net 21 N-0000055) (net 22 N-0000056) (net 23 N-0000057) (net 24 N-0000059) (net 25 N-0000062) (net 26 N-0000063) (net 27 N-0000064) (net 28 N-0000065) (net 29 N-0000066) (net 30 N-0000067) (net 31 N-0000068) (net 32 N-0000074) (net 33 N-0000080) (net 34 N-0000081) (net 35 N-0000082) (net 36 N-0000083) (net 37 N-0000084) (net 38 N-0000085) (net 39 N-0000086) (net 40 N-0000087) (net 41 N-0000088) (net 42 N-0000089) (net 43 N-0000090) (net 44 RX) (net 45 SPARE_IO) (net 46 TX) (net 47 col1) (net 48 col10) (net 49 col11) (net 50 col12) (net 51 col1a) (net 52 col2) (net 53 col2a) (net 54 col3) (net 55 col4) (net 56 col5) (net 57 col6) (net 58 col7) (net 59 col8) (net 60 col9) (net 61 led1) (net 62 led2) (net 63 led3) (net 64 led4) (net 65 led5) (net 66 led6) (net 67 led7) (net 68 led8) (net 69 row1) (net 70 row2) (net 71 row3) (net 72 xled1) (net 73 xled2) (net 74 xled3) (net 75 xled4) (net 76 xled5) (net 77 xled6) (net 78 xled7) (net 79 xled8) (net_class Default "This is the default net class." (clearance 0.254) (trace_width 0.254) (via_dia 0.889) (via_drill 0.635) (uvia_dia 0.508) (uvia_drill 0.127) (add_net "") (add_net +3.3V) (add_net +5V) (add_net GND) (add_net N-0000029) (add_net N-0000036) (add_net N-0000037) (add_net N-0000038) (add_net N-0000039) (add_net N-0000040) (add_net N-0000041) (add_net N-0000043) (add_net N-0000044) (add_net N-0000045) (add_net N-0000047) (add_net N-0000048) (add_net N-0000049) (add_net N-0000050) (add_net N-0000051) (add_net N-0000052) (add_net N-0000053) (add_net N-0000055) (add_net N-0000056) (add_net N-0000057) (add_net N-0000059) (add_net N-0000062) (add_net N-0000063) (add_net N-0000064) (add_net N-0000065) (add_net N-0000066) (add_net N-0000067) (add_net N-0000068) (add_net N-0000074) (add_net N-0000080) (add_net N-0000081) (add_net N-0000082) (add_net N-0000083) (add_net N-0000084) (add_net N-0000085) (add_net N-0000086) (add_net N-0000087) (add_net N-0000088) (add_net N-0000089) (add_net N-0000090) (add_net RX) (add_net SPARE_IO) (add_net TX) (add_net col1) (add_net col10) (add_net col11) (add_net col12) (add_net col1a) (add_net col2) (add_net col2a) (add_net col3) (add_net col4) (add_net col5) (add_net col6) (add_net col7) (add_net col8) (add_net col9) (add_net led1) (add_net led2) (add_net led3) (add_net led4) (add_net led5) (add_net led6) (add_net led7) (add_net led8) (add_net row1) (add_net row2) (add_net row3) (add_net xled1) (add_net xled2) (add_net xled3) (add_net xled4) (add_net xled5) (add_net xled6) (add_net xled7) (add_net xled8) ) (module D3 (layer B.Cu) (tedit 5551184A) (tstamp 54BD7076) (at 219 117) (descr "Diode 3 pas") (tags "DIODE DEV") (path /54BD85A3) (fp_text reference DZ1 (at 0 0) (layer B.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.2032)) (justify mirror)) ) (fp_text value ZENER (at 0 0) (layer B.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.048 0) (end 3.048 0) (layer B.SilkS) (width 0.3048)) (fp_line (start 3.81 0) (end 3.048 0) (layer B.SilkS) (width 0.3048)) (fp_line (start -3.048 0) (end -3.81 0) (layer B.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 2 +5V) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 2 +5V) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B17F96) (at 57.92 102.94 90) (descr "Resitance 3 pas") (tags R) (path /54908374) (autoplace_cost180 10) (fp_text reference R9 (at 0 -0.127 90) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 90) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 19 N-0000052) ) (pad 2 thru_hole circle (at 3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 60 col9) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B17F87) (at 37.6 102.94 270) (descr "Resitance 3 pas") (tags R) (path /5490833D) (autoplace_cost180 10) (fp_text reference R1 (at 0 -0.127 270) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 270) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 47 col1) ) (pad 2 thru_hole circle (at 3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 46 TX) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B17F67) (at 40.14 102.94 270) (descr "Resitance 3 pas") (tags R) (path /5490834A) (autoplace_cost180 10) (fp_text reference R2 (at 0 -0.127 270) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 270) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 52 col2) ) (pad 2 thru_hole circle (at 3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 44 RX) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B17C46) (at 42.68 102.94 270) (descr "Resitance 3 pas") (tags R) (path /54908350) (autoplace_cost180 10) (fp_text reference R3 (at 0 -0.127 270) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 270) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 54 col3) ) (pad 2 thru_hole circle (at 3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 20 N-0000053) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B17C54) (at 45.22 102.94 270) (descr "Resitance 3 pas") (tags R) (path /54908356) (autoplace_cost180 10) (fp_text reference R4 (at 0 -0.127 270) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 270) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 55 col4) ) (pad 2 thru_hole circle (at 3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 17 N-0000050) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B17C62) (at 47.76 102.94 270) (descr "Resitance 3 pas") (tags R) (path /5490835C) (autoplace_cost180 10) (fp_text reference R5 (at 0 -0.127 270) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 270) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 56 col5) ) (pad 2 thru_hole circle (at 3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 16 N-0000049) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B17C70) (at 50.3 102.94 270) (descr "Resitance 3 pas") (tags R) (path /54908362) (autoplace_cost180 10) (fp_text reference R6 (at 0 -0.127 270) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 270) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 57 col6) ) (pad 2 thru_hole circle (at 3.81 0 270) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 5 N-0000036) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B17C7E) (at 52.84 102.94 90) (descr "Resitance 3 pas") (tags R) (path /54908368) (autoplace_cost180 10) (fp_text reference R7 (at 0 -0.127 90) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 90) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 9 N-0000040) ) (pad 2 thru_hole circle (at 3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 58 col7) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B17C8C) (at 55.38 102.94 90) (descr "Resitance 3 pas") (tags R) (path /5490836E) (autoplace_cost180 10) (fp_text reference R8 (at 0 -0.127 90) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 90) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 18 N-0000051) ) (pad 2 thru_hole circle (at 3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 59 col8) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B1C0BD) (at 60.46 102.94 90) (descr "Resitance 3 pas") (tags R) (path /5490837A) (autoplace_cost180 10) (fp_text reference R10 (at 0 -0.127 90) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 90) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 6 N-0000037) ) (pad 2 thru_hole circle (at 3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 48 col10) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B17CA8) (at 63 102.94 90) (descr "Resitance 3 pas") (tags R) (path /54908380) (autoplace_cost180 10) (fp_text reference R11 (at 0 -0.127 90) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 90) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 8 N-0000039) ) (pad 2 thru_hole circle (at 3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 49 col11) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer B.Cu) (tedit 4E4C0E65) (tstamp 54B17CB6) (at 65.54 102.94 90) (descr "Resitance 3 pas") (tags R) (path /54908386) (autoplace_cost180 10) (fp_text reference R12 (at 0 -0.127 90) (layer B.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_text value 390 (at 0 -0.127 90) (layer B.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032)) (justify mirror)) ) (fp_line (start -3.81 0) (end -3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end -3.302 1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end -3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end 3.302 -1.016) (layer B.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end 3.302 0) (layer B.SilkS) (width 0.2032)) (fp_line (start -3.302 0.508) (end -2.794 1.016) (layer B.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 15 N-0000048) ) (pad 2 thru_hole circle (at 3.81 0 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 50 col12) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer F.Cu) (tedit 4E4C0E65) (tstamp 54B17CC4) (at 78.9 133.08) (descr "Resitance 3 pas") (tags R) (path /5490838C) (autoplace_cost180 10) (fp_text reference R_ROW1 (at 0 0.127) (layer F.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032))) ) (fp_text value 1K (at 0 0.127) (layer F.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032))) ) (fp_line (start -3.81 0) (end -3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 -1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end -3.302 -1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end -3.302 1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end 3.302 1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end 3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 -0.508) (end -2.794 -1.016) (layer F.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 7 N-0000038) ) (pad 2 thru_hole circle (at 3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer F.Cu) (tedit 4E4C0E65) (tstamp 54B17CD2) (at 18.75 129.5 180) (descr "Resitance 3 pas") (tags R) (path /5490839E) (autoplace_cost180 10) (fp_text reference R_ROW2 (at 0 0.127 180) (layer F.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032))) ) (fp_text value 1K (at 0 0.127 180) (layer F.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032))) ) (fp_line (start -3.81 0) (end -3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 -1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end -3.302 -1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end -3.302 1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end 3.302 1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end 3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 -0.508) (end -2.794 -1.016) (layer F.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0 180) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 14 N-0000047) ) (pad 2 thru_hole circle (at 3.81 0 180) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 70 row2) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer F.Cu) (tedit 4E4C0E65) (tstamp 54B17CE0) (at 218.6 133.08) (descr "Resitance 3 pas") (tags R) (path /549083A4) (autoplace_cost180 10) (fp_text reference R_ROW3 (at 0 0.127) (layer F.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032))) ) (fp_text value 1K (at 0 0.127) (layer F.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032))) ) (fp_line (start -3.81 0) (end -3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 -1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end -3.302 -1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end -3.302 1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end 3.302 1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end 3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 -0.508) (end -2.794 -1.016) (layer F.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 10 N-0000041) ) (pad 2 thru_hole circle (at 3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 71 row3) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module DIP-18__300 (layer B.Cu) (tedit 200000) (tstamp 54B17CFD) (at 219.05 100.97 90) (descr "8 pins DIL package, round pads") (path /54B17386) (fp_text reference P2 (at -7.62 1.27 90) (layer B.SilkS) (effects (font (size 1.778 1.143) (thickness 0.3048)) (justify mirror)) ) (fp_text value UDN2981A (at 5.08 -1.27 90) (layer B.SilkS) (effects (font (size 1.778 1.143) (thickness 0.3048)) (justify mirror)) ) (fp_line (start -12.7 1.27) (end -11.43 1.27) (layer B.SilkS) (width 0.381)) (fp_line (start -11.43 1.27) (end -11.43 -1.27) (layer B.SilkS) (width 0.381)) (fp_line (start -11.43 -1.27) (end -12.7 -1.27) (layer B.SilkS) (width 0.381)) (fp_line (start -12.7 2.54) (end 12.7 2.54) (layer B.SilkS) (width 0.381)) (fp_line (start 12.7 2.54) (end 12.7 -2.54) (layer B.SilkS) (width 0.381)) (fp_line (start 12.7 -2.54) (end -12.7 -2.54) (layer B.SilkS) (width 0.381)) (fp_line (start -12.7 -2.54) (end -12.7 2.54) (layer B.SilkS) (width 0.381)) (pad 1 thru_hole rect (at -10.16 -3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 72 xled1) ) (pad 2 thru_hole circle (at -7.62 -3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 73 xled2) ) (pad 3 thru_hole circle (at -5.08 -3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 74 xled3) ) (pad 4 thru_hole circle (at -2.54 -3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 75 xled4) ) (pad 5 thru_hole circle (at 0 -3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 76 xled5) ) (pad 6 thru_hole circle (at 2.54 -3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 77 xled6) ) (pad 7 thru_hole circle (at 5.08 -3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 78 xled7) ) (pad 8 thru_hole circle (at 7.62 -3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 79 xled8) ) (pad 9 thru_hole circle (at 10.16 -3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 2 +5V) ) (pad 10 thru_hole circle (at 10.16 3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 3 GND) ) (pad 11 thru_hole circle (at 7.62 3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 68 led8) ) (pad 12 thru_hole circle (at 5.08 3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 67 led7) ) (pad 13 thru_hole circle (at 2.54 3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 66 led6) ) (pad 14 thru_hole circle (at 0 3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 65 led5) ) (pad 15 thru_hole circle (at -2.54 3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 64 led4) ) (pad 16 thru_hole circle (at -5.08 3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 63 led3) ) (pad 17 thru_hole circle (at -7.62 3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 62 led2) ) (pad 18 thru_hole circle (at -10.16 3.81 90) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask B.SilkS) (net 61 led1) ) (model dil/dil_18.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module 1pin (layer F.Cu) (tedit 200000) (tstamp 54B1C854) (at 13.5 68) (descr "module 1 pin (ou trou mecanique de percage)") (tags DEV) (path /54B1CC4A) (fp_text reference M1 (at 0 -3.048) (layer F.SilkS) (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_text value M (at 0 2.794) (layer F.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_circle (center 0 0) (end 0 -2.286) (layer F.SilkS) (width 0.381)) (pad 1 thru_hole circle (at 0 0) (size 4.064 4.064) (drill 3.048) (layers *.Cu *.Mask F.SilkS) ) ) (module 1pin (layer F.Cu) (tedit 200000) (tstamp 554E4F5F) (at 13.5 159) (descr "module 1 pin (ou trou mecanique de percage)") (tags DEV) (path /54B1CC76) (fp_text reference M2 (at 0 -3.048) (layer F.SilkS) (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_text value M (at 0 2.794) (layer F.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_circle (center 0 0) (end 0 -2.286) (layer F.SilkS) (width 0.381)) (pad 1 thru_hole circle (at 0 0) (size 4.064 4.064) (drill 3.048) (layers *.Cu *.Mask F.SilkS) ) ) (module 1pin (layer F.Cu) (tedit 200000) (tstamp 54B1C860) (at 284.5 68) (descr "module 1 pin (ou trou mecanique de percage)") (tags DEV) (path /54B1CC7C) (fp_text reference M3 (at 0 -3.048) (layer F.SilkS) (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_text value M (at 0 2.794) (layer F.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_circle (center 0 0) (end 0 -2.286) (layer F.SilkS) (width 0.381)) (pad 1 thru_hole circle (at 0 0) (size 4.064 4.064) (drill 3.048) (layers *.Cu *.Mask F.SilkS) ) ) (module 1pin (layer F.Cu) (tedit 200000) (tstamp 54B1C866) (at 285.5 159) (descr "module 1 pin (ou trou mecanique de percage)") (tags DEV) (path /54B1CC82) (fp_text reference M4 (at 0 -3.048) (layer F.SilkS) (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_text value M (at 0 2.794) (layer F.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_circle (center 0 0) (end 0 -2.286) (layer F.SilkS) (width 0.381)) (pad 1 thru_hole circle (at 0 0) (size 4.064 4.064) (drill 3.048) (layers *.Cu *.Mask F.SilkS) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17F78) (at 249 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /549070DB) (fp_text reference D23 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 29 N-0000066) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17D1D) (at 259 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /549070E1) (fp_text reference D24 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 30 N-0000067) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 57 col6) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17D2D) (at 239 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /549070D5) (fp_text reference D22 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 28 N-0000065) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17D3D) (at 269 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /549070E7) (fp_text reference D25 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 31 N-0000068) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 58 col7) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17D4D) (at 279 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /549070ED) (fp_text reference D26 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 24 N-0000059) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 59 col8) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17D5D) (at 139 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /54905640) (fp_text reference D12 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 38 N-0000085) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 57 col6) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17D6D) (at 39 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /5490504C) (fp_text reference D2 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 11 N-0000043) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 52 col2) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17D7D) (at 49 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /54905056) (fp_text reference D3 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 13 N-0000045) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 54 col3) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17D8D) (at 59 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /5490505E) (fp_text reference D4 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 23 N-0000057) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17D9D) (at 69 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /54905068) (fp_text reference D5 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 22 N-0000056) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17DAD) (at 79 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /5490506E) (fp_text reference D6 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 21 N-0000055) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 57 col6) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17DBD) (at 89 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /549055F9) (fp_text reference D7 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 32 N-0000074) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 47 col1) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17DCD) (at 99 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /549055FF) (fp_text reference D8 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 34 N-0000081) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 52 col2) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17DDD) (at 109 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /54905605) (fp_text reference D9 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 35 N-0000082) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 54 col3) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17DED) (at 119 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /5490560B) (fp_text reference D10 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 36 N-0000083) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17DFD) (at 129 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /54905611) (fp_text reference D11 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 37 N-0000084) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17E0D) (at 29 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /54904DF0) (fp_text reference D1 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 12 N-0000044) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 47 col1) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17E1D) (at 149 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /54905646) (fp_text reference D13 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 39 N-0000086) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 58 col7) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17E2D) (at 159 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /5490564C) (fp_text reference D14 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 40 N-0000087) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 59 col8) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17E3D) (at 169 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /54905652) (fp_text reference D15 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 41 N-0000088) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 60 col9) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17E4D) (at 179 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /54905658) (fp_text reference D16 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 33 N-0000080) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 48 col10) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17E5D) (at 189 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /5490565E) (fp_text reference D17 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 42 N-0000089) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 49 col11) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17E6D) (at 199 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /54905664) (fp_text reference D18 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 43 N-0000090) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 50 col12) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17E7D) (at 209 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /549070C3) (fp_text reference D19 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 25 N-0000062) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 47 col1) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17E8D) (at 219 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /549070C9) (fp_text reference D20 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 26 N-0000063) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 52 col2) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module D2 (layer F.Cu) (tedit 54B29F05) (tstamp 54B17E9D) (at 229 136.5) (descr "Diode 3 pas") (tags "DIODE DEV") (path /549070CF) (fp_text reference D21 (at 0 -0.508) (layer F.SilkS) (effects (font (size 0.25 0.25) (thickness 0.05))) ) (fp_text value 1N4148 (at -0.508 0.508) (layer F.SilkS) hide (effects (font (size 0.381 0.381) (thickness 0.0762))) ) (fp_line (start -2.032 1.016) (end 2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.794 0) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 0) (end 2.032 -1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 -1.016) (end -2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.794 0) (layer F.SilkS) (width 0.3048)) (fp_line (start -2.032 0) (end -2.032 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 2.032 1.016) (end 2.032 0) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.524 -1.016) (end 1.524 1.016) (layer F.SilkS) (width 0.3048)) (fp_line (start 1.27 1.016) (end 1.27 -1.016) (layer F.SilkS) (width 0.3048)) (pad 2 thru_hole rect (at 3.556 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 27 N-0000064) ) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 54 col3) ) (model discret/diode.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module RASPI_BPLUS_MIRRORED (layer B.Cu) (tedit 54BD7BC3) (tstamp 54B1C6FA) (at 64 124 180) (descr "Double rangee de contacts 2 x 12 pins") (tags CONN) (path /548F13F7) (fp_text reference P1 (at 0 3.81 180) (layer B.SilkS) (effects (font (size 1.016 1.016) (thickness 0.27432)) (justify mirror)) ) (fp_text value RASPI_MODEL_B_PLUS_GPIO (at 0 -3.81 180) (layer B.SilkS) (effects (font (size 1.016 1.016) (thickness 0.2032)) (justify mirror)) ) (fp_text user ETH (at 49.53 43.18 450) (layer B.SilkS) (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) ) (fp_line (start 48.768 49.022) (end 53.594 49.022) (layer B.SilkS) (width 0.15)) (fp_line (start 53.594 49.022) (end 53.594 38.354) (layer B.SilkS) (width 0.15)) (fp_line (start 53.594 38.354) (end 49.784 38.354) (layer B.SilkS) (width 0.15)) (fp_text user "GPIO and mount holes exact, port placement approx." (at 8 40.5 180) (layer B.SilkS) (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) ) (fp_text user "RASPI B PLUS (MIRROR IMAGE)" (at 7.5 43 180) (layer B.SilkS) (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) ) (fp_text user microUSB (at -19 47 180) (layer B.SilkS) (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) ) (fp_line (start -22 49.008) (end -22 52.508) (layer B.SilkS) (width 0.15)) (fp_line (start -16 49.008) (end -16 52.508) (layer B.SilkS) (width 0.15)) (fp_text user HDMI (at 0 47 180) (layer B.SilkS) (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) ) (fp_line (start -7 48.5) (end -7 52.5) (layer B.SilkS) (width 0.15)) (fp_line (start 6 48.5) (end 6 52.5) (layer B.SilkS) (width 0.15)) (fp_text user USB (at 49.5 3.5 450) (layer B.SilkS) (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) ) (fp_text user USB (at 49.5 20.5 450) (layer B.SilkS) (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) ) (fp_line (start 49.5 11.032) (end 54 11.032) (layer B.SilkS) (width 0.15)) (fp_line (start 54 11.032) (end 54 0.032) (layer B.SilkS) (width 0.15)) (fp_line (start 54 0.032) (end 50 0.032) (layer B.SilkS) (width 0.15)) (fp_line (start 49.5 28.032) (end 54 28.032) (layer B.SilkS) (width 0.15)) (fp_line (start 54 28.032) (end 54 16.532) (layer B.SilkS) (width 0.15)) (fp_line (start 54 16.532) (end 49.5 16.532) (layer B.SilkS) (width 0.15)) (fp_line (start -32.5 -3.5) (end 52.5 -3.5) (layer B.SilkS) (width 0.15)) (fp_line (start 52.5 52.5) (end 52.5 -3.5) (layer B.SilkS) (width 0.15)) (fp_line (start 52.5 52.5) (end 32 52.5) (layer B.SilkS) (width 0.15)) (fp_line (start -32.5 52.5) (end -32.5 -3.5) (layer B.SilkS) (width 0.15)) (fp_line (start -32.5 52.5) (end 32.5 52.5) (layer B.SilkS) (width 0.15)) (fp_line (start 25.4 -2.54) (end -25.4 -2.54) (layer B.SilkS) (width 0.3048)) (fp_line (start 25.4 2.54) (end -25.4 2.54) (layer B.SilkS) (width 0.3048)) (fp_line (start 25.4 2.54) (end 25.4 -2.54) (layer B.SilkS) (width 0.3048)) (fp_line (start -25.4 2.54) (end -25.4 -2.54) (layer B.SilkS) (width 0.3048)) (pad 1 thru_hole rect (at -24.13 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 1 +3.3V) ) (pad 2 thru_hole circle (at -24.13 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 2 +5V) ) (pad 11 thru_hole circle (at -11.43 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 14 N-0000047) ) (pad 4 thru_hole circle (at -21.59 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 2 +5V) ) (pad 13 thru_hole circle (at -8.89 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 79 xled8) ) (pad 6 thru_hole circle (at -19.05 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 3 GND) ) (pad 15 thru_hole circle (at -6.35 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 74 xled3) ) (pad 8 thru_hole circle (at -16.51 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 46 TX) ) (pad 17 thru_hole circle (at -3.81 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) ) (pad 10 thru_hole circle (at -13.97 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 44 RX) ) (pad 19 thru_hole circle (at -1.27 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 19 N-0000052) ) (pad 12 thru_hole circle (at -11.43 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 10 N-0000041) ) (pad 21 thru_hole circle (at 1.27 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 18 N-0000051) ) (pad 14 thru_hole circle (at -8.89 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) ) (pad 23 thru_hole circle (at 3.81 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 6 N-0000037) ) (pad 16 thru_hole circle (at -6.35 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 75 xled4) ) (pad 25 thru_hole circle (at 6.35 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) ) (pad 18 thru_hole circle (at -3.81 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 76 xled5) ) (pad 27 thru_hole circle (at 8.89 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) ) (pad 20 thru_hole circle (at -1.27 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 3 GND) ) (pad 29 thru_hole circle (at 11.43 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 17 N-0000050) ) (pad 22 thru_hole circle (at 1.27 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 77 xled6) ) (pad 31 thru_hole circle (at 13.97 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 16 N-0000049) ) (pad 24 thru_hole circle (at 3.81 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 9 N-0000040) ) (pad 26 thru_hole circle (at 6.35 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 5 N-0000036) ) (pad 33 thru_hole circle (at 16.51 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 15 N-0000048) ) (pad 28 thru_hole circle (at 8.89 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) ) (pad 32 thru_hole circle (at 13.97 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 8 N-0000039) ) (pad 34 thru_hole circle (at 16.51 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) ) (pad 36 thru_hole circle (at 19.05 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 7 N-0000038) ) (pad 38 thru_hole circle (at 21.59 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 72 xled1) ) (pad 35 thru_hole circle (at 19.05 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 45 SPARE_IO) ) (pad 37 thru_hole circle (at 21.59 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 78 xled7) ) (pad 3 thru_hole circle (at -21.59 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 51 col1a) ) (pad 5 thru_hole circle (at -19.05 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 53 col2a) ) (pad 7 thru_hole circle (at -16.51 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 20 N-0000053) ) (pad 9 thru_hole circle (at -13.97 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 3 GND) ) (pad 39 thru_hole circle (at 24.13 1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 3 GND) ) (pad 40 thru_hole circle (at 24.13 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 73 xled2) ) (pad 30 thru_hole circle (at 11.43 -1.27 180) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 3 GND) ) (pad H2 thru_hole circle (at -29 0 180) (size 5.7 5.7) (drill 2.75) (layers *.Cu *.Mask B.SilkS) ) (pad H3 thru_hole circle (at 29 0 180) (size 5.7 5.7) (drill 2.75) (layers *.Cu *.Mask B.SilkS) ) (pad H4 thru_hole circle (at 29 49 180) (size 5.7 5.7) (drill 2.75) (layers *.Cu *.Mask B.SilkS) ) (pad H1 thru_hole circle (at -29 49 180) (size 5.7 5.7) (drill 2.75) (layers *.Cu *.Mask B.SilkS) ) (model pin_array/pins_array_20x2.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module 1pin (layer F.Cu) (tedit 200000) (tstamp 54BD0940) (at 208 68) (descr "module 1 pin (ou trou mecanique de percage)") (tags DEV) (path /54BD36C6) (fp_text reference M5 (at 0 -3.048) (layer F.SilkS) (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_text value M (at 0 2.794) (layer F.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_circle (center 0 0) (end 0 -2.286) (layer F.SilkS) (width 0.381)) (pad 1 thru_hole circle (at 0 0) (size 4.064 4.064) (drill 3.048) (layers *.Cu *.Mask F.SilkS) ) ) (module 1pin (layer F.Cu) (tedit 200000) (tstamp 54BD0946) (at 284.5 132) (descr "module 1 pin (ou trou mecanique de percage)") (tags DEV) (path /54BD36CC) (fp_text reference M6 (at 0 -3.048) (layer F.SilkS) (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_text value M (at 0 2.794) (layer F.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_circle (center 0 0) (end 0 -2.286) (layer F.SilkS) (width 0.381)) (pad 1 thru_hole circle (at 0 0) (size 4.064 4.064) (drill 3.048) (layers *.Cu *.Mask F.SilkS) ) ) (module 1pin (layer F.Cu) (tedit 200000) (tstamp 54BD094C) (at 208 132) (descr "module 1 pin (ou trou mecanique de percage)") (tags DEV) (path /54BD36D2) (fp_text reference M7 (at 0 -3.048) (layer F.SilkS) (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_text value M (at 0 2.794) (layer F.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.254))) ) (fp_circle (center 0 0) (end 0 -2.286) (layer F.SilkS) (width 0.381)) (pad 1 thru_hole circle (at 0 0) (size 4.064 4.064) (drill 3.048) (layers *.Cu *.Mask F.SilkS) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F22E4) (at 169 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5B2) (fp_text reference DMB9 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 60 col9) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F22CB) (at 179 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5B8) (fp_text reference DMB10 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 48 col10) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F22B2) (at 189 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5BE) (fp_text reference DMB11 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 49 col11) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2299) (at 199 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5C4) (fp_text reference DMB12 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 50 col12) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2280) (at 89 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5CC) (fp_text reference DAC1 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 47 col1) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2267) (at 99 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5E5) (fp_text reference DAC2 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 52 col2) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F224E) (at 109 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5EB) (fp_text reference DAC3 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 54 col3) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2235) (at 119 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5F1) (fp_text reference DAC4 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F221C) (at 129 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5F7) (fp_text reference DAC5 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2203) (at 139 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5FD) (fp_text reference DAC6 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 57 col6) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F21EA) (at 149 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF603) (fp_text reference DAC7 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 58 col7) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F21D1) (at 159 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF609) (fp_text reference DAC8 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 59 col8) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F21B8) (at 169 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF60F) (fp_text reference DAC9 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 60 col9) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F219F) (at 179 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF615) (fp_text reference DAC10 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 48 col10) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2186) (at 89 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF34A) (fp_text reference DPC1 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 47 col1) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F216D) (at 199 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF621) (fp_text reference DAC12 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 50 col12) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2154) (at 89 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF629) (fp_text reference DMQ1 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 47 col1) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F213B) (at 99 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF642) (fp_text reference DMQ2 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 52 col2) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2122) (at 109 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF648) (fp_text reference DMQ3 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 54 col3) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2109) (at 119 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF64E) (fp_text reference DMQ4 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F20F0) (at 129 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF654) (fp_text reference DMQ5 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F20D7) (at 139 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF65A) (fp_text reference DMQ6 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 57 col6) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F20BE) (at 149 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF660) (fp_text reference DMQ7 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 58 col7) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F20A5) (at 159 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF666) (fp_text reference DMQ8 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 59 col8) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F208C) (at 169 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF66C) (fp_text reference DMQ9 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 60 col9) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2073) (at 179 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF672) (fp_text reference DMQ10 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 48 col10) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F205A) (at 189 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF678) (fp_text reference DMQ11 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 49 col11) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2041) (at 199 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF67E) (fp_text reference DMQ12 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 65 led5) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 50 col12) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F2028) (at 79 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF686) (fp_text reference DLINK1 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 68 led8) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 58 col7) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F200F) (at 29 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF6A1) (fp_text reference DSC1 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 57 col6) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1FF6) (at 189 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF61B) (fp_text reference DAC11 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 64 led4) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 49 col11) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1FDD) (at 99 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF399) (fp_text reference DPC2 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 52 col2) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1FC4) (at 109 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF3AC) (fp_text reference DPC3 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 54 col3) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1FAB) (at 119 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF3B2) (fp_text reference DPC4 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1F92) (at 129 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF3B8) (fp_text reference DPC5 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1F79) (at 139 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF3BE) (fp_text reference DPC6 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 57 col6) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1F60) (at 149 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF3C4) (fp_text reference DPC7 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 58 col7) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1F47) (at 159 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF3CA) (fp_text reference DPC8 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 59 col8) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1F2E) (at 169 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF3D0) (fp_text reference DPC9 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 60 col9) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1F15) (at 179 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF3D6) (fp_text reference DPC10 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 48 col10) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1EFC) (at 189 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF3DC) (fp_text reference DPC11 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 49 col11) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1EE3) (at 199 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF3E2) (fp_text reference DPC12 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 61 led1) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 50 col12) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1ECA) (at 89 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF463) (fp_text reference DMA1 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 47 col1) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1EB1) (at 99 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF47C) (fp_text reference DMA2 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 52 col2) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1E98) (at 109 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF482) (fp_text reference DMA3 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 54 col3) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1E7F) (at 159 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5AC) (fp_text reference DMB8 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 59 col8) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1E66) (at 129 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF48E) (fp_text reference DMA5 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1E4D) (at 139 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF494) (fp_text reference DMA6 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 57 col6) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1E34) (at 149 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF49A) (fp_text reference DMA7 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 58 col7) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1E1B) (at 159 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF4A0) (fp_text reference DMA8 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 59 col8) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1E02) (at 169 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF4A6) (fp_text reference DMA9 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 60 col9) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1DE9) (at 179 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF4AC) (fp_text reference DMA10 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 48 col10) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1DD0) (at 189 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF4B2) (fp_text reference DMA11 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 49 col11) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1DB7) (at 199 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF4B8) (fp_text reference DMA12 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 50 col12) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1D9E) (at 89 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF56F) (fp_text reference DMB1 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 47 col1) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1D85) (at 99 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF588) (fp_text reference DMB2 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 52 col2) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1D6C) (at 109 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF58E) (fp_text reference DMB3 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 54 col3) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1D53) (at 119 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF594) (fp_text reference DMB4 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1D3A) (at 129 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF59A) (fp_text reference DMB5 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1D21) (at 139 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5A0) (fp_text reference DMB6 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 57 col6) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1D08) (at 149 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF5A6) (fp_text reference DMB7 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 63 led3) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 58 col7) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1CEF) (at 119 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF488) (fp_text reference DMA4 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 62 led2) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD77AA) (tstamp 548F1CD6) (at 279 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF843) (fp_text reference DRUN1 (at -9 -1.7) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD77A3) (tstamp 548F1CBD) (at 279 77.9) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF83D) (fp_text reference DPAUSE1 (at -8.5 -1.9) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD77A5) (tstamp 548F1CA4) (at 279 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF837) (fp_text reference DION1 (at -9.5 -2.1) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 54 col3) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD778C) (tstamp 548F1C8B) (at 259 107.1) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF7E9) (fp_text reference DBREAK1 (at -8.5 -1.6) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 52 col2) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7784) (tstamp 548F1C72) (at 259 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF7E3) (fp_text reference DCURAD1 (at -8.5 -1.8) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 47 col1) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD777C) (tstamp 548F1C59) (at 259 92.5) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF7DD) (fp_text reference DWRDCT1 (at -8.5 -2) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 50 col12) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7779) (tstamp 548F1C40) (at 259 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF7D7) (fp_text reference DDEFER1 (at -8.5 -1.7) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 49 col11) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7795) (tstamp 548F1C27) (at 259 77.9) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF7D1) (fp_text reference DEXEC1 (at -9 -1.9) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 48 col10) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7797) (tstamp 548F1C0E) (at 259 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF7CB) (fp_text reference DFETCH1 (at -9 -2.1) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 60 col9) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD774F) (tstamp 548F1BF5) (at 239 121.7) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF789) (fp_text reference DOPR1 (at -7.5 -1.7) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 59 col8) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD773D) (tstamp 548F1BDC) (at 239 114.4) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF783) (fp_text reference DIOT1 (at -7.5 -1.9) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 58 col7) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7737) (tstamp 548F1BC3) (at 239 107.1) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF77D) (fp_text reference DJMP1 (at -7.5 -1.6) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 57 col6) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD772E) (tstamp 548F1BAA) (at 239 99.8) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF777) (fp_text reference DJMS1 (at -8 -1.8) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7708) (tstamp 548F1B91) (at 239 92.5) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF741) (fp_text reference DDCA1 (at -8 -1.5) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1B78) (at 39 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF6BA) (fp_text reference DSC2 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 58 col7) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1B5F) (at 59 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF6C6) (fp_text reference DSC4 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 60 col9) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1B46) (at 69 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF6CC) (fp_text reference DSC5 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 48 col10) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1B14) (at 29 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF6DA) (fp_text reference DDF1 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 68 led8) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 47 col1) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1AFB) (at 39 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF6F3) (fp_text reference DDF2 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 68 led8) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 52 col2) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1AE2) (at 49 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF6F9) (fp_text reference DDF3 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 68 led8) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 54 col3) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1AC9) (at 49 129) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF6C0) (fp_text reference DSC3 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 59 col8) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7714) (tstamp 548F1AB0) (at 239 77.9) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF735) (fp_text reference DTAD1 (at -8 -1.9) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 52 col2) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7712) (tstamp 548F1A97) (at 239 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF728) (fp_text reference DAND1 (at -8 -2.1) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 47 col1) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD771B) (tstamp 548F1A7E) (at 239 85.2) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF73B) (fp_text reference DISZ1 (at -8 -1.7) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 66 led6) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 54 col3) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1A65) (at 69 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF71A) (fp_text reference DIF2 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 68 led8) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1A4C) (at 79 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF720) (fp_text reference DIF3 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 68 led8) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 57 col6) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-PDP (layer F.Cu) (tedit 54BD7621) (tstamp 548F1A33) (at 59 70.6) (descr "LED 3mm - Lead pitch 100mil (2,54mm)") (tags "LED led 3mm 3MM 100mil 2,54mm") (path /548EF701) (fp_text reference DIF1 (at 0 -5.5372) (layer F.SilkS) (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (fp_line (start -2.4 1.5) (end -2.4 -1.5) (layer F.SilkS) (width 0.15)) (fp_line (start 1.5 2.4) (end -1.5 2.4) (layer F.SilkS) (width 0.15)) (fp_line (start 2.4 -1.5) (end 2.4 1.5) (layer F.SilkS) (width 0.15)) (fp_line (start -1.5 -2.4) (end 1.5 -2.4) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 1.5) (end -1.5 2.4) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 1.5) (end 2.4 1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start -1.5 -1.5) (end -2.4 -1.5) (angle 90) (layer F.SilkS) (width 0.15)) (fp_arc (start 1.5 -1.5) (end 1.5 -2.4) (angle 90) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 68 led8) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F19EA) (at 79 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFC1B) (fp_text reference SW6 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value IF3 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 70 row2) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 21 N-0000055) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F19D9) (at 69 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFC15) (fp_text reference SW5 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value IF2 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 70 row2) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 22 N-0000056) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F19C8) (at 59 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFC0F) (fp_text reference SW4 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value IF1 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 70 row2) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 23 N-0000057) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F19B7) (at 49 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFC09) (fp_text reference SW3 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value DF3 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 70 row2) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 13 N-0000045) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F19A6) (at 39 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFC03) (fp_text reference SW2 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value DF2 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 70 row2) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 11 N-0000043) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1995) (at 29 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFBFD) (fp_text reference SW1 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value DF1 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 70 row2) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 12 N-0000044) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1984) (at 199 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFB6C) (fp_text reference SW18 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR12 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 43 N-0000090) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1973) (at 189 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFB66) (fp_text reference SW17 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR11 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 42 N-0000089) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1962) (at 169 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFB5A) (fp_text reference SW15 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR9 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 41 N-0000088) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1951) (at 159 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFB54) (fp_text reference SW14 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR8 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 40 N-0000087) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1940) (at 149 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFB4E) (fp_text reference SW13 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR7 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 39 N-0000086) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F192F) (at 139 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFB48) (fp_text reference SW12 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR6 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 38 N-0000085) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F191E) (at 209 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EF86F) (fp_text reference SW19 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value START (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 71 row3) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 25 N-0000062) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F190D) (at 219 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EF87C) (fp_text reference SW20 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value LOAD_ADD (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 71 row3) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 26 N-0000063) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F18FC) (at 179 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFB60) (fp_text reference SW16 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR10 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 33 N-0000080) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F18EB) (at 239 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EF888) (fp_text reference SW22 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value EXAM (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 71 row3) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 28 N-0000065) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F18DA) (at 249 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EF88E) (fp_text reference SW23 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value CONT (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 71 row3) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 29 N-0000066) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F18C9) (at 259 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EF894) (fp_text reference SW24 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value STOP (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 71 row3) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 30 N-0000067) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F18B8) (at 269 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EF89A) (fp_text reference SW25 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SING_STEP (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 71 row3) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 31 N-0000068) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F18A7) (at 279 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EF8A0) (fp_text reference SW26 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SING_INST (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 71 row3) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 24 N-0000059) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1896) (at 89 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFAF8) (fp_text reference SW7 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR1 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 32 N-0000074) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1885) (at 99 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFB27) (fp_text reference SW8 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR2 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 34 N-0000081) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1874) (at 109 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFB2D) (fp_text reference SW9 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR3 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 35 N-0000082) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1863) (at 119 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFB33) (fp_text reference SW10 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR4 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 36 N-0000083) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1852) (at 129 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EFB42) (fp_text reference SW11 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value SR5 (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 69 row1) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 37 N-0000084) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module SW_KND2_PDP2 (layer F.Cu) (tedit 554E2AD7) (tstamp 548F1841) (at 229 159.5) (descr "Switch inverseur") (tags "SWITCH DEV") (path /548EF882) (fp_text reference SW21 (at 3.429 -3.683 90) (layer F.SilkS) hide (effects (font (size 0.3 0.3) (thickness 0.05))) ) (fp_text value DEP (at -0.05 -20.3) (layer F.SilkS) (effects (font (size 1.2 1.2) (thickness 0.2032))) ) (fp_line (start -4.75 1.95) (end -4.75 -10.35) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 1.95) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 1.958) (end 4.75 1.958) (layer F.SilkS) (width 0.15)) (fp_line (start -4.75 -10.3) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end 4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -18.9) (end -4.75 -18.9) (layer F.SilkS) (width 0.15)) (fp_line (start 4.75 -10.3) (end -4.75 -10.3) (layer F.SilkS) (width 0.15)) (pad 1 thru_hole oval (at 0 0) (size 5.08 2.54) (drill oval 3.45 1.18) (layers *.Cu *.Mask F.SilkS) (net 71 row3) ) (pad 2 thru_hole oval (at 0 -5.58) (size 5.08 2.54) (drill oval 3.45 1.15) (layers *.Cu *.Mask F.SilkS) (net 27 N-0000064) ) (pad 3 thru_hole circle (at 0 -15) (size 4 4) (drill 3) (layers *.Cu *.Mask F.SilkS) ) ) (module R3 (layer F.Cu) (tedit 4E4C0E65) (tstamp 554E2BA1) (at 18.75 133) (descr "Resitance 3 pas") (tags R) (path /554E5219) (autoplace_cost180 10) (fp_text reference R_S1 (at 0 0.127) (layer F.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032))) ) (fp_text value 300 (at 0 0.127) (layer F.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032))) ) (fp_line (start -3.81 0) (end -3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 -1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end -3.302 -1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end -3.302 1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end 3.302 1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end 3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 -0.508) (end -2.794 -1.016) (layer F.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 4 N-0000029) ) (pad 2 thru_hole circle (at 3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 44 RX) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module R3 (layer F.Cu) (tedit 4E4C0E65) (tstamp 554E2BAF) (at 18.75 136.5) (descr "Resitance 3 pas") (tags R) (path /554E5233) (autoplace_cost180 10) (fp_text reference R_S2 (at 0 0.127) (layer F.SilkS) hide (effects (font (size 1.397 1.27) (thickness 0.2032))) ) (fp_text value 620 (at 0 0.127) (layer F.SilkS) (effects (font (size 1.397 1.27) (thickness 0.2032))) ) (fp_line (start -3.81 0) (end -3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.81 0) (end 3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 0) (end 3.302 -1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 -1.016) (end -3.302 -1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 -1.016) (end -3.302 1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 1.016) (end 3.302 1.016) (layer F.SilkS) (width 0.2032)) (fp_line (start 3.302 1.016) (end 3.302 0) (layer F.SilkS) (width 0.2032)) (fp_line (start -3.302 -0.508) (end -2.794 -1.016) (layer F.SilkS) (width 0.2032)) (pad 1 thru_hole circle (at -3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 3 GND) ) (pad 2 thru_hole circle (at 3.81 0) (size 1.397 1.397) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 4 N-0000029) ) (model discret/resistor.wrl (at (xyz 0 0 0)) (scale (xyz 0.3 0.3 0.3)) (rotate (xyz 0 0 0)) ) ) (module PIN_ARRAY_4x1 (layer F.Cu) (tedit 4C10F42E) (tstamp 554E2BBB) (at 11.5 136 270) (descr "Double rangee de contacts 2 x 5 pins") (tags CONN) (path /554E5206) (fp_text reference P5 (at 0 -2.54 270) (layer F.SilkS) (effects (font (size 1.016 1.016) (thickness 0.2032))) ) (fp_text value "SERIAL 5V TTL" (at 0 2.54 270) (layer F.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.2032))) ) (fp_line (start 5.08 1.27) (end -5.08 1.27) (layer F.SilkS) (width 0.254)) (fp_line (start 5.08 -1.27) (end -5.08 -1.27) (layer F.SilkS) (width 0.254)) (fp_line (start -5.08 -1.27) (end -5.08 1.27) (layer F.SilkS) (width 0.254)) (fp_line (start 5.08 1.27) (end 5.08 -1.27) (layer F.SilkS) (width 0.254)) (pad 1 thru_hole rect (at -3.81 0 270) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask F.SilkS) (net 3 GND) ) (pad 2 thru_hole circle (at -1.27 0 270) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask F.SilkS) (net 2 +5V) ) (pad 3 thru_hole circle (at 1.27 0 270) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask F.SilkS) (net 4 N-0000029) ) (pad 4 thru_hole circle (at 3.81 0 270) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask F.SilkS) (net 46 TX) ) (model pin_array\pins_array_4x1.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module PIN_ARRAY_20X2 (layer B.Cu) (tedit 5031D84E) (tstamp 54BD2EE9) (at 253.9 130.05) (descr "Double rangee de contacts 2 x 12 pins") (tags CONN) (path /554E0D39) (fp_text reference P3 (at 0 3.81) (layer B.SilkS) (effects (font (size 1.016 1.016) (thickness 0.27432)) (justify mirror)) ) (fp_text value EXPANSION_20X2 (at 0 -3.81) (layer B.SilkS) (effects (font (size 1.016 1.016) (thickness 0.2032)) (justify mirror)) ) (fp_line (start 25.4 -2.54) (end -25.4 -2.54) (layer B.SilkS) (width 0.3048)) (fp_line (start 25.4 2.54) (end -25.4 2.54) (layer B.SilkS) (width 0.3048)) (fp_line (start 25.4 2.54) (end 25.4 -2.54) (layer B.SilkS) (width 0.3048)) (fp_line (start -25.4 2.54) (end -25.4 -2.54) (layer B.SilkS) (width 0.3048)) (pad 1 thru_hole rect (at -24.13 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 2 +5V) ) (pad 2 thru_hole circle (at -24.13 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 2 +5V) ) (pad 11 thru_hole circle (at -11.43 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 68 led8) ) (pad 4 thru_hole circle (at -21.59 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) ) (pad 13 thru_hole circle (at -8.89 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 70 row2) ) (pad 6 thru_hole circle (at -19.05 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 1 +3.3V) ) (pad 15 thru_hole circle (at -6.35 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 45 SPARE_IO) ) (pad 8 thru_hole circle (at -16.51 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 3 GND) ) (pad 17 thru_hole circle (at -3.81 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 47 col1) ) (pad 10 thru_hole circle (at -13.97 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 67 led7) ) (pad 19 thru_hole circle (at -1.27 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 52 col2) ) (pad 12 thru_hole circle (at -11.43 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 68 led8) ) (pad 21 thru_hole circle (at 1.27 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 54 col3) ) (pad 14 thru_hole circle (at -8.89 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 70 row2) ) (pad 23 thru_hole circle (at 3.81 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 55 col4) ) (pad 16 thru_hole circle (at -6.35 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 45 SPARE_IO) ) (pad 25 thru_hole circle (at 6.35 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 56 col5) ) (pad 18 thru_hole circle (at -3.81 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 47 col1) ) (pad 27 thru_hole circle (at 8.89 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 57 col6) ) (pad 20 thru_hole circle (at -1.27 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 52 col2) ) (pad 29 thru_hole circle (at 11.43 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 58 col7) ) (pad 22 thru_hole circle (at 1.27 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 54 col3) ) (pad 31 thru_hole circle (at 13.97 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 59 col8) ) (pad 24 thru_hole circle (at 3.81 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 55 col4) ) (pad 26 thru_hole circle (at 6.35 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 56 col5) ) (pad 33 thru_hole circle (at 16.51 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 60 col9) ) (pad 28 thru_hole circle (at 8.89 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 57 col6) ) (pad 32 thru_hole circle (at 13.97 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 59 col8) ) (pad 34 thru_hole circle (at 16.51 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 60 col9) ) (pad 36 thru_hole circle (at 19.05 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 48 col10) ) (pad 38 thru_hole circle (at 21.59 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 49 col11) ) (pad 35 thru_hole circle (at 19.05 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 48 col10) ) (pad 37 thru_hole circle (at 21.59 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 49 col11) ) (pad 3 thru_hole circle (at -21.59 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) ) (pad 5 thru_hole circle (at -19.05 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 1 +3.3V) ) (pad 7 thru_hole circle (at -16.51 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 3 GND) ) (pad 9 thru_hole circle (at -13.97 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 67 led7) ) (pad 39 thru_hole circle (at 24.13 -1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 50 col12) ) (pad 40 thru_hole circle (at 24.13 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 50 col12) ) (pad 30 thru_hole circle (at 11.43 1.27) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 58 col7) ) (model pin_array/pins_array_20x2.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-StrEight (layer F.Cu) (tedit 554E561D) (tstamp 554E5741) (at 259 114.4) (descr LED) (tags LED) (path /554E5897) (fp_text reference DPAUSE2 (at 0 -5.5372) (layer F.SilkS) hide (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 55 col4) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module LED-3-StrEight (layer F.Cu) (tedit 554E561D) (tstamp 554E5747) (at 259 121.7) (descr LED) (tags LED) (path /554E589D) (fp_text reference DRUN2 (at 0 -5.5372) (layer F.SilkS) hide (effects (font (size 0.7 0.7) (thickness 0.025))) ) (fp_text value LED (at 0 2.54) (layer F.SilkS) hide (effects (font (size 0.762 0.762) (thickness 0.0889))) ) (pad 1 thru_hole circle (at -1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 67 led7) ) (pad 2 thru_hole circle (at 1.27 0) (size 1.6764 1.6764) (drill 0.8128) (layers *.Cu *.Mask F.SilkS) (net 56 col5) ) (model discret/leds/led3_vertical_verde.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module PIN_ARRAY_3X1 (layer B.Cu) (tedit 554F4504) (tstamp 554F4492) (at 64.3 111.8) (descr "Connecteur 3 pins") (tags "CONN DEV") (path /554F46DF) (fp_text reference J_COL1 (at -6.7 0) (layer B.SilkS) (effects (font (size 1.016 1.016) (thickness 0.1524)) (justify mirror)) ) (fp_text value CONN_3 (at 0 2.159) (layer B.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.1524)) (justify mirror)) ) (fp_line (start -3.81 -1.27) (end -3.81 1.27) (layer B.SilkS) (width 0.1524)) (fp_line (start -3.81 1.27) (end 3.81 1.27) (layer B.SilkS) (width 0.1524)) (fp_line (start 3.81 1.27) (end 3.81 -1.27) (layer B.SilkS) (width 0.1524)) (fp_line (start 3.81 -1.27) (end -3.81 -1.27) (layer B.SilkS) (width 0.1524)) (fp_line (start -1.27 1.27) (end -1.27 -1.27) (layer B.SilkS) (width 0.1524)) (pad 1 thru_hole rect (at -2.54 0) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 51 col1a) ) (pad 2 thru_hole circle (at 0 0) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 46 TX) ) (pad 3 thru_hole circle (at 2.54 0) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 46 TX) ) (model pin_array/pins_array_3x1.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (module PIN_ARRAY_3X1 (layer B.Cu) (tedit 554F4512) (tstamp 554F449E) (at 64.3 115.2) (descr "Connecteur 3 pins") (tags "CONN DEV") (path /554F46EE) (fp_text reference J_COL2 (at -6.7 0) (layer B.SilkS) (effects (font (size 1.016 1.016) (thickness 0.1524)) (justify mirror)) ) (fp_text value CONN_3 (at 0 2.159) (layer B.SilkS) hide (effects (font (size 1.016 1.016) (thickness 0.1524)) (justify mirror)) ) (fp_line (start -3.81 -1.27) (end -3.81 1.27) (layer B.SilkS) (width 0.1524)) (fp_line (start -3.81 1.27) (end 3.81 1.27) (layer B.SilkS) (width 0.1524)) (fp_line (start 3.81 1.27) (end 3.81 -1.27) (layer B.SilkS) (width 0.1524)) (fp_line (start 3.81 -1.27) (end -3.81 -1.27) (layer B.SilkS) (width 0.1524)) (fp_line (start -1.27 1.27) (end -1.27 -1.27) (layer B.SilkS) (width 0.1524)) (pad 1 thru_hole rect (at -2.54 0) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 53 col2a) ) (pad 2 thru_hole circle (at 0 0) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 44 RX) ) (pad 3 thru_hole circle (at 2.54 0) (size 1.524 1.524) (drill 1.016) (layers *.Cu *.Mask B.SilkS) (net 44 RX) ) (model pin_array/pins_array_3x1.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) ) (gr_line (start 288.5 64) (end 9.5 64) (angle 90) (layer Edge.Cuts) (width 0.1)) (gr_line (start 9.5 163) (end 288.5 163) (angle 90) (layer Edge.Cuts) (width 0.1)) (gr_line (start 9.5 64) (end 9.5 163) (angle 90) (layer Edge.Cuts) (width 0.1)) (gr_line (start 65.1002 115.2144) (end 65.9892 115.2144) (angle 90) (layer B.SilkS) (width 0.2)) (gr_line (start 65.1002 111.8108) (end 65.9892 111.8108) (angle 90) (layer B.SilkS) (width 0.2)) (gr_text "2 optional LEDs for \nStraight Eight only" (at 262.5598 118.4148 90) (layer B.SilkS) (effects (font (size 0.6 0.6) (thickness 0.1)) (justify mirror)) ) (gr_line (start 259.0038 121.7168) (end 258.953 121.7168) (angle 90) (layer B.SilkS) (width 0.2)) (gr_line (start 261.5946 114.4524) (end 261.5946 121.793) (angle 90) (layer B.SilkS) (width 0.2)) (gr_text "To enable serial port: mod RPi,\ncut traces 1-2 & jumper 2-3" (at 52.7304 112.9792) (layer B.SilkS) (effects (font (size 0.6 0.6) (thickness 0.1)) (justify mirror)) ) (gr_line (start 288.5 163) (end 288.5 64) (angle 90) (layer Edge.Cuts) (width 0.1)) (gr_text "PiDP-8/I\nFront Panel" (at 275 95 90) (layer B.SilkS) (effects (font (size 3 3) (thickness 0.6)) (justify left mirror)) ) (segment (start 234.85 128.78) (end 234.85 131.32) (width 0.381) (layer B.Cu) (net 1)) (segment (start 88.13 122.73) (end 89.3368 122.73) (width 0.381) (layer F.Cu) (net 1)) (segment (start 233.6431 127.5731) (end 234.85 128.78) (width 0.381) (layer F.Cu) (net 1)) (segment (start 204.418 127.5731) (end 233.6431 127.5731) (width 0.381) (layer F.Cu) (net 1)) (segment (start 201.1889 130.8022) (end 204.418 127.5731) (width 0.381) (layer F.Cu) (net 1)) (segment (start 137.7069 130.8022) (end 201.1889 130.8022) (width 0.381) (layer F.Cu) (net 1)) (segment (start 130.8107 123.906) (end 137.7069 130.8022) (width 0.381) (layer F.Cu) (net 1)) (segment (start 130.8107 122.4756) (end 130.8107 123.906) (width 0.381) (layer F.Cu) (net 1)) (segment (start 129.0368 120.7017) (end 130.8107 122.4756) (width 0.381) (layer F.Cu) (net 1)) (segment (start 91.3651 120.7017) (end 129.0368 120.7017) (width 0.381) (layer F.Cu) (net 1)) (segment (start 89.3368 122.73) (end 91.3651 120.7017) (width 0.381) (layer F.Cu) (net 1)) (segment (start 215.19 117) (end 222.81 117) (width 0.254) (layer F.Cu) (net 2)) (segment (start 216.7832 117) (end 215.19 117) (width 0.381) (layer B.Cu) (net 2)) (segment (start 228.5632 128.78) (end 216.7832 117) (width 0.381) (layer B.Cu) (net 2)) (segment (start 229.77 128.78) (end 228.5632 128.78) (width 0.381) (layer B.Cu) (net 2)) (segment (start 229.77 131.32) (end 229.77 129.9868) (width 0.381) (layer F.Cu) (net 2)) (segment (start 229.77 128.78) (end 229.77 129.9868) (width 0.381) (layer F.Cu) (net 2)) (segment (start 88.13 125.27) (end 85.59 125.27) (width 0.381) (layer B.Cu) (net 2)) (segment (start 76.13 134.73) (end 11.5 134.73) (width 0.381) (layer F.Cu) (net 2)) (segment (start 85.59 125.27) (end 76.13 134.73) (width 0.381) (layer F.Cu) (net 2)) (segment (start 86.9231 124.0631) (end 88.13 125.27) (width 0.381) (layer F.Cu) (net 2)) (segment (start 86.9231 121.744) (end 86.9231 124.0631) (width 0.381) (layer F.Cu) (net 2)) (segment (start 88.641 120.0261) (end 86.9231 121.744) (width 0.381) (layer F.Cu) (net 2)) (segment (start 137.9892 120.0261) (end 88.641 120.0261) (width 0.381) (layer F.Cu) (net 2)) (segment (start 138.4946 120.5315) (end 137.9892 120.0261) (width 0.381) (layer F.Cu) (net 2)) (segment (start 211.6585 120.5315) (end 138.4946 120.5315) (width 0.381) (layer F.Cu) (net 2)) (segment (start 215.19 117) (end 211.6585 120.5315) (width 0.381) (layer F.Cu) (net 2)) (segment (start 216.7001 92.2701) (end 215.24 90.81) (width 0.254) (layer B.Cu) (net 2)) (segment (start 222.81 117) (end 222.81 115.9202) (width 0.254) (layer B.Cu) (net 2)) (segment (start 222.81 115.9202) (end 216.7001 109.8103) (width 0.254) (layer B.Cu) (net 2)) (segment (start 216.7001 109.8103) (end 216.7001 92.2701) (width 0.254) (layer B.Cu) (net 2)) (segment (start 11.5 132.19) (end 12.7068 132.19) (width 0.381) (layer F.Cu) (net 3)) (segment (start 36.4101 98.6598) (end 36.4101 120.6624) (width 0.381) (layer F.Cu) (net 3)) (segment (start 51.1529 83.917) (end 36.4101 98.6598) (width 0.381) (layer F.Cu) (net 3)) (segment (start 101.9637 83.917) (end 51.1529 83.917) (width 0.381) (layer F.Cu) (net 3)) (segment (start 110.0418 91.9951) (end 101.9637 83.917) (width 0.381) (layer F.Cu) (net 3)) (segment (start 221.6749 91.9951) (end 110.0418 91.9951) (width 0.381) (layer F.Cu) (net 3)) (segment (start 222.86 90.81) (end 221.6749 91.9951) (width 0.381) (layer F.Cu) (net 3)) (segment (start 25.466 120.6624) (end 36.4101 120.6624) (width 0.381) (layer F.Cu) (net 3)) (segment (start 13.9384 132.19) (end 25.466 120.6624) (width 0.381) (layer F.Cu) (net 3)) (segment (start 12.7068 132.19) (end 13.9384 132.19) (width 0.381) (layer F.Cu) (net 3)) (segment (start 53.7769 126.4769) (end 52.57 125.27) (width 0.381) (layer F.Cu) (net 3)) (segment (start 64.0631 126.4769) (end 53.7769 126.4769) (width 0.381) (layer F.Cu) (net 3)) (segment (start 65.27 125.27) (end 64.0631 126.4769) (width 0.381) (layer F.Cu) (net 3)) (segment (start 37.8024 120.6624) (end 39.87 122.73) (width 0.381) (layer F.Cu) (net 3)) (segment (start 36.4101 120.6624) (end 37.8024 120.6624) (width 0.381) (layer F.Cu) (net 3)) (segment (start 51.3 124) (end 52.57 125.27) (width 0.381) (layer F.Cu) (net 3)) (segment (start 41.14 124) (end 51.3 124) (width 0.381) (layer F.Cu) (net 3)) (segment (start 39.87 122.73) (end 41.14 124) (width 0.381) (layer F.Cu) (net 3)) (segment (start 16.0929 135.3471) (end 14.94 136.5) (width 0.381) (layer B.Cu) (net 3)) (segment (start 16.0929 132.5232) (end 16.0929 135.3471) (width 0.381) (layer B.Cu) (net 3)) (segment (start 15.4053 131.8356) (end 16.0929 132.5232) (width 0.381) (layer B.Cu) (net 3)) (segment (start 13.0612 131.8356) (end 15.4053 131.8356) (width 0.381) (layer B.Cu) (net 3)) (segment (start 12.7068 132.19) (end 13.0612 131.8356) (width 0.381) (layer B.Cu) (net 3)) (segment (start 11.5 132.19) (end 12.7068 132.19) (width 0.381) (layer B.Cu) (net 3)) (segment (start 81.8243 126.4957) (end 83.05 125.27) (width 0.381) (layer B.Cu) (net 3)) (segment (start 80.0256 126.4957) (end 81.8243 126.4957) (width 0.381) (layer B.Cu) (net 3)) (segment (start 79.24 125.7101) (end 80.0256 126.4957) (width 0.381) (layer B.Cu) (net 3)) (segment (start 79.24 124) (end 77.97 122.73) (width 0.381) (layer B.Cu) (net 3)) (segment (start 79.24 125.7101) (end 79.24 124) (width 0.381) (layer B.Cu) (net 3)) (segment (start 66.4863 126.4863) (end 65.27 125.27) (width 0.381) (layer B.Cu) (net 3)) (segment (start 78.4638 126.4863) (end 66.4863 126.4863) (width 0.381) (layer B.Cu) (net 3)) (segment (start 79.24 125.7101) (end 78.4638 126.4863) (width 0.381) (layer B.Cu) (net 3)) (segment (start 237.39 131.32) (end 237.39 128.78) (width 0.381) (layer B.Cu) (net 3)) (segment (start 229.8356 97.7856) (end 222.86 90.81) (width 0.381) (layer B.Cu) (net 3)) (segment (start 229.8356 121.2256) (end 229.8356 97.7856) (width 0.381) (layer B.Cu) (net 3)) (segment (start 237.39 128.78) (end 229.8356 121.2256) (width 0.381) (layer B.Cu) (net 3)) (segment (start 14.94 133.83) (end 14.94 133) (width 0.254) (layer B.Cu) (net 4)) (segment (start 11.5 137.27) (end 14.94 133.83) (width 0.254) (layer B.Cu) (net 4)) (segment (start 21.4481 137.6119) (end 22.56 136.5) (width 0.254) (layer F.Cu) (net 4)) (segment (start 11.8419 137.6119) (end 21.4481 137.6119) (width 0.254) (layer F.Cu) (net 4)) (segment (start 11.5 137.27) (end 11.8419 137.6119) (width 0.254) (layer F.Cu) (net 4)) (segment (start 50.3 116.2723) (end 50.3 106.75) (width 0.254) (layer B.Cu) (net 5)) (segment (start 56.38 122.3523) (end 50.3 116.2723) (width 0.254) (layer B.Cu) (net 5)) (segment (start 56.38 124) (end 56.38 122.3523) (width 0.254) (layer B.Cu) (net 5)) (segment (start 57.65 125.27) (end 56.38 124) (width 0.254) (layer B.Cu) (net 5)) (segment (start 59.3736 105.6636) (end 60.46 106.75) (width 0.254) (layer B.Cu) (net 6)) (segment (start 54.9319 105.6636) (end 59.3736 105.6636) (width 0.254) (layer B.Cu) (net 6)) (segment (start 54.2629 106.3326) (end 54.9319 105.6636) (width 0.254) (layer B.Cu) (net 6)) (segment (start 54.2629 116.8029) (end 54.2629 106.3326) (width 0.254) (layer B.Cu) (net 6)) (segment (start 60.19 122.73) (end 54.2629 116.8029) (width 0.254) (layer B.Cu) (net 6)) (segment (start 52.618 133.08) (end 75.09 133.08) (width 0.254) (layer B.Cu) (net 7)) (segment (start 49 129.462) (end 52.618 133.08) (width 0.254) (layer B.Cu) (net 7)) (segment (start 49 128.4389) (end 49 129.462) (width 0.254) (layer B.Cu) (net 7)) (segment (start 45.8311 125.27) (end 49 128.4389) (width 0.254) (layer B.Cu) (net 7)) (segment (start 44.95 125.27) (end 45.8311 125.27) (width 0.254) (layer B.Cu) (net 7)) (segment (start 61.4039 105.1539) (end 63 106.75) (width 0.254) (layer B.Cu) (net 8)) (segment (start 50.3589 105.1539) (end 61.4039 105.1539) (width 0.254) (layer B.Cu) (net 8)) (segment (start 49.2201 106.2927) (end 50.3589 105.1539) (width 0.254) (layer B.Cu) (net 8)) (segment (start 49.2201 117.556) (end 49.2201 106.2927) (width 0.254) (layer B.Cu) (net 8)) (segment (start 53.7535 122.0894) (end 49.2201 117.556) (width 0.254) (layer B.Cu) (net 8)) (segment (start 53.7535 123.1633) (end 53.7535 122.0894) (width 0.254) (layer B.Cu) (net 8)) (segment (start 53.0434 123.8734) (end 53.7535 123.1633) (width 0.254) (layer B.Cu) (net 8)) (segment (start 51.4266 123.8734) (end 53.0434 123.8734) (width 0.254) (layer B.Cu) (net 8)) (segment (start 50.03 125.27) (end 51.4266 123.8734) (width 0.254) (layer B.Cu) (net 8)) (segment (start 52.84 116.099) (end 52.84 106.75) (width 0.254) (layer B.Cu) (net 9)) (segment (start 58.92 122.179) (end 52.84 116.099) (width 0.254) (layer B.Cu) (net 9)) (segment (start 58.92 124) (end 58.92 122.179) (width 0.254) (layer B.Cu) (net 9)) (segment (start 60.19 125.27) (end 58.92 124) (width 0.254) (layer B.Cu) (net 9)) (segment (start 211.8529 133.08) (end 214.79 133.08) (width 0.254) (layer F.Cu) (net 10)) (segment (start 210.5187 134.4142) (end 211.8529 133.08) (width 0.254) (layer F.Cu) (net 10)) (segment (start 206.2707 134.4142) (end 210.5187 134.4142) (width 0.254) (layer F.Cu) (net 10)) (segment (start 203.2306 131.3741) (end 206.2707 134.4142) (width 0.254) (layer F.Cu) (net 10)) (segment (start 100.8747 131.3741) (end 203.2306 131.3741) (width 0.254) (layer F.Cu) (net 10)) (segment (start 99 129.4994) (end 100.8747 131.3741) (width 0.254) (layer F.Cu) (net 10)) (segment (start 99 128.4743) (end 99 129.4994) (width 0.254) (layer F.Cu) (net 10)) (segment (start 97.757 127.2313) (end 99 128.4743) (width 0.254) (layer F.Cu) (net 10)) (segment (start 88.4342 127.2313) (end 97.757 127.2313) (width 0.254) (layer F.Cu) (net 10)) (segment (start 86.86 125.6571) (end 88.4342 127.2313) (width 0.254) (layer F.Cu) (net 10)) (segment (start 86.86 124.9006) (end 86.86 125.6571) (width 0.254) (layer F.Cu) (net 10)) (segment (start 86.0806 124.1212) (end 86.86 124.9006) (width 0.254) (layer F.Cu) (net 10)) (segment (start 76.5788 124.1212) (end 86.0806 124.1212) (width 0.254) (layer F.Cu) (net 10)) (segment (start 75.43 125.27) (end 76.5788 124.1212) (width 0.254) (layer F.Cu) (net 10)) (segment (start 42.556 148.7127) (end 42.556 136.5) (width 0.254) (layer F.Cu) (net 11)) (segment (start 39 152.2687) (end 42.556 148.7127) (width 0.254) (layer F.Cu) (net 11)) (segment (start 39 153.92) (end 39 152.2687) (width 0.254) (layer F.Cu) (net 11)) (segment (start 32.556 148.7127) (end 32.556 136.5) (width 0.254) (layer B.Cu) (net 12)) (segment (start 29 152.2687) (end 32.556 148.7127) (width 0.254) (layer B.Cu) (net 12)) (segment (start 29 153.92) (end 29 152.2687) (width 0.254) (layer B.Cu) (net 12)) (segment (start 52.556 148.7127) (end 52.556 136.5) (width 0.254) (layer B.Cu) (net 13)) (segment (start 49 152.2687) (end 52.556 148.7127) (width 0.254) (layer B.Cu) (net 13)) (segment (start 49 153.92) (end 49 152.2687) (width 0.254) (layer B.Cu) (net 13)) (segment (start 24.8265 127.2335) (end 22.56 129.5) (width 0.254) (layer F.Cu) (net 14)) (segment (start 67.4806 127.2335) (end 24.8265 127.2335) (width 0.254) (layer F.Cu) (net 14)) (segment (start 69.08 125.6341) (end 67.4806 127.2335) (width 0.254) (layer F.Cu) (net 14)) (segment (start 69.08 124.9232) (end 69.08 125.6341) (width 0.254) (layer F.Cu) (net 14)) (segment (start 69.8766 124.1266) (end 69.08 124.9232) (width 0.254) (layer F.Cu) (net 14)) (segment (start 74.0334 124.1266) (end 69.8766 124.1266) (width 0.254) (layer F.Cu) (net 14)) (segment (start 75.43 122.73) (end 74.0334 124.1266) (width 0.254) (layer F.Cu) (net 14)) (segment (start 47.5614 122.6586) (end 47.49 122.73) (width 0.254) (layer B.Cu) (net 15)) (segment (start 47.5614 113.2398) (end 47.5614 122.6586) (width 0.254) (layer B.Cu) (net 15)) (segment (start 41.5681 107.2465) (end 47.5614 113.2398) (width 0.254) (layer B.Cu) (net 15)) (segment (start 41.5681 106.2783) (end 41.5681 107.2465) (width 0.254) (layer B.Cu) (net 15)) (segment (start 43.2397 104.6067) (end 41.5681 106.2783) (width 0.254) (layer B.Cu) (net 15)) (segment (start 63.3967 104.6067) (end 43.2397 104.6067) (width 0.254) (layer B.Cu) (net 15)) (segment (start 65.54 106.75) (end 63.3967 104.6067) (width 0.254) (layer B.Cu) (net 15)) (segment (start 46.6389 105.6289) (end 47.76 106.75) (width 0.254) (layer B.Cu) (net 16)) (segment (start 44.7939 105.6289) (end 46.6389 105.6289) (width 0.254) (layer B.Cu) (net 16)) (segment (start 44.1005 106.3223) (end 44.7939 105.6289) (width 0.254) (layer B.Cu) (net 16)) (segment (start 44.1005 107.2817) (end 44.1005 106.3223) (width 0.254) (layer B.Cu) (net 16)) (segment (start 48.0697 111.2509) (end 44.1005 107.2817) (width 0.254) (layer B.Cu) (net 16)) (segment (start 48.0697 120.7697) (end 48.0697 111.2509) (width 0.254) (layer B.Cu) (net 16)) (segment (start 50.03 122.73) (end 48.0697 120.7697) (width 0.254) (layer B.Cu) (net 16)) (segment (start 48.5781 110.1081) (end 45.22 106.75) (width 0.254) (layer B.Cu) (net 17)) (segment (start 48.5781 118.7381) (end 48.5781 110.1081) (width 0.254) (layer B.Cu) (net 17)) (segment (start 52.57 122.73) (end 48.5781 118.7381) (width 0.254) (layer B.Cu) (net 17)) (segment (start 58.7011 110.0711) (end 55.38 106.75) (width 0.254) (layer B.Cu) (net 18)) (segment (start 58.7011 118.7011) (end 58.7011 110.0711) (width 0.254) (layer B.Cu) (net 18)) (segment (start 62.73 122.73) (end 58.7011 118.7011) (width 0.254) (layer B.Cu) (net 18)) (segment (start 59.4636 108.2936) (end 57.92 106.75) (width 0.254) (layer B.Cu) (net 19)) (segment (start 59.4636 116.9236) (end 59.4636 108.2936) (width 0.254) (layer B.Cu) (net 19)) (segment (start 65.27 122.73) (end 59.4636 116.9236) (width 0.254) (layer B.Cu) (net 19)) (segment (start 79.0762 121.2962) (end 80.51 122.73) (width 0.254) (layer F.Cu) (net 20)) (segment (start 49.6975 121.2962) (end 79.0762 121.2962) (width 0.254) (layer F.Cu) (net 20)) (segment (start 42.68 114.2787) (end 49.6975 121.2962) (width 0.254) (layer F.Cu) (net 20)) (segment (start 42.68 106.75) (end 42.68 114.2787) (width 0.254) (layer F.Cu) (net 20)) (segment (start 82.556 148.7127) (end 82.556 136.5) (width 0.254) (layer B.Cu) (net 21)) (segment (start 79 152.2687) (end 82.556 148.7127) (width 0.254) (layer B.Cu) (net 21)) (segment (start 79 153.92) (end 79 152.2687) (width 0.254) (layer B.Cu) (net 21)) (segment (start 72.556 148.7127) (end 72.556 136.5) (width 0.254) (layer B.Cu) (net 22)) (segment (start 69 152.2687) (end 72.556 148.7127) (width 0.254) (layer B.Cu) (net 22)) (segment (start 69 153.92) (end 69 152.2687) (width 0.254) (layer B.Cu) (net 22)) (segment (start 62.556 148.7127) (end 62.556 136.5) (width 0.254) (layer B.Cu) (net 23)) (segment (start 59 152.2687) (end 62.556 148.7127) (width 0.254) (layer B.Cu) (net 23)) (segment (start 59 153.92) (end 59 152.2687) (width 0.254) (layer B.Cu) (net 23)) (segment (start 282.556 148.7127) (end 282.556 136.5) (width 0.254) (layer F.Cu) (net 24)) (segment (start 279 152.2687) (end 282.556 148.7127) (width 0.254) (layer F.Cu) (net 24)) (segment (start 279 153.92) (end 279 152.2687) (width 0.254) (layer F.Cu) (net 24)) (segment (start 212.556 148.7127) (end 212.556 136.5) (width 0.254) (layer B.Cu) (net 25)) (segment (start 209 152.2687) (end 212.556 148.7127) (width 0.254) (layer B.Cu) (net 25)) (segment (start 209 153.92) (end 209 152.2687) (width 0.254) (layer B.Cu) (net 25)) (segment (start 222.556 148.7127) (end 222.556 136.5) (width 0.254) (layer B.Cu) (net 26)) (segment (start 219 152.2687) (end 222.556 148.7127) (width 0.254) (layer B.Cu) (net 26)) (segment (start 219 153.92) (end 219 152.2687) (width 0.254) (layer B.Cu) (net 26)) (segment (start 232.556 148.7127) (end 232.556 136.5) (width 0.254) (layer F.Cu) (net 27)) (segment (start 229 152.2687) (end 232.556 148.7127) (width 0.254) (layer F.Cu) (net 27)) (segment (start 229 153.92) (end 229 152.2687) (width 0.254) (layer F.Cu) (net 27)) (segment (start 242.556 148.7127) (end 242.556 136.5) (width 0.254) (layer B.Cu) (net 28)) (segment (start 239 152.2687) (end 242.556 148.7127) (width 0.254) (layer B.Cu) (net 28)) (segment (start 239 153.92) (end 239 152.2687) (width 0.254) (layer B.Cu) (net 28)) (segment (start 252.556 148.7127) (end 252.556 136.5) (width 0.254) (layer B.Cu) (net 29)) (segment (start 249 152.2687) (end 252.556 148.7127) (width 0.254) (layer B.Cu) (net 29)) (segment (start 249 153.92) (end 249 152.2687) (width 0.254) (layer B.Cu) (net 29)) (segment (start 262.556 148.7127) (end 262.556 136.5) (width 0.254) (layer B.Cu) (net 30)) (segment (start 259 152.2687) (end 262.556 148.7127) (width 0.254) (layer B.Cu) (net 30)) (segment (start 259 153.92) (end 259 152.2687) (width 0.254) (layer B.Cu) (net 30)) (segment (start 272.556 148.7127) (end 272.556 136.5) (width 0.254) (layer B.Cu) (net 31)) (segment (start 269 152.2687) (end 272.556 148.7127) (width 0.254) (layer B.Cu) (net 31)) (segment (start 269 153.92) (end 269 152.2687) (width 0.254) (layer B.Cu) (net 31)) (segment (start 92.556 148.7127) (end 92.556 136.5) (width 0.254) (layer B.Cu) (net 32)) (segment (start 89 152.2687) (end 92.556 148.7127) (width 0.254) (layer B.Cu) (net 32)) (segment (start 89 153.92) (end 89 152.2687) (width 0.254) (layer B.Cu) (net 32)) (segment (start 182.556 148.7127) (end 182.556 136.5) (width 0.254) (layer B.Cu) (net 33)) (segment (start 179 152.2687) (end 182.556 148.7127) (width 0.254) (layer B.Cu) (net 33)) (segment (start 179 153.92) (end 179 152.2687) (width 0.254) (layer B.Cu) (net 33)) (segment (start 102.556 148.7127) (end 102.556 136.5) (width 0.254) (layer B.Cu) (net 34)) (segment (start 99 152.2687) (end 102.556 148.7127) (width 0.254) (layer B.Cu) (net 34)) (segment (start 99 153.92) (end 99 152.2687) (width 0.254) (layer B.Cu) (net 34)) (segment (start 112.556 148.7127) (end 112.556 136.5) (width 0.254) (layer B.Cu) (net 35)) (segment (start 109 152.2687) (end 112.556 148.7127) (width 0.254) (layer B.Cu) (net 35)) (segment (start 109 153.92) (end 109 152.2687) (width 0.254) (layer B.Cu) (net 35)) (segment (start 122.556 148.7127) (end 122.556 136.5) (width 0.254) (layer B.Cu) (net 36)) (segment (start 119 152.2687) (end 122.556 148.7127) (width 0.254) (layer B.Cu) (net 36)) (segment (start 119 153.92) (end 119 152.2687) (width 0.254) (layer B.Cu) (net 36)) (segment (start 129 153.92) (end 129 152.2687) (width 0.254) (layer B.Cu) (net 37)) (segment (start 132.556 136.5) (end 132.556 137.5798) (width 0.254) (layer B.Cu) (net 37)) (segment (start 132.556 148.7127) (end 132.556 137.5798) (width 0.254) (layer B.Cu) (net 37)) (segment (start 129 152.2687) (end 132.556 148.7127) (width 0.254) (layer B.Cu) (net 37)) (segment (start 142.556 148.7127) (end 142.556 136.5) (width 0.254) (layer F.Cu) (net 38)) (segment (start 139 152.2687) (end 142.556 148.7127) (width 0.254) (layer F.Cu) (net 38)) (segment (start 139 153.92) (end 139 152.2687) (width 0.254) (layer F.Cu) (net 38)) (segment (start 152.556 148.7127) (end 152.556 136.5) (width 0.254) (layer B.Cu) (net 39)) (segment (start 149 152.2687) (end 152.556 148.7127) (width 0.254) (layer B.Cu) (net 39)) (segment (start 149 153.92) (end 149 152.2687) (width 0.254) (layer B.Cu) (net 39)) (segment (start 162.556 148.7127) (end 162.556 136.5) (width 0.254) (layer F.Cu) (net 40)) (segment (start 159 152.2687) (end 162.556 148.7127) (width 0.254) (layer F.Cu) (net 40)) (segment (start 159 153.92) (end 159 152.2687) (width 0.254) (layer F.Cu) (net 40)) (segment (start 172.556 148.7127) (end 172.556 136.5) (width 0.254) (layer F.Cu) (net 41)) (segment (start 169 152.2687) (end 172.556 148.7127) (width 0.254) (layer F.Cu) (net 41)) (segment (start 169 153.92) (end 169 152.2687) (width 0.254) (layer F.Cu) (net 41)) (segment (start 192.556 148.7127) (end 192.556 136.5) (width 0.254) (layer B.Cu) (net 42)) (segment (start 189 152.2687) (end 192.556 148.7127) (width 0.254) (layer B.Cu) (net 42)) (segment (start 189 153.92) (end 189 152.2687) (width 0.254) (layer B.Cu) (net 42)) (segment (start 202.556 148.7127) (end 202.556 136.5) (width 0.254) (layer B.Cu) (net 43)) (segment (start 199 152.2687) (end 202.556 148.7127) (width 0.254) (layer B.Cu) (net 43)) (segment (start 199 153.92) (end 199 152.2687) (width 0.254) (layer B.Cu) (net 43)) (segment (start 64.3 115.2) (end 66.84 115.2) (width 0.254) (layer F.Cu) (net 44)) (segment (start 42.7916 104.0984) (end 40.14 106.75) (width 0.254) (layer B.Cu) (net 44)) (segment (start 64.4354 104.0984) (end 42.7916 104.0984) (width 0.254) (layer B.Cu) (net 44)) (segment (start 66.62 106.283) (end 64.4354 104.0984) (width 0.254) (layer B.Cu) (net 44)) (segment (start 66.62 107.2192) (end 66.62 106.283) (width 0.254) (layer B.Cu) (net 44)) (segment (start 65.0924 108.7468) (end 66.62 107.2192) (width 0.254) (layer B.Cu) (net 44)) (segment (start 62.6625 108.7468) (end 65.0924 108.7468) (width 0.254) (layer B.Cu) (net 44)) (segment (start 60.6166 110.7927) (end 62.6625 108.7468) (width 0.254) (layer B.Cu) (net 44)) (segment (start 60.6166 112.7519) (end 60.6166 110.7927) (width 0.254) (layer B.Cu) (net 44)) (segment (start 61.9213 114.0566) (end 60.6166 112.7519) (width 0.254) (layer B.Cu) (net 44)) (segment (start 63.1566 114.0566) (end 61.9213 114.0566) (width 0.254) (layer B.Cu) (net 44)) (segment (start 64.3 115.2) (end 63.1566 114.0566) (width 0.254) (layer B.Cu) (net 44)) (segment (start 70.24 133) (end 22.56 133) (width 0.254) (layer F.Cu) (net 44)) (segment (start 77.97 125.27) (end 70.24 133) (width 0.254) (layer F.Cu) (net 44)) (segment (start 76.7 124) (end 77.97 125.27) (width 0.254) (layer B.Cu) (net 44)) (segment (start 66.84 115.2) (end 67.1787 114.8613) (width 0.254) (layer B.Cu) (net 44)) (segment (start 67.1787 114.8613) (end 73.2959 114.8613) (width 0.254) (layer B.Cu) (net 44)) (segment (start 73.2959 114.8613) (end 76.7 118.2654) (width 0.254) (layer B.Cu) (net 44)) (segment (start 76.7 118.2654) (end 76.7 124) (width 0.254) (layer B.Cu) (net 44)) (via (at 162.2826 127.0012) (size 0.889) (layers F.Cu B.Cu) (net 45)) (segment (start 247.55 128.78) (end 247.55 131.32) (width 0.254) (layer F.Cu) (net 45)) (segment (start 245.7712 127.0012) (end 162.2826 127.0012) (width 0.254) (layer F.Cu) (net 45)) (segment (start 247.55 128.78) (end 245.7712 127.0012) (width 0.254) (layer F.Cu) (net 45)) (segment (start 161.9792 126.6978) (end 162.2826 127.0012) (width 0.254) (layer B.Cu) (net 45)) (segment (start 98.254 126.6978) (end 161.9792 126.6978) (width 0.254) (layer B.Cu) (net 45)) (segment (start 92.6456 132.3062) (end 98.254 126.6978) (width 0.254) (layer B.Cu) (net 45)) (segment (start 85.7128 132.3062) (end 92.6456 132.3062) (width 0.254) (layer B.Cu) (net 45)) (segment (start 84.8598 131.4532) (end 85.7128 132.3062) (width 0.254) (layer B.Cu) (net 45)) (segment (start 72.1583 131.4532) (end 84.8598 131.4532) (width 0.254) (layer B.Cu) (net 45)) (segment (start 71.867 131.7445) (end 72.1583 131.4532) (width 0.254) (layer B.Cu) (net 45)) (segment (start 54.8876 131.7445) (end 71.867 131.7445) (width 0.254) (layer B.Cu) (net 45)) (segment (start 48.76 125.6169) (end 54.8876 131.7445) (width 0.254) (layer B.Cu) (net 45)) (segment (start 48.76 124.9205) (end 48.76 125.6169) (width 0.254) (layer B.Cu) (net 45)) (segment (start 47.9661 124.1266) (end 48.76 124.9205) (width 0.254) (layer B.Cu) (net 45)) (segment (start 46.3466 124.1266) (end 47.9661 124.1266) (width 0.254) (layer B.Cu) (net 45)) (segment (start 44.95 122.73) (end 46.3466 124.1266) (width 0.254) (layer B.Cu) (net 45)) (segment (start 64.3 111.8) (end 66.84 111.8) (width 0.254) (layer F.Cu) (net 46)) (segment (start 39.2496 105.1004) (end 37.6 106.75) (width 0.254) (layer F.Cu) (net 46)) (segment (start 50.2323 105.1004) (end 39.2496 105.1004) (width 0.254) (layer F.Cu) (net 46)) (segment (start 51.57 106.4381) (end 50.2323 105.1004) (width 0.254) (layer F.Cu) (net 46)) (segment (start 51.57 107.0356) (end 51.57 106.4381) (width 0.254) (layer F.Cu) (net 46)) (segment (start 55.1911 110.6567) (end 51.57 107.0356) (width 0.254) (layer F.Cu) (net 46)) (segment (start 63.1567 110.6567) (end 55.1911 110.6567) (width 0.254) (layer F.Cu) (net 46)) (segment (start 64.3 111.8) (end 63.1567 110.6567) (width 0.254) (layer F.Cu) (net 46)) (segment (start 10.3482 138.6582) (end 11.5 139.81) (width 0.254) (layer F.Cu) (net 46)) (segment (start 10.3482 134.2582) (end 10.3482 138.6582) (width 0.254) (layer F.Cu) (net 46)) (segment (start 11.0826 133.5238) (end 10.3482 134.2582) (width 0.254) (layer F.Cu) (net 46)) (segment (start 12.991 133.5238) (end 11.0826 133.5238) (width 0.254) (layer F.Cu) (net 46)) (segment (start 13.5623 134.0951) (end 12.991 133.5238) (width 0.254) (layer F.Cu) (net 46)) (segment (start 71.6849 134.0951) (end 13.5623 134.0951) (width 0.254) (layer F.Cu) (net 46)) (segment (start 80.51 125.27) (end 71.6849 134.0951) (width 0.254) (layer F.Cu) (net 46)) (segment (start 81.7006 124.0794) (end 80.51 125.27) (width 0.254) (layer B.Cu) (net 46)) (segment (start 66.84 111.8) (end 71.2498 111.8) (width 0.254) (layer B.Cu) (net 46)) (segment (start 71.2498 111.8) (end 81.7006 122.2508) (width 0.254) (layer B.Cu) (net 46)) (segment (start 81.7006 122.2508) (end 81.7006 124.0794) (width 0.254) (layer B.Cu) (net 46)) (segment (start 89.7475 114.9225) (end 90.27 114.4) (width 0.254) (layer B.Cu) (net 47)) (segment (start 89.7475 128.4775) (end 89.7475 114.9225) (width 0.254) (layer B.Cu) (net 47)) (segment (start 90.27 129) (end 89.7475 128.4775) (width 0.254) (layer B.Cu) (net 47)) (segment (start 30.27 91.8) (end 37.6 99.13) (width 0.254) (layer B.Cu) (net 47)) (segment (start 30.27 70.6) (end 30.27 91.8) (width 0.254) (layer B.Cu) (net 47)) (segment (start 25.19 111.54) (end 25.19 136.5) (width 0.254) (layer B.Cu) (net 47)) (segment (start 37.6 99.13) (end 25.19 111.54) (width 0.254) (layer B.Cu) (net 47)) (segment (start 90.27 114.4) (end 90.27 99.8) (width 0.254) (layer B.Cu) (net 47)) (segment (start 89.7645 71.1055) (end 90.27 70.6) (width 0.254) (layer B.Cu) (net 47)) (segment (start 89.7645 84.6945) (end 89.7645 71.1055) (width 0.254) (layer B.Cu) (net 47)) (segment (start 90.27 85.2) (end 89.7645 84.6945) (width 0.254) (layer B.Cu) (net 47)) (segment (start 250.09 131.32) (end 250.09 128.78) (width 0.254) (layer B.Cu) (net 47)) (segment (start 240.27 76.6805) (end 240.27 70.6) (width 0.254) (layer B.Cu) (net 47)) (segment (start 240.7751 76.6805) (end 240.27 76.6805) (width 0.254) (layer B.Cu) (net 47)) (segment (start 245.0476 80.953) (end 240.7751 76.6805) (width 0.254) (layer B.Cu) (net 47)) (segment (start 245.0476 88.8697) (end 245.0476 80.953) (width 0.254) (layer B.Cu) (net 47)) (segment (start 257.2282 101.0503) (end 245.0476 88.8697) (width 0.254) (layer B.Cu) (net 47)) (segment (start 259.0197 101.0503) (end 257.2282 101.0503) (width 0.254) (layer B.Cu) (net 47)) (segment (start 260.27 99.8) (end 259.0197 101.0503) (width 0.254) (layer B.Cu) (net 47)) (segment (start 250.09 98.6192) (end 250.09 128.78) (width 0.254) (layer B.Cu) (net 47)) (segment (start 242.4985 91.0277) (end 250.09 98.6192) (width 0.254) (layer B.Cu) (net 47)) (segment (start 242.4985 84.1909) (end 242.4985 91.0277) (width 0.254) (layer B.Cu) (net 47)) (segment (start 239.0505 80.7429) (end 242.4985 84.1909) (width 0.254) (layer B.Cu) (net 47)) (segment (start 239.0505 77.395) (end 239.0505 80.7429) (width 0.254) (layer B.Cu) (net 47)) (segment (start 239.765 76.6805) (end 239.0505 77.395) (width 0.254) (layer B.Cu) (net 47)) (segment (start 240.27 76.6805) (end 239.765 76.6805) (width 0.254) (layer B.Cu) (net 47)) (segment (start 38.724 98.006) (end 37.6 99.13) (width 0.254) (layer F.Cu) (net 47)) (segment (start 90.27 98.006) (end 38.724 98.006) (width 0.254) (layer F.Cu) (net 47)) (segment (start 90.27 99.8) (end 90.27 98.006) (width 0.254) (layer F.Cu) (net 47)) (segment (start 90.27 98.006) (end 90.27 85.2) (width 0.254) (layer F.Cu) (net 47)) (segment (start 246.9958 134.4142) (end 250.09 131.32) (width 0.254) (layer F.Cu) (net 47)) (segment (start 211.5968 134.4142) (end 246.9958 134.4142) (width 0.254) (layer F.Cu) (net 47)) (segment (start 209.511 136.5) (end 211.5968 134.4142) (width 0.254) (layer F.Cu) (net 47)) (segment (start 205.19 136.5) (end 209.511 136.5) (width 0.254) (layer F.Cu) (net 47)) (segment (start 90.27 131.9828) (end 90.27 129) (width 0.254) (layer F.Cu) (net 47)) (segment (start 200.6728 131.9828) (end 90.27 131.9828) (width 0.254) (layer F.Cu) (net 47)) (segment (start 205.19 136.5) (end 200.6728 131.9828) (width 0.254) (layer F.Cu) (net 47)) (segment (start 89.7072 131.9828) (end 85.19 136.5) (width 0.254) (layer F.Cu) (net 47)) (segment (start 90.27 131.9828) (end 89.7072 131.9828) (width 0.254) (layer F.Cu) (net 47)) (segment (start 180.27 70.6) (end 180.27 85.2) (width 0.254) (layer B.Cu) (net 48)) (segment (start 180.27 99.8) (end 180.27 114.4) (width 0.254) (layer F.Cu) (net 48)) (segment (start 180.27 114.4) (end 180.27 129) (width 0.254) (layer B.Cu) (net 48)) (segment (start 180.27 131.42) (end 175.19 136.5) (width 0.254) (layer B.Cu) (net 48)) (segment (start 180.27 129) (end 180.27 131.42) (width 0.254) (layer B.Cu) (net 48)) (segment (start 272.95 131.32) (end 272.95 128.78) (width 0.254) (layer B.Cu) (net 48)) (segment (start 180.27 85.2) (end 180.27 99.8) (width 0.254) (layer B.Cu) (net 48)) (segment (start 62.0927 100.7627) (end 60.46 99.13) (width 0.254) (layer B.Cu) (net 48)) (segment (start 68.4168 100.7627) (end 62.0927 100.7627) (width 0.254) (layer B.Cu) (net 48)) (segment (start 86.7466 119.0925) (end 68.4168 100.7627) (width 0.254) (layer B.Cu) (net 48)) (segment (start 86.7466 123.2801) (end 86.7466 119.0925) (width 0.254) (layer B.Cu) (net 48)) (segment (start 86.0267 124) (end 86.7466 123.2801) (width 0.254) (layer B.Cu) (net 48)) (segment (start 85.2432 124) (end 86.0267 124) (width 0.254) (layer B.Cu) (net 48)) (segment (start 84.4466 124.7966) (end 85.2432 124) (width 0.254) (layer B.Cu) (net 48)) (segment (start 84.4466 129) (end 84.4466 124.7966) (width 0.254) (layer B.Cu) (net 48)) (segment (start 84.4466 129) (end 70.27 129) (width 0.254) (layer B.Cu) (net 48)) (segment (start 86.0054 129) (end 84.4466 129) (width 0.254) (layer B.Cu) (net 48)) (segment (start 87.2621 130.2567) (end 86.0054 129) (width 0.254) (layer B.Cu) (net 48)) (segment (start 91.3517 130.2567) (end 87.2621 130.2567) (width 0.254) (layer B.Cu) (net 48)) (segment (start 97.9385 123.6699) (end 91.3517 130.2567) (width 0.254) (layer B.Cu) (net 48)) (segment (start 162.1397 123.6699) (end 97.9385 123.6699) (width 0.254) (layer B.Cu) (net 48)) (segment (start 169.0327 116.7769) (end 162.1397 123.6699) (width 0.254) (layer B.Cu) (net 48)) (segment (start 169.0327 116.7521) (end 169.0327 116.7769) (width 0.254) (layer B.Cu) (net 48)) (segment (start 170.1121 115.6727) (end 169.0327 116.7521) (width 0.254) (layer B.Cu) (net 48)) (segment (start 170.77 115.6727) (end 170.1121 115.6727) (width 0.254) (layer B.Cu) (net 48)) (segment (start 180.27 106.1727) (end 170.77 115.6727) (width 0.254) (layer B.Cu) (net 48)) (segment (start 180.27 99.8) (end 180.27 106.1727) (width 0.254) (layer B.Cu) (net 48)) (segment (start 259 76.63) (end 260.27 77.9) (width 0.254) (layer F.Cu) (net 48)) (segment (start 259 70.049) (end 259 76.63) (width 0.254) (layer F.Cu) (net 48)) (segment (start 258.3066 69.3556) (end 259 70.049) (width 0.254) (layer F.Cu) (net 48)) (segment (start 214.99 69.3556) (end 258.3066 69.3556) (width 0.254) (layer F.Cu) (net 48)) (segment (start 211.9706 72.375) (end 214.99 69.3556) (width 0.254) (layer F.Cu) (net 48)) (segment (start 182.045 72.375) (end 211.9706 72.375) (width 0.254) (layer F.Cu) (net 48)) (segment (start 180.27 70.6) (end 182.045 72.375) (width 0.254) (layer F.Cu) (net 48)) (segment (start 272.95 109.9576) (end 272.95 128.78) (width 0.254) (layer B.Cu) (net 48)) (segment (start 256.4706 93.4782) (end 272.95 109.9576) (width 0.254) (layer B.Cu) (net 48)) (segment (start 256.4706 81.6994) (end 256.4706 93.4782) (width 0.254) (layer B.Cu) (net 48)) (segment (start 260.27 77.9) (end 256.4706 81.6994) (width 0.254) (layer B.Cu) (net 48)) (segment (start 190.27 114.4) (end 190.27 129) (width 0.254) (layer B.Cu) (net 49)) (segment (start 190.27 131.42) (end 185.19 136.5) (width 0.254) (layer B.Cu) (net 49)) (segment (start 190.27 129) (end 190.27 131.42) (width 0.254) (layer B.Cu) (net 49)) (segment (start 64.0912 100.2212) (end 63 99.13) (width 0.254) (layer B.Cu) (net 49)) (segment (start 65.9879 100.2212) (end 64.0912 100.2212) (width 0.254) (layer B.Cu) (net 49)) (segment (start 68.3427 97.8664) (end 65.9879 100.2212) (width 0.254) (layer B.Cu) (net 49)) (segment (start 68.3427 88.2627) (end 68.3427 97.8664) (width 0.254) (layer B.Cu) (net 49)) (segment (start 87.7805 68.8249) (end 68.3427 88.2627) (width 0.254) (layer B.Cu) (net 49)) (segment (start 188.4949 68.8249) (end 87.7805 68.8249) (width 0.254) (layer B.Cu) (net 49)) (segment (start 190.27 70.6) (end 188.4949 68.8249) (width 0.254) (layer B.Cu) (net 49)) (segment (start 190.27 99.8) (end 190.27 114.4) (width 0.254) (layer F.Cu) (net 49)) (segment (start 190.27 70.6) (end 190.27 85.2) (width 0.254) (layer B.Cu) (net 49)) (segment (start 190.27 85.2) (end 190.27 99.8) (width 0.254) (layer B.Cu) (net 49)) (segment (start 192.5263 87.4563) (end 190.27 85.2) (width 0.254) (layer F.Cu) (net 49)) (segment (start 244.0222 87.4563) (end 192.5263 87.4563) (width 0.254) (layer F.Cu) (net 49)) (segment (start 250.2897 93.7238) (end 244.0222 87.4563) (width 0.254) (layer F.Cu) (net 49)) (segment (start 260.773 93.7238) (end 250.2897 93.7238) (width 0.254) (layer F.Cu) (net 49)) (segment (start 261.5335 92.9633) (end 260.773 93.7238) (width 0.254) (layer F.Cu) (net 49)) (segment (start 261.5335 86.4635) (end 261.5335 92.9633) (width 0.254) (layer F.Cu) (net 49)) (segment (start 260.27 85.2) (end 261.5335 86.4635) (width 0.254) (layer F.Cu) (net 49)) (segment (start 275.49 131.32) (end 275.49 128.78) (width 0.254) (layer B.Cu) (net 49)) (segment (start 259 86.47) (end 260.27 85.2) (width 0.254) (layer B.Cu) (net 49)) (segment (start 259 93.1606) (end 259 86.47) (width 0.254) (layer B.Cu) (net 49)) (segment (start 275.49 109.6506) (end 259 93.1606) (width 0.254) (layer B.Cu) (net 49)) (segment (start 275.49 128.78) (end 275.49 109.6506) (width 0.254) (layer B.Cu) (net 49)) (via (at 203.034 110.2619) (size 0.889) (layers F.Cu B.Cu) (net 50)) (segment (start 199.029 130.241) (end 200.27 129) (width 0.254) (layer B.Cu) (net 50)) (segment (start 197.0417 130.241) (end 199.029 130.241) (width 0.254) (layer B.Cu) (net 50)) (segment (start 196.5005 129.6998) (end 197.0417 130.241) (width 0.254) (layer B.Cu) (net 50)) (segment (start 196.5005 118.1695) (end 196.5005 129.6998) (width 0.254) (layer B.Cu) (net 50)) (segment (start 200.27 114.4) (end 196.5005 118.1695) (width 0.254) (layer B.Cu) (net 50)) (segment (start 197.0417 134.6483) (end 195.19 136.5) (width 0.254) (layer B.Cu) (net 50)) (segment (start 197.0417 130.241) (end 197.0417 134.6483) (width 0.254) (layer B.Cu) (net 50)) (segment (start 202.0039 86.9339) (end 200.27 85.2) (width 0.254) (layer F.Cu) (net 50)) (segment (start 254.7039 86.9339) (end 202.0039 86.9339) (width 0.254) (layer F.Cu) (net 50)) (segment (start 260.27 92.5) (end 254.7039 86.9339) (width 0.254) (layer F.Cu) (net 50)) (segment (start 278.03 131.32) (end 278.03 128.78) (width 0.254) (layer B.Cu) (net 50)) (segment (start 278.03 110.26) (end 260.27 92.5) (width 0.254) (layer B.Cu) (net 50)) (segment (start 278.03 128.78) (end 278.03 110.26) (width 0.254) (layer B.Cu) (net 50)) (segment (start 193.8351 71.8196) (end 199.4465 71.8196) (width 0.254) (layer B.Cu) (net 50)) (segment (start 190.332 68.3165) (end 193.8351 71.8196) (width 0.254) (layer B.Cu) (net 50)) (segment (start 87.5205 68.3165) (end 190.332 68.3165) (width 0.254) (layer B.Cu) (net 50)) (segment (start 65.54 90.297) (end 87.5205 68.3165) (width 0.254) (layer B.Cu) (net 50)) (segment (start 65.54 99.13) (end 65.54 90.297) (width 0.254) (layer B.Cu) (net 50)) (segment (start 200.27 70.9961) (end 200.27 70.6) (width 0.254) (layer B.Cu) (net 50)) (segment (start 199.4465 71.8196) (end 200.27 70.9961) (width 0.254) (layer B.Cu) (net 50)) (segment (start 199.4465 71.8196) (end 199.4465 83.9286) (width 0.254) (layer B.Cu) (net 50)) (segment (start 199.4465 84.3765) (end 200.27 85.2) (width 0.254) (layer B.Cu) (net 50)) (segment (start 199.4465 83.9286) (end 199.4465 84.3765) (width 0.254) (layer B.Cu) (net 50)) (segment (start 196.5105 96.0405) (end 200.27 99.8) (width 0.254) (layer B.Cu) (net 50)) (segment (start 196.5105 84.6626) (end 196.5105 96.0405) (width 0.254) (layer B.Cu) (net 50)) (segment (start 197.2445 83.9286) (end 196.5105 84.6626) (width 0.254) (layer B.Cu) (net 50)) (segment (start 199.4465 83.9286) (end 197.2445 83.9286) (width 0.254) (layer B.Cu) (net 50)) (segment (start 200.27 107.4979) (end 203.034 110.2619) (width 0.254) (layer B.Cu) (net 50)) (segment (start 200.27 99.8) (end 200.27 107.4979) (width 0.254) (layer B.Cu) (net 50)) (segment (start 200.27 113.0259) (end 203.034 110.2619) (width 0.254) (layer F.Cu) (net 50)) (segment (start 200.27 114.4) (end 200.27 113.0259) (width 0.254) (layer F.Cu) (net 50)) (segment (start 61.76 111.8) (end 62.9033 111.8) (width 0.254) (layer B.Cu) (net 51)) (segment (start 62.9033 111.5142) (end 62.9033 111.8) (width 0.254) (layer B.Cu) (net 51)) (segment (start 63.7609 110.6566) (end 62.9033 111.5142) (width 0.254) (layer B.Cu) (net 51)) (segment (start 71.4668 110.6566) (end 63.7609 110.6566) (width 0.254) (layer B.Cu) (net 51)) (segment (start 81.1814 120.3712) (end 71.4668 110.6566) (width 0.254) (layer B.Cu) (net 51)) (segment (start 83.2312 120.3712) (end 81.1814 120.3712) (width 0.254) (layer B.Cu) (net 51)) (segment (start 85.59 122.73) (end 83.2312 120.3712) (width 0.254) (layer B.Cu) (net 51)) (via (at 100.27 122.844) (size 0.889) (layers F.Cu B.Cu) (net 52)) (segment (start 100.27 85.2) (end 100.27 70.6) (width 0.254) (layer B.Cu) (net 52)) (segment (start 100.27 131.42) (end 95.19 136.5) (width 0.254) (layer B.Cu) (net 52)) (segment (start 100.27 129) (end 100.27 131.42) (width 0.254) (layer B.Cu) (net 52)) (segment (start 252.63 131.32) (end 252.63 128.78) (width 0.254) (layer B.Cu) (net 52)) (segment (start 100.27 99.8) (end 100.27 85.2) (width 0.254) (layer F.Cu) (net 52)) (segment (start 41.5103 71.8403) (end 40.27 70.6) (width 0.254) (layer F.Cu) (net 52)) (segment (start 62.954 71.8403) (end 41.5103 71.8403) (width 0.254) (layer F.Cu) (net 52)) (segment (start 65.4471 69.3472) (end 62.954 71.8403) (width 0.254) (layer F.Cu) (net 52)) (segment (start 99.0172 69.3472) (end 65.4471 69.3472) (width 0.254) (layer F.Cu) (net 52)) (segment (start 100.27 70.6) (end 99.0172 69.3472) (width 0.254) (layer F.Cu) (net 52)) (segment (start 100.27 114.4) (end 100.27 99.8) (width 0.254) (layer B.Cu) (net 52)) (segment (start 100.27 122.844) (end 100.27 114.4) (width 0.254) (layer B.Cu) (net 52)) (segment (start 100.27 129) (end 100.27 122.844) (width 0.254) (layer F.Cu) (net 52)) (segment (start 40.27 99) (end 40.14 99.13) (width 0.254) (layer B.Cu) (net 52)) (segment (start 40.27 70.6) (end 40.27 99) (width 0.254) (layer B.Cu) (net 52)) (segment (start 30.814 132.124) (end 35.19 136.5) (width 0.254) (layer B.Cu) (net 52)) (segment (start 29.1142 132.124) (end 30.814 132.124) (width 0.254) (layer B.Cu) (net 52)) (segment (start 26.4733 129.4831) (end 29.1142 132.124) (width 0.254) (layer B.Cu) (net 52)) (segment (start 26.4733 112.7967) (end 26.4733 129.4831) (width 0.254) (layer B.Cu) (net 52)) (segment (start 40.14 99.13) (end 26.4733 112.7967) (width 0.254) (layer B.Cu) (net 52)) (segment (start 244.5392 82.1692) (end 240.27 77.9) (width 0.254) (layer B.Cu) (net 52)) (segment (start 244.5392 89.0801) (end 244.5392 82.1692) (width 0.254) (layer B.Cu) (net 52)) (segment (start 257.2572 101.7981) (end 244.5392 89.0801) (width 0.254) (layer B.Cu) (net 52)) (segment (start 257.2572 105.8449) (end 257.2572 101.7981) (width 0.254) (layer B.Cu) (net 52)) (segment (start 252.63 110.4721) (end 257.2572 105.8449) (width 0.254) (layer B.Cu) (net 52)) (segment (start 252.63 128.78) (end 252.63 110.4721) (width 0.254) (layer B.Cu) (net 52)) (segment (start 259.0149 105.8449) (end 260.27 107.1) (width 0.254) (layer B.Cu) (net 52)) (segment (start 257.2572 105.8449) (end 259.0149 105.8449) (width 0.254) (layer B.Cu) (net 52)) (segment (start 216.5134 135.1766) (end 215.19 136.5) (width 0.254) (layer F.Cu) (net 52)) (segment (start 248.7734 135.1766) (end 216.5134 135.1766) (width 0.254) (layer F.Cu) (net 52)) (segment (start 252.63 131.32) (end 248.7734 135.1766) (width 0.254) (layer F.Cu) (net 52)) (segment (start 97.3006 134.3894) (end 95.19 136.5) (width 0.254) (layer F.Cu) (net 52)) (segment (start 195.3253 134.3894) (end 97.3006 134.3894) (width 0.254) (layer F.Cu) (net 52)) (segment (start 198.5324 137.5965) (end 195.3253 134.3894) (width 0.254) (layer F.Cu) (net 52)) (segment (start 214.0935 137.5965) (end 198.5324 137.5965) (width 0.254) (layer F.Cu) (net 52)) (segment (start 215.19 136.5) (end 214.0935 137.5965) (width 0.254) (layer F.Cu) (net 52)) (segment (start 80.9148 120.5948) (end 83.05 122.73) (width 0.254) (layer F.Cu) (net 53)) (segment (start 68.0123 120.5948) (end 80.9148 120.5948) (width 0.254) (layer F.Cu) (net 53)) (segment (start 62.9033 115.4858) (end 68.0123 120.5948) (width 0.254) (layer F.Cu) (net 53)) (segment (start 62.9033 115.2) (end 62.9033 115.4858) (width 0.254) (layer F.Cu) (net 53)) (segment (start 61.76 115.2) (end 62.9033 115.2) (width 0.254) (layer F.Cu) (net 53)) (via (at 110.27 122.844) (size 0.889) (layers F.Cu B.Cu) (net 54)) (segment (start 110.27 131.42) (end 105.19 136.5) (width 0.254) (layer B.Cu) (net 54)) (segment (start 110.27 129) (end 110.27 131.42) (width 0.254) (layer B.Cu) (net 54)) (segment (start 110.27 70.6) (end 110.27 85.2) (width 0.254) (layer B.Cu) (net 54)) (segment (start 277.9404 72.9296) (end 280.27 70.6) (width 0.254) (layer F.Cu) (net 54)) (segment (start 270.8089 72.9296) (end 277.9404 72.9296) (width 0.254) (layer F.Cu) (net 54)) (segment (start 259 84.7385) (end 270.8089 72.9296) (width 0.254) (layer F.Cu) (net 54)) (segment (start 259 85.6562) (end 259 84.7385) (width 0.254) (layer F.Cu) (net 54)) (segment (start 258.2306 86.4256) (end 259 85.6562) (width 0.254) (layer F.Cu) (net 54)) (segment (start 241.4956 86.4256) (end 258.2306 86.4256) (width 0.254) (layer F.Cu) (net 54)) (segment (start 240.27 85.2) (end 241.4956 86.4256) (width 0.254) (layer F.Cu) (net 54)) (segment (start 52.5394 68.3306) (end 50.27 70.6) (width 0.254) (layer F.Cu) (net 54)) (segment (start 108.0006 68.3306) (end 52.5394 68.3306) (width 0.254) (layer F.Cu) (net 54)) (segment (start 110.27 70.6) (end 108.0006 68.3306) (width 0.254) (layer F.Cu) (net 54)) (segment (start 110.27 85.2) (end 110.27 99.8) (width 0.254) (layer B.Cu) (net 54)) (segment (start 110.27 99.8) (end 110.27 114.4) (width 0.254) (layer B.Cu) (net 54)) (segment (start 110.27 114.4) (end 110.27 122.844) (width 0.254) (layer B.Cu) (net 54)) (segment (start 110.27 129) (end 110.27 122.844) (width 0.254) (layer F.Cu) (net 54)) (segment (start 255.17 128.78) (end 255.17 131.32) (width 0.254) (layer B.Cu) (net 54)) (segment (start 228.0301 133.6599) (end 225.19 136.5) (width 0.254) (layer B.Cu) (net 54)) (segment (start 246.8371 133.6599) (end 228.0301 133.6599) (width 0.254) (layer B.Cu) (net 54)) (segment (start 248.82 131.677) (end 246.8371 133.6599) (width 0.254) (layer B.Cu) (net 54)) (segment (start 249.6549 132.5119) (end 248.82 131.677) (width 0.254) (layer B.Cu) (net 54)) (segment (start 253.9781 132.5119) (end 249.6549 132.5119) (width 0.254) (layer B.Cu) (net 54)) (segment (start 255.17 131.32) (end 253.9781 132.5119) (width 0.254) (layer B.Cu) (net 54)) (segment (start 240.27 90.043) (end 240.27 85.2) (width 0.254) (layer B.Cu) (net 54)) (segment (start 248.82 98.593) (end 240.27 90.043) (width 0.254) (layer B.Cu) (net 54)) (segment (start 248.82 131.677) (end 248.82 98.593) (width 0.254) (layer B.Cu) (net 54)) (segment (start 106.7922 134.8978) (end 105.19 136.5) (width 0.254) (layer F.Cu) (net 54)) (segment (start 195.1149 134.8978) (end 106.7922 134.8978) (width 0.254) (layer F.Cu) (net 54)) (segment (start 198.322 138.1049) (end 195.1149 134.8978) (width 0.254) (layer F.Cu) (net 54)) (segment (start 223.5851 138.1049) (end 198.322 138.1049) (width 0.254) (layer F.Cu) (net 54)) (segment (start 225.19 136.5) (end 223.5851 138.1049) (width 0.254) (layer F.Cu) (net 54)) (segment (start 42.68 78.19) (end 42.68 99.13) (width 0.254) (layer B.Cu) (net 54)) (segment (start 50.27 70.6) (end 42.68 78.19) (width 0.254) (layer B.Cu) (net 54)) (segment (start 43.0937 134.4037) (end 45.19 136.5) (width 0.254) (layer B.Cu) (net 54)) (segment (start 33.8877 134.4037) (end 43.0937 134.4037) (width 0.254) (layer B.Cu) (net 54)) (segment (start 29 129.516) (end 33.8877 134.4037) (width 0.254) (layer B.Cu) (net 54)) (segment (start 29 112.3634) (end 29 129.516) (width 0.254) (layer B.Cu) (net 54)) (segment (start 42.2334 99.13) (end 29 112.3634) (width 0.254) (layer B.Cu) (net 54)) (segment (start 42.68 99.13) (end 42.2334 99.13) (width 0.254) (layer B.Cu) (net 54)) (via (at 120.27 122.844) (size 0.889) (layers F.Cu B.Cu) (net 55)) (segment (start 120.27 70.6) (end 120.27 85.2) (width 0.254) (layer B.Cu) (net 55)) (segment (start 120.27 85.2) (end 120.27 99.8) (width 0.254) (layer B.Cu) (net 55)) (segment (start 120.27 99.8) (end 120.27 114.4) (width 0.254) (layer B.Cu) (net 55)) (segment (start 254.8311 134.1989) (end 257.71 131.32) (width 0.254) (layer B.Cu) (net 55)) (segment (start 237.4911 134.1989) (end 254.8311 134.1989) (width 0.254) (layer B.Cu) (net 55)) (segment (start 235.19 136.5) (end 237.4911 134.1989) (width 0.254) (layer B.Cu) (net 55)) (segment (start 62.0311 68.8389) (end 60.27 70.6) (width 0.254) (layer F.Cu) (net 55)) (segment (start 100.907 68.8389) (end 62.0311 68.8389) (width 0.254) (layer F.Cu) (net 55)) (segment (start 103.8889 71.8208) (end 100.907 68.8389) (width 0.254) (layer F.Cu) (net 55)) (segment (start 119.0492 71.8208) (end 103.8889 71.8208) (width 0.254) (layer F.Cu) (net 55)) (segment (start 120.27 70.6) (end 119.0492 71.8208) (width 0.254) (layer F.Cu) (net 55)) (segment (start 120.27 131.42) (end 115.19 136.5) (width 0.254) (layer B.Cu) (net 55)) (segment (start 120.27 129) (end 120.27 131.42) (width 0.254) (layer B.Cu) (net 55)) (segment (start 120.27 114.4) (end 120.27 122.844) (width 0.254) (layer B.Cu) (net 55)) (segment (start 120.27 129) (end 120.27 122.844) (width 0.254) (layer F.Cu) (net 55)) (segment (start 45.22 85.65) (end 60.27 70.6) (width 0.254) (layer B.Cu) (net 55)) (segment (start 45.22 99.13) (end 45.22 85.65) (width 0.254) (layer B.Cu) (net 55)) (segment (start 237.3336 89.5636) (end 240.27 92.5) (width 0.254) (layer F.Cu) (net 55)) (segment (start 124.6336 89.5636) (end 237.3336 89.5636) (width 0.254) (layer F.Cu) (net 55)) (segment (start 120.27 85.2) (end 124.6336 89.5636) (width 0.254) (layer F.Cu) (net 55)) (segment (start 279 79.17) (end 280.27 77.9) (width 0.254) (layer F.Cu) (net 55)) (segment (start 279 90.12) (end 279 79.17) (width 0.254) (layer F.Cu) (net 55)) (segment (start 258.445 110.675) (end 279 90.12) (width 0.254) (layer F.Cu) (net 55)) (segment (start 240.27 92.5) (end 258.445 110.675) (width 0.254) (layer F.Cu) (net 55)) (segment (start 260.27 112.5) (end 260.27 114.4) (width 0.254) (layer F.Cu) (net 55)) (segment (start 258.445 110.675) (end 260.27 112.5) (width 0.254) (layer F.Cu) (net 55)) (segment (start 259 127.49) (end 257.71 128.78) (width 0.254) (layer B.Cu) (net 55)) (segment (start 259 115.67) (end 259 127.49) (width 0.254) (layer B.Cu) (net 55)) (segment (start 260.27 114.4) (end 259 115.67) (width 0.254) (layer B.Cu) (net 55)) (segment (start 257.71 128.78) (end 257.71 131.32) (width 0.254) (layer B.Cu) (net 55)) (segment (start 56.2699 135.4201) (end 55.19 136.5) (width 0.254) (layer F.Cu) (net 55)) (segment (start 77.6829 135.4201) (end 56.2699 135.4201) (width 0.254) (layer F.Cu) (net 55)) (segment (start 79.8427 137.5799) (end 77.6829 135.4201) (width 0.254) (layer F.Cu) (net 55)) (segment (start 114.1101 137.5799) (end 79.8427 137.5799) (width 0.254) (layer F.Cu) (net 55)) (segment (start 115.19 136.5) (end 114.1101 137.5799) (width 0.254) (layer F.Cu) (net 55)) (via (at 129.9214 122.844) (size 0.889) (layers F.Cu B.Cu) (net 56)) (segment (start 130.27 85.2) (end 130.27 99.8) (width 0.254) (layer B.Cu) (net 56)) (segment (start 130.27 99.8) (end 130.27 114.4) (width 0.254) (layer B.Cu) (net 56)) (segment (start 256.565 135.005) (end 260.25 131.32) (width 0.254) (layer B.Cu) (net 56)) (segment (start 246.685 135.005) (end 256.565 135.005) (width 0.254) (layer B.Cu) (net 56)) (segment (start 245.19 136.5) (end 246.685 135.005) (width 0.254) (layer B.Cu) (net 56)) (segment (start 129.9214 128.6514) (end 129.9214 122.844) (width 0.254) (layer F.Cu) (net 56)) (segment (start 130.27 129) (end 129.9214 128.6514) (width 0.254) (layer F.Cu) (net 56)) (segment (start 130.27 122.4954) (end 129.9214 122.844) (width 0.254) (layer B.Cu) (net 56)) (segment (start 130.27 114.4) (end 130.27 122.4954) (width 0.254) (layer B.Cu) (net 56)) (segment (start 130.27 131.42) (end 125.19 136.5) (width 0.254) (layer B.Cu) (net 56)) (segment (start 130.27 129) (end 130.27 131.42) (width 0.254) (layer B.Cu) (net 56)) (segment (start 67.294 138.604) (end 65.19 136.5) (width 0.254) (layer F.Cu) (net 56)) (segment (start 123.086 138.604) (end 67.294 138.604) (width 0.254) (layer F.Cu) (net 56)) (segment (start 125.19 136.5) (end 123.086 138.604) (width 0.254) (layer F.Cu) (net 56)) (segment (start 260.25 121.72) (end 260.25 128.78) (width 0.254) (layer B.Cu) (net 56)) (segment (start 260.27 121.7) (end 260.25 121.72) (width 0.254) (layer B.Cu) (net 56)) (segment (start 260.25 128.78) (end 260.25 131.32) (width 0.254) (layer B.Cu) (net 56)) (segment (start 70.27 76.62) (end 47.76 99.13) (width 0.254) (layer B.Cu) (net 56)) (segment (start 70.27 70.6) (end 70.27 76.62) (width 0.254) (layer B.Cu) (net 56)) (segment (start 280.27 96.1423) (end 258.4412 117.9711) (width 0.254) (layer F.Cu) (net 56)) (segment (start 280.27 85.2) (end 280.27 96.1423) (width 0.254) (layer F.Cu) (net 56)) (segment (start 260.27 119.8) (end 258.4412 117.9711) (width 0.254) (layer F.Cu) (net 56)) (segment (start 260.27 121.7) (end 260.27 119.8) (width 0.254) (layer F.Cu) (net 56)) (segment (start 130.27 74.0582) (end 128.5409 72.3291) (width 0.254) (layer F.Cu) (net 56)) (segment (start 130.27 85.2) (end 130.27 74.0582) (width 0.254) (layer F.Cu) (net 56)) (segment (start 97.0709 72.3291) (end 128.5409 72.3291) (width 0.254) (layer F.Cu) (net 56)) (segment (start 96.4914 71.7496) (end 97.0709 72.3291) (width 0.254) (layer F.Cu) (net 56)) (segment (start 91.5172 71.7496) (end 96.4914 71.7496) (width 0.254) (layer F.Cu) (net 56)) (segment (start 91.441 71.8258) (end 91.5172 71.7496) (width 0.254) (layer F.Cu) (net 56)) (segment (start 71.4958 71.8258) (end 91.441 71.8258) (width 0.254) (layer F.Cu) (net 56)) (segment (start 70.27 70.6) (end 71.4958 71.8258) (width 0.254) (layer F.Cu) (net 56)) (segment (start 128.5409 72.3291) (end 130.27 70.6) (width 0.254) (layer F.Cu) (net 56)) (segment (start 258.4412 117.9711) (end 240.27 99.8) (width 0.254) (layer F.Cu) (net 56)) (segment (start 235.2726 94.8026) (end 240.27 99.8) (width 0.254) (layer F.Cu) (net 56)) (segment (start 135.2674 94.8026) (end 235.2726 94.8026) (width 0.254) (layer F.Cu) (net 56)) (segment (start 130.27 99.8) (end 135.2674 94.8026) (width 0.254) (layer F.Cu) (net 56)) (via (at 140.27 122.805) (size 0.889) (layers F.Cu B.Cu) (net 57)) (segment (start 262.79 128.78) (end 262.79 131.32) (width 0.254) (layer B.Cu) (net 57)) (segment (start 257.61 136.5) (end 255.19 136.5) (width 0.254) (layer B.Cu) (net 57)) (segment (start 262.79 131.32) (end 257.61 136.5) (width 0.254) (layer B.Cu) (net 57)) (segment (start 140.27 70.6) (end 140.27 85.2) (width 0.254) (layer B.Cu) (net 57)) (segment (start 140.27 99.8) (end 140.27 85.2) (width 0.254) (layer B.Cu) (net 57)) (segment (start 31.1683 129) (end 30.27 129) (width 0.254) (layer B.Cu) (net 57)) (segment (start 76.7848 138.0948) (end 75.19 136.5) (width 0.254) (layer F.Cu) (net 57)) (segment (start 116.7935 138.0948) (end 76.7848 138.0948) (width 0.254) (layer F.Cu) (net 57)) (segment (start 119.4682 135.4201) (end 116.7935 138.0948) (width 0.254) (layer F.Cu) (net 57)) (segment (start 134.1101 135.4201) (end 119.4682 135.4201) (width 0.254) (layer F.Cu) (net 57)) (segment (start 135.19 136.5) (end 134.1101 135.4201) (width 0.254) (layer F.Cu) (net 57)) (segment (start 241.11 107.1) (end 240.27 107.1) (width 0.254) (layer F.Cu) (net 57)) (segment (start 262.79 128.78) (end 241.11 107.1) (width 0.254) (layer F.Cu) (net 57)) (segment (start 140.27 131.42) (end 135.19 136.5) (width 0.254) (layer B.Cu) (net 57)) (segment (start 140.27 129) (end 140.27 131.42) (width 0.254) (layer B.Cu) (net 57)) (segment (start 140.27 99.8) (end 140.27 114.4) (width 0.254) (layer B.Cu) (net 57)) (segment (start 36.0636 133.8953) (end 31.1683 129) (width 0.254) (layer B.Cu) (net 57)) (segment (start 72.5853 133.8953) (end 36.0636 133.8953) (width 0.254) (layer B.Cu) (net 57)) (segment (start 75.19 136.5) (end 72.5853 133.8953) (width 0.254) (layer B.Cu) (net 57)) (segment (start 140.27 114.4) (end 140.27 122.805) (width 0.254) (layer B.Cu) (net 57)) (segment (start 140.27 122.805) (end 140.27 129) (width 0.254) (layer F.Cu) (net 57)) (segment (start 47.3653 102.0647) (end 50.3 99.13) (width 0.254) (layer B.Cu) (net 57)) (segment (start 40.0177 102.0647) (end 47.3653 102.0647) (width 0.254) (layer B.Cu) (net 57)) (segment (start 31.1683 110.9141) (end 40.0177 102.0647) (width 0.254) (layer B.Cu) (net 57)) (segment (start 31.1683 129) (end 31.1683 110.9141) (width 0.254) (layer B.Cu) (net 57)) (segment (start 77.9693 72.9007) (end 80.27 70.6) (width 0.254) (layer B.Cu) (net 57)) (segment (start 76.5293 72.9007) (end 77.9693 72.9007) (width 0.254) (layer B.Cu) (net 57)) (segment (start 50.3 99.13) (end 76.5293 72.9007) (width 0.254) (layer B.Cu) (net 57)) (segment (start 238.1754 105.0054) (end 240.27 107.1) (width 0.254) (layer F.Cu) (net 57)) (segment (start 228.7164 105.0054) (end 238.1754 105.0054) (width 0.254) (layer F.Cu) (net 57)) (segment (start 223.5908 99.8798) (end 228.7164 105.0054) (width 0.254) (layer F.Cu) (net 57)) (segment (start 214.8688 99.8798) (end 223.5908 99.8798) (width 0.254) (layer F.Cu) (net 57)) (segment (start 212.5019 97.5129) (end 214.8688 99.8798) (width 0.254) (layer F.Cu) (net 57)) (segment (start 165.3282 97.5129) (end 212.5019 97.5129) (width 0.254) (layer F.Cu) (net 57)) (segment (start 161.2551 101.586) (end 165.3282 97.5129) (width 0.254) (layer F.Cu) (net 57)) (segment (start 142.056 101.586) (end 161.2551 101.586) (width 0.254) (layer F.Cu) (net 57)) (segment (start 140.27 99.8) (end 142.056 101.586) (width 0.254) (layer F.Cu) (net 57)) (via (at 158.0419 121.5844) (size 0.889) (layers F.Cu B.Cu) (net 58)) (segment (start 150.27 85.2) (end 150.27 70.6) (width 0.254) (layer B.Cu) (net 58)) (segment (start 265.33 136.36) (end 265.19 136.5) (width 0.254) (layer B.Cu) (net 58)) (segment (start 265.33 131.32) (end 265.33 136.36) (width 0.254) (layer B.Cu) (net 58)) (segment (start 81.4988 115.6288) (end 80.27 114.4) (width 0.254) (layer F.Cu) (net 58)) (segment (start 149.0412 115.6288) (end 81.4988 115.6288) (width 0.254) (layer F.Cu) (net 58)) (segment (start 150.27 114.4) (end 149.0412 115.6288) (width 0.254) (layer F.Cu) (net 58)) (segment (start 150.27 85.2) (end 150.27 99.8) (width 0.254) (layer B.Cu) (net 58)) (segment (start 150.27 99.8) (end 150.27 114.4) (width 0.254) (layer B.Cu) (net 58)) (segment (start 150.8575 114.4) (end 158.0419 121.5844) (width 0.254) (layer B.Cu) (net 58)) (segment (start 150.27 114.4) (end 150.8575 114.4) (width 0.254) (layer B.Cu) (net 58)) (segment (start 247.4947 114.4) (end 240.27 114.4) (width 0.254) (layer F.Cu) (net 58)) (segment (start 261.52 128.4253) (end 247.4947 114.4) (width 0.254) (layer F.Cu) (net 58)) (segment (start 261.52 129.1267) (end 261.52 128.4253) (width 0.254) (layer F.Cu) (net 58)) (segment (start 262.3462 129.9529) (end 261.52 129.1267) (width 0.254) (layer F.Cu) (net 58)) (segment (start 264.1571 129.9529) (end 262.3462 129.9529) (width 0.254) (layer F.Cu) (net 58)) (segment (start 265.33 128.78) (end 264.1571 129.9529) (width 0.254) (layer F.Cu) (net 58)) (segment (start 264.1571 130.1471) (end 265.33 131.32) (width 0.254) (layer F.Cu) (net 58)) (segment (start 264.1571 129.9529) (end 264.1571 130.1471) (width 0.254) (layer F.Cu) (net 58)) (segment (start 157.6856 121.5844) (end 158.0419 121.5844) (width 0.254) (layer F.Cu) (net 58)) (segment (start 150.27 129) (end 157.6856 121.5844) (width 0.254) (layer F.Cu) (net 58)) (segment (start 233.0856 121.5844) (end 240.27 114.4) (width 0.254) (layer F.Cu) (net 58)) (segment (start 158.0419 121.5844) (end 233.0856 121.5844) (width 0.254) (layer F.Cu) (net 58)) (segment (start 150.27 131.42) (end 145.19 136.5) (width 0.254) (layer B.Cu) (net 58)) (segment (start 150.27 129) (end 150.27 131.42) (width 0.254) (layer B.Cu) (net 58)) (segment (start 38.7266 127.4566) (end 40.27 129) (width 0.254) (layer B.Cu) (net 58)) (segment (start 38.7266 106.6156) (end 38.7266 127.4566) (width 0.254) (layer B.Cu) (net 58)) (segment (start 41.8307 103.5115) (end 38.7266 106.6156) (width 0.254) (layer B.Cu) (net 58)) (segment (start 48.4585 103.5115) (end 41.8307 103.5115) (width 0.254) (layer B.Cu) (net 58)) (segment (start 52.84 99.13) (end 48.4585 103.5115) (width 0.254) (layer B.Cu) (net 58)) (segment (start 56.7912 103.0812) (end 52.84 99.13) (width 0.254) (layer B.Cu) (net 58)) (segment (start 64.6395 103.0812) (end 56.7912 103.0812) (width 0.254) (layer B.Cu) (net 58)) (segment (start 77.178 115.6197) (end 64.6395 103.0812) (width 0.254) (layer B.Cu) (net 58)) (segment (start 79.0503 115.6197) (end 77.178 115.6197) (width 0.254) (layer B.Cu) (net 58)) (segment (start 80.27 114.4) (end 79.0503 115.6197) (width 0.254) (layer B.Cu) (net 58)) (via (at 34.4426 128.0754) (size 0.889) (layers F.Cu B.Cu) (net 59)) (via (at 162.2028 122.439) (size 0.889) (layers F.Cu B.Cu) (net 59)) (segment (start 273.7505 135.0605) (end 275.19 136.5) (width 0.254) (layer B.Cu) (net 59)) (segment (start 271.6105 135.0605) (end 273.7505 135.0605) (width 0.254) (layer B.Cu) (net 59)) (segment (start 267.87 131.32) (end 271.6105 135.0605) (width 0.254) (layer B.Cu) (net 59)) (segment (start 267.87 128.78) (end 267.87 131.32) (width 0.254) (layer F.Cu) (net 59)) (segment (start 245.0628 126.4928) (end 240.27 121.7) (width 0.254) (layer F.Cu) (net 59)) (segment (start 245.0628 126.4929) (end 245.0628 126.4928) (width 0.254) (layer F.Cu) (net 59)) (segment (start 257.052 126.4929) (end 245.0628 126.4929) (width 0.254) (layer F.Cu) (net 59)) (segment (start 258.98 128.4209) (end 257.052 126.4929) (width 0.254) (layer F.Cu) (net 59)) (segment (start 258.98 129.1268) (end 258.98 128.4209) (width 0.254) (layer F.Cu) (net 59)) (segment (start 259.7766 129.9234) (end 258.98 129.1268) (width 0.254) (layer F.Cu) (net 59)) (segment (start 260.4702 129.9234) (end 259.7766 129.9234) (width 0.254) (layer F.Cu) (net 59)) (segment (start 261.3934 130.8466) (end 260.4702 129.9234) (width 0.254) (layer F.Cu) (net 59)) (segment (start 261.3934 131.5737) (end 261.3934 130.8466) (width 0.254) (layer F.Cu) (net 59)) (segment (start 262.3 132.4803) (end 261.3934 131.5737) (width 0.254) (layer F.Cu) (net 59)) (segment (start 266.7097 132.4803) (end 262.3 132.4803) (width 0.254) (layer F.Cu) (net 59)) (segment (start 267.87 131.32) (end 266.7097 132.4803) (width 0.254) (layer F.Cu) (net 59)) (segment (start 160.27 131.42) (end 155.19 136.5) (width 0.254) (layer B.Cu) (net 59)) (segment (start 160.27 129) (end 160.27 131.42) (width 0.254) (layer B.Cu) (net 59)) (segment (start 34.7376 127.7804) (end 34.4426 128.0754) (width 0.254) (layer F.Cu) (net 59)) (segment (start 42.5862 127.7804) (end 34.7376 127.7804) (width 0.254) (layer F.Cu) (net 59)) (segment (start 45.0282 130.2224) (end 42.5862 127.7804) (width 0.254) (layer F.Cu) (net 59)) (segment (start 49.0476 130.2224) (end 45.0282 130.2224) (width 0.254) (layer F.Cu) (net 59)) (segment (start 50.27 129) (end 49.0476 130.2224) (width 0.254) (layer F.Cu) (net 59)) (segment (start 158.4779 127.2079) (end 160.27 129) (width 0.254) (layer B.Cu) (net 59)) (segment (start 110.309 127.2079) (end 158.4779 127.2079) (width 0.254) (layer B.Cu) (net 59)) (segment (start 109 128.5169) (end 110.309 127.2079) (width 0.254) (layer B.Cu) (net 59)) (segment (start 109 129.464) (end 109 128.5169) (width 0.254) (layer B.Cu) (net 59)) (segment (start 107.4969 130.9671) (end 109 129.464) (width 0.254) (layer B.Cu) (net 59)) (segment (start 104.7575 130.9671) (end 107.4969 130.9671) (width 0.254) (layer B.Cu) (net 59)) (segment (start 98.0985 137.6261) (end 104.7575 130.9671) (width 0.254) (layer B.Cu) (net 59)) (segment (start 94.7424 137.6261) (end 98.0985 137.6261) (width 0.254) (layer B.Cu) (net 59)) (segment (start 93.6932 136.5769) (end 94.7424 137.6261) (width 0.254) (layer B.Cu) (net 59)) (segment (start 93.6932 135.6392) (end 93.6932 136.5769) (width 0.254) (layer B.Cu) (net 59)) (segment (start 93.072 135.018) (end 93.6932 135.6392) (width 0.254) (layer B.Cu) (net 59)) (segment (start 86.4229 135.018) (end 93.072 135.018) (width 0.254) (layer B.Cu) (net 59)) (segment (start 83.3665 131.9616) (end 86.4229 135.018) (width 0.254) (layer B.Cu) (net 59)) (segment (start 72.3687 131.9616) (end 83.3665 131.9616) (width 0.254) (layer B.Cu) (net 59)) (segment (start 72.0775 132.2528) (end 72.3687 131.9616) (width 0.254) (layer B.Cu) (net 59)) (segment (start 53.5228 132.2528) (end 72.0775 132.2528) (width 0.254) (layer B.Cu) (net 59)) (segment (start 50.27 129) (end 53.5228 132.2528) (width 0.254) (layer B.Cu) (net 59)) (segment (start 160.27 114.4) (end 160.27 101.0468) (width 0.254) (layer B.Cu) (net 59)) (segment (start 160.27 101.0468) (end 160.27 99.8) (width 0.254) (layer B.Cu) (net 59)) (segment (start 163.0305 123.2667) (end 162.2028 122.439) (width 0.254) (layer F.Cu) (net 59)) (segment (start 238.7033 123.2667) (end 163.0305 123.2667) (width 0.254) (layer F.Cu) (net 59)) (segment (start 240.27 121.7) (end 238.7033 123.2667) (width 0.254) (layer F.Cu) (net 59)) (segment (start 160.27 126.0272) (end 160.27 129) (width 0.254) (layer F.Cu) (net 59)) (segment (start 163.0305 123.2667) (end 160.27 126.0272) (width 0.254) (layer F.Cu) (net 59)) (segment (start 160.27 120.5062) (end 160.27 114.4) (width 0.254) (layer B.Cu) (net 59)) (segment (start 162.2028 122.439) (end 160.27 120.5062) (width 0.254) (layer B.Cu) (net 59)) (segment (start 31.7164 125.3492) (end 34.4426 128.0754) (width 0.254) (layer B.Cu) (net 59)) (segment (start 31.7164 111.0923) (end 31.7164 125.3492) (width 0.254) (layer B.Cu) (net 59)) (segment (start 40.2357 102.573) (end 31.7164 111.0923) (width 0.254) (layer B.Cu) (net 59)) (segment (start 48.3842 102.573) (end 40.2357 102.573) (width 0.254) (layer B.Cu) (net 59)) (segment (start 51.7499 99.2073) (end 48.3842 102.573) (width 0.254) (layer B.Cu) (net 59)) (segment (start 51.7499 98.693) (end 51.7499 99.2073) (width 0.254) (layer B.Cu) (net 59)) (segment (start 52.3962 98.0467) (end 51.7499 98.693) (width 0.254) (layer B.Cu) (net 59)) (segment (start 54.2967 98.0467) (end 52.3962 98.0467) (width 0.254) (layer B.Cu) (net 59)) (segment (start 55.38 99.13) (end 54.2967 98.0467) (width 0.254) (layer B.Cu) (net 59)) (segment (start 156.4896 88.9804) (end 160.27 85.2) (width 0.254) (layer B.Cu) (net 59)) (segment (start 156.4896 100.2923) (end 156.4896 88.9804) (width 0.254) (layer B.Cu) (net 59)) (segment (start 157.2441 101.0468) (end 156.4896 100.2923) (width 0.254) (layer B.Cu) (net 59)) (segment (start 160.27 101.0468) (end 157.2441 101.0468) (width 0.254) (layer B.Cu) (net 59)) (segment (start 160.27 85.2) (end 160.27 70.6) (width 0.254) (layer B.Cu) (net 59)) (via (at 170.8751 117.5151) (size 0.889) (layers F.Cu B.Cu) (net 60)) (via (at 56.7816 109.3605) (size 0.889) (layers F.Cu B.Cu) (net 60)) (segment (start 170.27 114.4) (end 170.27 99.8) (width 0.254) (layer B.Cu) (net 60)) (segment (start 170.27 70.6) (end 170.27 85.2) (width 0.254) (layer B.Cu) (net 60)) (segment (start 170.27 85.2) (end 170.27 99.8) (width 0.254) (layer B.Cu) (net 60)) (segment (start 170.27 131.42) (end 165.19 136.5) (width 0.254) (layer B.Cu) (net 60)) (segment (start 170.27 129) (end 170.27 131.42) (width 0.254) (layer B.Cu) (net 60)) (segment (start 170.8751 115.0051) (end 170.8751 117.5151) (width 0.254) (layer F.Cu) (net 60)) (segment (start 170.27 114.4) (end 170.8751 115.0051) (width 0.254) (layer F.Cu) (net 60)) (segment (start 169.3295 119.0607) (end 169.3295 126.1413) (width 0.254) (layer B.Cu) (net 60)) (segment (start 170.8751 117.5151) (end 169.3295 119.0607) (width 0.254) (layer B.Cu) (net 60)) (segment (start 169.3295 128.0595) (end 169.3295 126.1413) (width 0.254) (layer B.Cu) (net 60)) (segment (start 170.27 129) (end 169.3295 128.0595) (width 0.254) (layer B.Cu) (net 60)) (segment (start 270.41 131.32) (end 270.41 128.78) (width 0.254) (layer B.Cu) (net 60)) (segment (start 255.9498 74.9202) (end 260.27 70.6) (width 0.254) (layer B.Cu) (net 60)) (segment (start 255.9498 93.6765) (end 255.9498 74.9202) (width 0.254) (layer B.Cu) (net 60)) (segment (start 270.41 108.1367) (end 255.9498 93.6765) (width 0.254) (layer B.Cu) (net 60)) (segment (start 270.41 128.78) (end 270.41 108.1367) (width 0.254) (layer B.Cu) (net 60)) (segment (start 63.6218 131.2362) (end 61.3856 129) (width 0.254) (layer B.Cu) (net 60)) (segment (start 71.6565 131.2362) (end 63.6218 131.2362) (width 0.254) (layer B.Cu) (net 60)) (segment (start 71.9571 130.9356) (end 71.6565 131.2362) (width 0.254) (layer B.Cu) (net 60)) (segment (start 85.0612 130.9356) (end 71.9571 130.9356) (width 0.254) (layer B.Cu) (net 60)) (segment (start 85.9234 131.7978) (end 85.0612 130.9356) (width 0.254) (layer B.Cu) (net 60)) (segment (start 92.0876 131.7978) (end 85.9234 131.7978) (width 0.254) (layer B.Cu) (net 60)) (segment (start 97.7441 126.1413) (end 92.0876 131.7978) (width 0.254) (layer B.Cu) (net 60)) (segment (start 169.3295 126.1413) (end 97.7441 126.1413) (width 0.254) (layer B.Cu) (net 60)) (segment (start 61.3856 129) (end 60.27 129) (width 0.254) (layer B.Cu) (net 60)) (segment (start 171.5398 69.3302) (end 170.27 70.6) (width 0.254) (layer F.Cu) (net 60)) (segment (start 205.5364 69.3302) (end 171.5398 69.3302) (width 0.254) (layer F.Cu) (net 60)) (segment (start 206.6267 70.4205) (end 205.5364 69.3302) (width 0.254) (layer F.Cu) (net 60)) (segment (start 210.9943 70.4205) (end 206.6267 70.4205) (width 0.254) (layer F.Cu) (net 60)) (segment (start 212.5676 68.8472) (end 210.9943 70.4205) (width 0.254) (layer F.Cu) (net 60)) (segment (start 258.5172 68.8472) (end 212.5676 68.8472) (width 0.254) (layer F.Cu) (net 60)) (segment (start 260.27 70.6) (end 258.5172 68.8472) (width 0.254) (layer F.Cu) (net 60)) (segment (start 56.7816 117.7046) (end 56.7816 109.3605) (width 0.254) (layer B.Cu) (net 60)) (segment (start 61.3856 122.3086) (end 56.7816 117.7046) (width 0.254) (layer B.Cu) (net 60)) (segment (start 61.3856 129) (end 61.3856 122.3086) (width 0.254) (layer B.Cu) (net 60)) (segment (start 56.7816 100.2684) (end 57.92 99.13) (width 0.254) (layer F.Cu) (net 60)) (segment (start 56.7816 109.3605) (end 56.7816 100.2684) (width 0.254) (layer F.Cu) (net 60)) (segment (start 188.9652 71.8352) (end 187.73 70.6) (width 0.254) (layer F.Cu) (net 61)) (segment (start 196.4948 71.8352) (end 188.9652 71.8352) (width 0.254) (layer F.Cu) (net 61)) (segment (start 197.73 70.6) (end 196.4948 71.8352) (width 0.254) (layer F.Cu) (net 61)) (segment (start 88.9495 69.3805) (end 87.73 70.6) (width 0.254) (layer B.Cu) (net 61)) (segment (start 96.5105 69.3805) (end 88.9495 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 97.73 70.6) (end 96.5105 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 98.9495 69.3805) (end 97.73 70.6) (width 0.254) (layer B.Cu) (net 61)) (segment (start 106.5105 69.3805) (end 98.9495 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 107.73 70.6) (end 106.5105 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 108.9495 69.3805) (end 107.73 70.6) (width 0.254) (layer B.Cu) (net 61)) (segment (start 116.5105 69.3805) (end 108.9495 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 117.73 70.6) (end 116.5105 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 118.9495 69.3805) (end 117.73 70.6) (width 0.254) (layer B.Cu) (net 61)) (segment (start 126.5105 69.3805) (end 118.9495 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 127.73 70.6) (end 126.5105 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 128.9495 69.3805) (end 127.73 70.6) (width 0.254) (layer B.Cu) (net 61)) (segment (start 136.5105 69.3805) (end 128.9495 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 137.73 70.6) (end 136.5105 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 138.9495 69.3805) (end 137.73 70.6) (width 0.254) (layer B.Cu) (net 61)) (segment (start 146.5105 69.3805) (end 138.9495 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 147.73 70.6) (end 146.5105 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 148.9495 69.3805) (end 147.73 70.6) (width 0.254) (layer B.Cu) (net 61)) (segment (start 156.5105 69.3805) (end 148.9495 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 157.73 70.6) (end 156.5105 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 158.9495 69.3805) (end 157.73 70.6) (width 0.254) (layer B.Cu) (net 61)) (segment (start 166.5105 69.3805) (end 158.9495 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 167.73 70.6) (end 166.5105 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 168.9495 69.3805) (end 167.73 70.6) (width 0.254) (layer B.Cu) (net 61)) (segment (start 176.5105 69.3805) (end 168.9495 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 177.73 70.6) (end 176.5105 69.3805) (width 0.254) (layer B.Cu) (net 61)) (segment (start 186.4901 69.3601) (end 187.73 70.6) (width 0.254) (layer B.Cu) (net 61)) (segment (start 178.9699 69.3601) (end 186.4901 69.3601) (width 0.254) (layer B.Cu) (net 61)) (segment (start 177.73 70.6) (end 178.9699 69.3601) (width 0.254) (layer B.Cu) (net 61)) (segment (start 224.4891 109.5009) (end 222.86 111.13) (width 0.254) (layer B.Cu) (net 61)) (segment (start 224.4891 95.9211) (end 224.4891 109.5009) (width 0.254) (layer B.Cu) (net 61)) (segment (start 223.188 94.62) (end 224.4891 95.9211) (width 0.254) (layer B.Cu) (net 61)) (segment (start 222.568 94.62) (end 223.188 94.62) (width 0.254) (layer B.Cu) (net 61)) (segment (start 214.6246 86.6766) (end 222.568 94.62) (width 0.254) (layer B.Cu) (net 61)) (segment (start 214.6246 83.1806) (end 214.6246 86.6766) (width 0.254) (layer B.Cu) (net 61)) (segment (start 200.8244 69.3804) (end 214.6246 83.1806) (width 0.254) (layer B.Cu) (net 61)) (segment (start 198.9496 69.3804) (end 200.8244 69.3804) (width 0.254) (layer B.Cu) (net 61)) (segment (start 197.73 70.6) (end 198.9496 69.3804) (width 0.254) (layer B.Cu) (net 61)) (segment (start 96.5104 86.4196) (end 97.73 85.2) (width 0.254) (layer B.Cu) (net 62)) (segment (start 88.9496 86.4196) (end 96.5104 86.4196) (width 0.254) (layer B.Cu) (net 62)) (segment (start 87.73 85.2) (end 88.9496 86.4196) (width 0.254) (layer B.Cu) (net 62)) (segment (start 98.9496 86.4196) (end 97.73 85.2) (width 0.254) (layer B.Cu) (net 62)) (segment (start 106.5104 86.4196) (end 98.9496 86.4196) (width 0.254) (layer B.Cu) (net 62)) (segment (start 107.73 85.2) (end 106.5104 86.4196) (width 0.254) (layer B.Cu) (net 62)) (segment (start 108.9605 86.4305) (end 107.73 85.2) (width 0.254) (layer F.Cu) (net 62)) (segment (start 116.4995 86.4305) (end 108.9605 86.4305) (width 0.254) (layer F.Cu) (net 62)) (segment (start 117.73 85.2) (end 116.4995 86.4305) (width 0.254) (layer F.Cu) (net 62)) (segment (start 221.3999 107.1299) (end 222.86 108.59) (width 0.254) (layer B.Cu) (net 62)) (segment (start 221.3999 95.4147) (end 221.3999 107.1299) (width 0.254) (layer B.Cu) (net 62)) (segment (start 215.4577 89.4725) (end 221.3999 95.4147) (width 0.254) (layer B.Cu) (net 62)) (segment (start 202.0025 89.4725) (end 215.4577 89.4725) (width 0.254) (layer B.Cu) (net 62)) (segment (start 197.73 85.2) (end 202.0025 89.4725) (width 0.254) (layer B.Cu) (net 62)) (segment (start 138.9496 83.9804) (end 137.73 85.2) (width 0.254) (layer F.Cu) (net 62)) (segment (start 146.5104 83.9804) (end 138.9496 83.9804) (width 0.254) (layer F.Cu) (net 62)) (segment (start 147.73 85.2) (end 146.5104 83.9804) (width 0.254) (layer F.Cu) (net 62)) (segment (start 148.9943 86.4643) (end 147.73 85.2) (width 0.254) (layer F.Cu) (net 62)) (segment (start 156.4657 86.4643) (end 148.9943 86.4643) (width 0.254) (layer F.Cu) (net 62)) (segment (start 157.73 85.2) (end 156.4657 86.4643) (width 0.254) (layer F.Cu) (net 62)) (segment (start 158.9496 83.9804) (end 157.73 85.2) (width 0.254) (layer F.Cu) (net 62)) (segment (start 166.5104 83.9804) (end 158.9496 83.9804) (width 0.254) (layer F.Cu) (net 62)) (segment (start 167.73 85.2) (end 166.5104 83.9804) (width 0.254) (layer F.Cu) (net 62)) (segment (start 168.9943 86.4643) (end 167.73 85.2) (width 0.254) (layer F.Cu) (net 62)) (segment (start 176.4657 86.4643) (end 168.9943 86.4643) (width 0.254) (layer F.Cu) (net 62)) (segment (start 177.73 85.2) (end 176.4657 86.4643) (width 0.254) (layer F.Cu) (net 62)) (segment (start 178.9496 83.9804) (end 177.73 85.2) (width 0.254) (layer F.Cu) (net 62)) (segment (start 186.5104 83.9804) (end 178.9496 83.9804) (width 0.254) (layer F.Cu) (net 62)) (segment (start 187.73 85.2) (end 186.5104 83.9804) (width 0.254) (layer F.Cu) (net 62)) (segment (start 188.9887 83.9413) (end 187.73 85.2) (width 0.254) (layer F.Cu) (net 62)) (segment (start 196.4713 83.9413) (end 188.9887 83.9413) (width 0.254) (layer F.Cu) (net 62)) (segment (start 197.73 85.2) (end 196.4713 83.9413) (width 0.254) (layer F.Cu) (net 62)) (segment (start 126.5104 83.9804) (end 127.73 85.2) (width 0.254) (layer F.Cu) (net 62)) (segment (start 118.9496 83.9804) (end 126.5104 83.9804) (width 0.254) (layer F.Cu) (net 62)) (segment (start 117.73 85.2) (end 118.9496 83.9804) (width 0.254) (layer F.Cu) (net 62)) (segment (start 136.5104 86.4196) (end 137.73 85.2) (width 0.254) (layer F.Cu) (net 62)) (segment (start 128.9496 86.4196) (end 136.5104 86.4196) (width 0.254) (layer F.Cu) (net 62)) (segment (start 127.73 85.2) (end 128.9496 86.4196) (width 0.254) (layer F.Cu) (net 62)) (segment (start 98.9835 98.5465) (end 97.73 99.8) (width 0.254) (layer B.Cu) (net 63)) (segment (start 106.4765 98.5465) (end 98.9835 98.5465) (width 0.254) (layer B.Cu) (net 63)) (segment (start 107.73 99.8) (end 106.4765 98.5465) (width 0.254) (layer B.Cu) (net 63)) (segment (start 196.487 98.557) (end 197.73 99.8) (width 0.254) (layer F.Cu) (net 63)) (segment (start 188.973 98.557) (end 196.487 98.557) (width 0.254) (layer F.Cu) (net 63)) (segment (start 187.73 99.8) (end 188.973 98.557) (width 0.254) (layer F.Cu) (net 63)) (segment (start 223.9433 104.9667) (end 222.86 106.05) (width 0.254) (layer F.Cu) (net 63)) (segment (start 223.9433 103.0561) (end 223.9433 104.9667) (width 0.254) (layer F.Cu) (net 63)) (segment (start 223.1272 102.24) (end 223.9433 103.0561) (width 0.254) (layer F.Cu) (net 63)) (segment (start 200.17 102.24) (end 223.1272 102.24) (width 0.254) (layer F.Cu) (net 63)) (segment (start 197.73 99.8) (end 200.17 102.24) (width 0.254) (layer F.Cu) (net 63)) (segment (start 88.959 101.029) (end 87.73 99.8) (width 0.254) (layer F.Cu) (net 63)) (segment (start 96.501 101.029) (end 88.959 101.029) (width 0.254) (layer F.Cu) (net 63)) (segment (start 97.73 99.8) (end 96.501 101.029) (width 0.254) (layer F.Cu) (net 63)) (segment (start 176.5104 101.0196) (end 177.73 99.8) (width 0.254) (layer F.Cu) (net 63)) (segment (start 168.9496 101.0196) (end 176.5104 101.0196) (width 0.254) (layer F.Cu) (net 63)) (segment (start 167.73 99.8) (end 168.9496 101.0196) (width 0.254) (layer F.Cu) (net 63)) (segment (start 186.4749 98.5449) (end 187.73 99.8) (width 0.254) (layer F.Cu) (net 63)) (segment (start 178.9851 98.5449) (end 186.4749 98.5449) (width 0.254) (layer F.Cu) (net 63)) (segment (start 177.73 99.8) (end 178.9851 98.5449) (width 0.254) (layer F.Cu) (net 63)) (segment (start 128.9496 101.0196) (end 127.73 99.8) (width 0.254) (layer F.Cu) (net 63)) (segment (start 136.5104 101.0196) (end 128.9496 101.0196) (width 0.254) (layer F.Cu) (net 63)) (segment (start 137.73 99.8) (end 136.5104 101.0196) (width 0.254) (layer F.Cu) (net 63)) (segment (start 108.9503 101.0203) (end 107.73 99.8) (width 0.254) (layer F.Cu) (net 63)) (segment (start 116.5097 101.0203) (end 108.9503 101.0203) (width 0.254) (layer F.Cu) (net 63)) (segment (start 117.73 99.8) (end 116.5097 101.0203) (width 0.254) (layer F.Cu) (net 63)) (segment (start 126.5104 101.0196) (end 127.73 99.8) (width 0.254) (layer F.Cu) (net 63)) (segment (start 118.9496 101.0196) (end 126.5104 101.0196) (width 0.254) (layer F.Cu) (net 63)) (segment (start 117.73 99.8) (end 118.9496 101.0196) (width 0.254) (layer F.Cu) (net 63)) (segment (start 166.5031 98.5731) (end 167.73 99.8) (width 0.254) (layer B.Cu) (net 63)) (segment (start 158.9569 98.5731) (end 166.5031 98.5731) (width 0.254) (layer B.Cu) (net 63)) (segment (start 157.73 99.8) (end 158.9569 98.5731) (width 0.254) (layer B.Cu) (net 63)) (segment (start 139.4579 98.0721) (end 137.73 99.8) (width 0.254) (layer F.Cu) (net 63)) (segment (start 146.0021 98.0721) (end 139.4579 98.0721) (width 0.254) (layer F.Cu) (net 63)) (segment (start 147.73 99.8) (end 146.0021 98.0721) (width 0.254) (layer F.Cu) (net 63)) (segment (start 148.9941 98.5359) (end 147.73 99.8) (width 0.254) (layer F.Cu) (net 63)) (segment (start 156.4659 98.5359) (end 148.9941 98.5359) (width 0.254) (layer F.Cu) (net 63)) (segment (start 157.73 99.8) (end 156.4659 98.5359) (width 0.254) (layer F.Cu) (net 63)) (segment (start 148.9496 113.1804) (end 147.73 114.4) (width 0.254) (layer F.Cu) (net 64)) (segment (start 156.5104 113.1804) (end 148.9496 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 157.73 114.4) (end 156.5104 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 158.9522 115.6222) (end 157.73 114.4) (width 0.254) (layer F.Cu) (net 64)) (segment (start 166.5078 115.6222) (end 158.9522 115.6222) (width 0.254) (layer F.Cu) (net 64)) (segment (start 167.73 114.4) (end 166.5078 115.6222) (width 0.254) (layer F.Cu) (net 64)) (segment (start 178.9717 113.1583) (end 177.73 114.4) (width 0.254) (layer B.Cu) (net 64)) (segment (start 186.4883 113.1583) (end 178.9717 113.1583) (width 0.254) (layer B.Cu) (net 64)) (segment (start 187.73 114.4) (end 186.4883 113.1583) (width 0.254) (layer B.Cu) (net 64)) (segment (start 196.4923 113.1623) (end 197.73 114.4) (width 0.254) (layer B.Cu) (net 64)) (segment (start 188.9677 113.1623) (end 196.4923 113.1623) (width 0.254) (layer B.Cu) (net 64)) (segment (start 187.73 114.4) (end 188.9677 113.1623) (width 0.254) (layer B.Cu) (net 64)) (segment (start 118.9496 113.1804) (end 117.73 114.4) (width 0.254) (layer F.Cu) (net 64)) (segment (start 126.5104 113.1804) (end 118.9496 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 127.73 114.4) (end 126.5104 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 108.9496 113.1804) (end 107.73 114.4) (width 0.254) (layer F.Cu) (net 64)) (segment (start 116.5104 113.1804) (end 108.9496 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 117.73 114.4) (end 116.5104 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 168.9564 113.1736) (end 167.73 114.4) (width 0.254) (layer F.Cu) (net 64)) (segment (start 176.5036 113.1736) (end 168.9564 113.1736) (width 0.254) (layer F.Cu) (net 64)) (segment (start 177.73 114.4) (end 176.5036 113.1736) (width 0.254) (layer F.Cu) (net 64)) (segment (start 98.9496 113.1804) (end 97.73 114.4) (width 0.254) (layer F.Cu) (net 64)) (segment (start 106.5104 113.1804) (end 98.9496 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 107.73 114.4) (end 106.5104 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 88.9496 113.1804) (end 87.73 114.4) (width 0.254) (layer F.Cu) (net 64)) (segment (start 96.5104 113.1804) (end 88.9496 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 97.73 114.4) (end 96.5104 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 138.9496 113.1804) (end 137.73 114.4) (width 0.254) (layer F.Cu) (net 64)) (segment (start 146.5104 113.1804) (end 138.9496 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 147.73 114.4) (end 146.5104 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 128.9496 113.1804) (end 127.73 114.4) (width 0.254) (layer F.Cu) (net 64)) (segment (start 136.5104 113.1804) (end 128.9496 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 137.73 114.4) (end 136.5104 113.1804) (width 0.254) (layer F.Cu) (net 64)) (segment (start 218.9886 107.3814) (end 222.86 103.51) (width 0.254) (layer F.Cu) (net 64)) (segment (start 218.9886 107.3815) (end 218.9886 107.3814) (width 0.254) (layer F.Cu) (net 64)) (segment (start 204.7067 107.3815) (end 218.9886 107.3815) (width 0.254) (layer F.Cu) (net 64)) (segment (start 197.73 114.3582) (end 204.7067 107.3815) (width 0.254) (layer F.Cu) (net 64)) (segment (start 197.73 114.4) (end 197.73 114.3582) (width 0.254) (layer F.Cu) (net 64)) (via (at 211.7167 117.5345) (size 0.889) (layers F.Cu B.Cu) (net 65)) (segment (start 138.9495 127.7805) (end 137.73 129) (width 0.254) (layer B.Cu) (net 65)) (segment (start 146.5105 127.7805) (end 138.9495 127.7805) (width 0.254) (layer B.Cu) (net 65)) (segment (start 147.73 129) (end 146.5105 127.7805) (width 0.254) (layer B.Cu) (net 65)) (segment (start 178.9495 127.7805) (end 177.73 129) (width 0.254) (layer F.Cu) (net 65)) (segment (start 186.5105 127.7805) (end 178.9495 127.7805) (width 0.254) (layer F.Cu) (net 65)) (segment (start 187.73 129) (end 186.5105 127.7805) (width 0.254) (layer F.Cu) (net 65)) (segment (start 166.5104 130.2196) (end 167.73 129) (width 0.254) (layer F.Cu) (net 65)) (segment (start 158.9496 130.2196) (end 166.5104 130.2196) (width 0.254) (layer F.Cu) (net 65)) (segment (start 157.73 129) (end 158.9496 130.2196) (width 0.254) (layer F.Cu) (net 65)) (segment (start 168.9496 130.2196) (end 167.73 129) (width 0.254) (layer F.Cu) (net 65)) (segment (start 176.5104 130.2196) (end 168.9496 130.2196) (width 0.254) (layer F.Cu) (net 65)) (segment (start 177.73 129) (end 176.5104 130.2196) (width 0.254) (layer F.Cu) (net 65)) (segment (start 156.5105 127.7805) (end 157.73 129) (width 0.254) (layer B.Cu) (net 65)) (segment (start 148.9495 127.7805) (end 156.5105 127.7805) (width 0.254) (layer B.Cu) (net 65)) (segment (start 147.73 129) (end 148.9495 127.7805) (width 0.254) (layer B.Cu) (net 65)) (segment (start 128.9719 127.7581) (end 127.73 129) (width 0.254) (layer B.Cu) (net 65)) (segment (start 136.4881 127.7581) (end 128.9719 127.7581) (width 0.254) (layer B.Cu) (net 65)) (segment (start 137.73 129) (end 136.4881 127.7581) (width 0.254) (layer B.Cu) (net 65)) (segment (start 98.9713 127.7587) (end 97.73 129) (width 0.254) (layer B.Cu) (net 65)) (segment (start 106.4887 127.7587) (end 98.9713 127.7587) (width 0.254) (layer B.Cu) (net 65)) (segment (start 107.73 129) (end 106.4887 127.7587) (width 0.254) (layer B.Cu) (net 65)) (segment (start 88.9496 127.7804) (end 87.73 129) (width 0.254) (layer F.Cu) (net 65)) (segment (start 96.5104 127.7804) (end 88.9496 127.7804) (width 0.254) (layer F.Cu) (net 65)) (segment (start 97.73 129) (end 96.5104 127.7804) (width 0.254) (layer F.Cu) (net 65)) (segment (start 188.9603 130.2303) (end 187.73 129) (width 0.254) (layer F.Cu) (net 65)) (segment (start 196.4997 130.2303) (end 188.9603 130.2303) (width 0.254) (layer F.Cu) (net 65)) (segment (start 197.73 129) (end 196.4997 130.2303) (width 0.254) (layer F.Cu) (net 65)) (segment (start 116.5104 130.2196) (end 117.73 129) (width 0.254) (layer F.Cu) (net 65)) (segment (start 108.9496 130.2196) (end 116.5104 130.2196) (width 0.254) (layer F.Cu) (net 65)) (segment (start 107.73 129) (end 108.9496 130.2196) (width 0.254) (layer F.Cu) (net 65)) (segment (start 118.9496 130.2196) (end 117.73 129) (width 0.254) (layer F.Cu) (net 65)) (segment (start 126.5104 130.2196) (end 118.9496 130.2196) (width 0.254) (layer F.Cu) (net 65)) (segment (start 127.73 129) (end 126.5104 130.2196) (width 0.254) (layer F.Cu) (net 65)) (segment (start 209.1955 117.5345) (end 211.7167 117.5345) (width 0.254) (layer B.Cu) (net 65)) (segment (start 197.73 129) (end 209.1955 117.5345) (width 0.254) (layer B.Cu) (net 65)) (segment (start 224.5007 102.6107) (end 222.86 100.97) (width 0.254) (layer F.Cu) (net 65)) (segment (start 224.5007 105.9974) (end 224.5007 102.6107) (width 0.254) (layer F.Cu) (net 65)) (segment (start 223.1781 107.32) (end 224.5007 105.9974) (width 0.254) (layer F.Cu) (net 65)) (segment (start 221.9312 107.32) (end 223.1781 107.32) (width 0.254) (layer F.Cu) (net 65)) (segment (start 211.7167 117.5345) (end 221.9312 107.32) (width 0.254) (layer F.Cu) (net 65)) (segment (start 237.73 77.9) (end 237.73 85.2) (width 0.254) (layer B.Cu) (net 66)) (segment (start 237.73 85.2) (end 237.73 92.5) (width 0.254) (layer B.Cu) (net 66)) (segment (start 237.73 92.5) (end 237.73 99.8) (width 0.254) (layer B.Cu) (net 66)) (segment (start 237.73 99.8) (end 237.73 107.1) (width 0.254) (layer B.Cu) (net 66)) (segment (start 257.73 85.2) (end 257.73 92.5) (width 0.254) (layer B.Cu) (net 66)) (segment (start 257.73 77.9) (end 257.73 85.2) (width 0.254) (layer F.Cu) (net 66)) (segment (start 237.73 107.1) (end 237.73 114.4) (width 0.254) (layer B.Cu) (net 66)) (segment (start 237.73 114.4) (end 237.73 121.7) (width 0.254) (layer B.Cu) (net 66)) (segment (start 256.5049 76.6749) (end 257.73 77.9) (width 0.254) (layer F.Cu) (net 66)) (segment (start 256.5049 71.8251) (end 256.5049 76.6749) (width 0.254) (layer F.Cu) (net 66)) (segment (start 256.5049 71.8251) (end 257.73 70.6) (width 0.254) (layer F.Cu) (net 66)) (segment (start 237.73 73.0502) (end 238.9551 71.8251) (width 0.254) (layer F.Cu) (net 66)) (segment (start 237.73 77.9) (end 237.73 73.0502) (width 0.254) (layer F.Cu) (net 66)) (segment (start 237.73 70.6) (end 238.9551 71.8251) (width 0.254) (layer F.Cu) (net 66)) (segment (start 238.9551 71.8251) (end 256.5049 71.8251) (width 0.254) (layer F.Cu) (net 66)) (segment (start 224.23 99.8) (end 222.86 98.43) (width 0.254) (layer F.Cu) (net 66)) (segment (start 237.73 99.8) (end 224.23 99.8) (width 0.254) (layer F.Cu) (net 66)) (segment (start 257.73 114.4) (end 257.73 107.1) (width 0.254) (layer B.Cu) (net 67)) (segment (start 239.93 128.78) (end 239.93 131.32) (width 0.254) (layer B.Cu) (net 67)) (segment (start 28.9496 130.2196) (end 27.73 129) (width 0.254) (layer F.Cu) (net 67)) (segment (start 36.5104 130.2196) (end 28.9496 130.2196) (width 0.254) (layer F.Cu) (net 67)) (segment (start 37.73 129) (end 36.5104 130.2196) (width 0.254) (layer F.Cu) (net 67)) (segment (start 225.8905 118.1052) (end 223.8917 118.1052) (width 0.254) (layer B.Cu) (net 67)) (segment (start 236.12 128.3347) (end 225.8905 118.1052) (width 0.254) (layer B.Cu) (net 67)) (segment (start 236.12 131.736) (end 236.12 128.3347) (width 0.254) (layer B.Cu) (net 67)) (segment (start 236.896 132.512) (end 236.12 131.736) (width 0.254) (layer B.Cu) (net 67)) (segment (start 238.738 132.512) (end 236.896 132.512) (width 0.254) (layer B.Cu) (net 67)) (segment (start 239.93 131.32) (end 238.738 132.512) (width 0.254) (layer B.Cu) (net 67)) (segment (start 58.9496 127.7804) (end 57.73 129) (width 0.254) (layer F.Cu) (net 67)) (segment (start 66.5104 127.7804) (end 58.9496 127.7804) (width 0.254) (layer F.Cu) (net 67)) (segment (start 67.73 129) (end 66.5104 127.7804) (width 0.254) (layer F.Cu) (net 67)) (segment (start 48.9597 127.7703) (end 47.73 129) (width 0.254) (layer F.Cu) (net 67)) (segment (start 56.5003 127.7703) (end 48.9597 127.7703) (width 0.254) (layer F.Cu) (net 67)) (segment (start 57.73 129) (end 56.5003 127.7703) (width 0.254) (layer F.Cu) (net 67)) (segment (start 39.0049 130.2749) (end 37.73 129) (width 0.254) (layer B.Cu) (net 67)) (segment (start 46.4551 130.2749) (end 39.0049 130.2749) (width 0.254) (layer B.Cu) (net 67)) (segment (start 47.73 129) (end 46.4551 130.2749) (width 0.254) (layer B.Cu) (net 67)) (segment (start 69.4579 130.7279) (end 67.73 129) (width 0.254) (layer B.Cu) (net 67)) (segment (start 71.446 130.7279) (end 69.4579 130.7279) (width 0.254) (layer B.Cu) (net 67)) (segment (start 71.7637 130.4102) (end 71.446 130.7279) (width 0.254) (layer B.Cu) (net 67)) (segment (start 85.2546 130.4102) (end 71.7637 130.4102) (width 0.254) (layer B.Cu) (net 67)) (segment (start 86.1276 131.2832) (end 85.2546 130.4102) (width 0.254) (layer B.Cu) (net 67)) (segment (start 91.8681 131.2832) (end 86.1276 131.2832) (width 0.254) (layer B.Cu) (net 67)) (segment (start 97.5183 125.633) (end 91.8681 131.2832) (width 0.254) (layer B.Cu) (net 67)) (segment (start 161.6142 125.633) (end 97.5183 125.633) (width 0.254) (layer B.Cu) (net 67)) (segment (start 170.0493 117.1979) (end 161.6142 125.633) (width 0.254) (layer B.Cu) (net 67)) (segment (start 170.0493 117.1731) (end 170.0493 117.1979) (width 0.254) (layer B.Cu) (net 67)) (segment (start 170.5331 116.6893) (end 170.0493 117.1731) (width 0.254) (layer B.Cu) (net 67)) (segment (start 173.049 116.6893) (end 170.5331 116.6893) (width 0.254) (layer B.Cu) (net 67)) (segment (start 177.131 112.6073) (end 173.049 116.6893) (width 0.254) (layer B.Cu) (net 67)) (segment (start 214.4442 112.6073) (end 177.131 112.6073) (width 0.254) (layer B.Cu) (net 67)) (segment (start 219.9421 118.1052) (end 214.4442 112.6073) (width 0.254) (layer B.Cu) (net 67)) (segment (start 223.8917 118.1052) (end 219.9421 118.1052) (width 0.254) (layer B.Cu) (net 67)) (segment (start 223.8917 115.2401) (end 223.8917 118.1052) (width 0.254) (layer B.Cu) (net 67)) (segment (start 221.7524 113.1008) (end 223.8917 115.2401) (width 0.254) (layer B.Cu) (net 67)) (segment (start 221.7524 110.6961) (end 221.7524 113.1008) (width 0.254) (layer B.Cu) (net 67)) (segment (start 222.5885 109.86) (end 221.7524 110.6961) (width 0.254) (layer B.Cu) (net 67)) (segment (start 223.122 109.86) (end 222.5885 109.86) (width 0.254) (layer B.Cu) (net 67)) (segment (start 223.9609 109.0211) (end 223.122 109.86) (width 0.254) (layer B.Cu) (net 67)) (segment (start 223.9609 96.9909) (end 223.9609 109.0211) (width 0.254) (layer B.Cu) (net 67)) (segment (start 222.86 95.89) (end 223.9609 96.9909) (width 0.254) (layer B.Cu) (net 67)) (segment (start 257.73 107.1) (end 257.73 99.8) (width 0.254) (layer F.Cu) (net 67)) (segment (start 277.73 70.6) (end 277.73 77.9) (width 0.254) (layer B.Cu) (net 67)) (segment (start 277.73 77.9) (end 277.73 85.2) (width 0.254) (layer F.Cu) (net 67)) (segment (start 272.33 85.2) (end 257.73 99.8) (width 0.254) (layer F.Cu) (net 67)) (segment (start 277.73 85.2) (end 272.33 85.2) (width 0.254) (layer F.Cu) (net 67)) (segment (start 257.73 114.4) (end 257.73 121.7) (width 0.254) (layer B.Cu) (net 67)) (segment (start 239 102.97) (end 257.73 121.7) (width 0.254) (layer F.Cu) (net 67)) (segment (start 239 99.336) (end 239 102.97) (width 0.254) (layer F.Cu) (net 67)) (segment (start 235.554 95.89) (end 239 99.336) (width 0.254) (layer F.Cu) (net 67)) (segment (start 222.86 95.89) (end 235.554 95.89) (width 0.254) (layer F.Cu) (net 67)) (segment (start 66.5104 69.3804) (end 67.73 70.6) (width 0.254) (layer B.Cu) (net 68)) (segment (start 58.9496 69.3804) (end 66.5104 69.3804) (width 0.254) (layer B.Cu) (net 68)) (segment (start 57.73 70.6) (end 58.9496 69.3804) (width 0.254) (layer B.Cu) (net 68)) (segment (start 68.9496 69.3804) (end 67.73 70.6) (width 0.254) (layer B.Cu) (net 68)) (segment (start 76.5104 69.3804) (end 68.9496 69.3804) (width 0.254) (layer B.Cu) (net 68)) (segment (start 77.73 70.6) (end 76.5104 69.3804) (width 0.254) (layer B.Cu) (net 68)) (segment (start 28.9976 69.3324) (end 27.73 70.6) (width 0.254) (layer B.Cu) (net 68)) (segment (start 36.4624 69.3324) (end 28.9976 69.3324) (width 0.254) (layer B.Cu) (net 68)) (segment (start 37.73 70.6) (end 36.4624 69.3324) (width 0.254) (layer B.Cu) (net 68)) (segment (start 48.9976 69.3324) (end 47.73 70.6) (width 0.254) (layer B.Cu) (net 68)) (segment (start 56.4624 69.3324) (end 48.9976 69.3324) (width 0.254) (layer B.Cu) (net 68)) (segment (start 57.73 70.6) (end 56.4624 69.3324) (width 0.254) (layer B.Cu) (net 68)) (segment (start 38.9976 69.3324) (end 37.73 70.6) (width 0.254) (layer B.Cu) (net 68)) (segment (start 46.4624 69.3324) (end 38.9976 69.3324) (width 0.254) (layer B.Cu) (net 68)) (segment (start 47.73 70.6) (end 46.4624 69.3324) (width 0.254) (layer B.Cu) (net 68)) (segment (start 81.5189 72.3375) (end 81.5189 69.408) (width 0.254) (layer B.Cu) (net 68)) (segment (start 59.3711 94.4853) (end 81.5189 72.3375) (width 0.254) (layer B.Cu) (net 68)) (segment (start 59.3711 99.6096) (end 59.3711 94.4853) (width 0.254) (layer B.Cu) (net 68)) (segment (start 62.0804 102.3189) (end 59.3711 99.6096) (width 0.254) (layer B.Cu) (net 68)) (segment (start 65.6489 102.3189) (end 62.0804 102.3189) (width 0.254) (layer B.Cu) (net 68)) (segment (start 77.73 114.4) (end 65.6489 102.3189) (width 0.254) (layer B.Cu) (net 68)) (segment (start 78.9515 69.3785) (end 77.73 70.6) (width 0.254) (layer B.Cu) (net 68)) (segment (start 81.4894 69.3785) (end 78.9515 69.3785) (width 0.254) (layer B.Cu) (net 68)) (segment (start 81.5189 69.408) (end 81.4894 69.3785) (width 0.254) (layer B.Cu) (net 68)) (segment (start 242.47 131.32) (end 242.47 128.78) (width 0.254) (layer B.Cu) (net 68)) (segment (start 223.3435 89.7061) (end 221.7649 89.7061) (width 0.254) (layer B.Cu) (net 68)) (segment (start 236.5104 102.873) (end 223.3435 89.7061) (width 0.254) (layer B.Cu) (net 68)) (segment (start 236.5104 122.8204) (end 236.5104 102.873) (width 0.254) (layer B.Cu) (net 68)) (segment (start 242.47 128.78) (end 236.5104 122.8204) (width 0.254) (layer B.Cu) (net 68)) (segment (start 221.7649 89.5881) (end 221.7649 89.7061) (width 0.254) (layer B.Cu) (net 68)) (segment (start 199.9705 67.7937) (end 221.7649 89.5881) (width 0.254) (layer B.Cu) (net 68)) (segment (start 83.1332 67.7937) (end 199.9705 67.7937) (width 0.254) (layer B.Cu) (net 68)) (segment (start 81.5189 69.408) (end 83.1332 67.7937) (width 0.254) (layer B.Cu) (net 68)) (segment (start 221.7649 92.2549) (end 222.86 93.35) (width 0.254) (layer B.Cu) (net 68)) (segment (start 221.7649 89.7061) (end 221.7649 92.2549) (width 0.254) (layer B.Cu) (net 68)) (segment (start 119 159.5) (end 109 159.5) (width 0.381) (layer F.Cu) (net 69)) (segment (start 109 159.5) (end 99 159.5) (width 0.381) (layer F.Cu) (net 69)) (segment (start 99 159.5) (end 89 159.5) (width 0.381) (layer F.Cu) (net 69)) (segment (start 119 159.5) (end 129 159.5) (width 0.381) (layer F.Cu) (net 69)) (segment (start 129 159.5) (end 139 159.5) (width 0.381) (layer F.Cu) (net 69)) (segment (start 139 159.5) (end 149 159.5) (width 0.381) (layer F.Cu) (net 69)) (segment (start 169 159.5) (end 179 159.5) (width 0.381) (layer F.Cu) (net 69)) (segment (start 179 159.5) (end 189 159.5) (width 0.381) (layer F.Cu) (net 69)) (segment (start 189 159.5) (end 199 159.5) (width 0.381) (layer F.Cu) (net 69)) (segment (start 149 159.5) (end 159 159.5) (width 0.381) (layer F.Cu) (net 69)) (segment (start 159 159.5) (end 169 159.5) (width 0.381) (layer F.Cu) (net 69)) (segment (start 83.6994 134.0694) (end 82.71 133.08) (width 0.381) (layer B.Cu) (net 69)) (segment (start 83.6994 152.4846) (end 83.6994 134.0694) (width 0.381) (layer B.Cu) (net 69)) (segment (start 89 157.7852) (end 83.6994 152.4846) (width 0.381) (layer B.Cu) (net 69)) (segment (start 89 159.5) (end 89 157.7852) (width 0.381) (layer B.Cu) (net 69)) (segment (start 39 159.5) (end 49 159.5) (width 0.381) (layer F.Cu) (net 70)) (segment (start 59 159.5) (end 69 159.5) (width 0.381) (layer F.Cu) (net 70)) (segment (start 29 159.5) (end 39 159.5) (width 0.381) (layer F.Cu) (net 70)) (segment (start 19.2122 133.7722) (end 14.94 129.5) (width 0.381) (layer B.Cu) (net 70)) (segment (start 19.2122 135.5578) (end 19.2122 133.7722) (width 0.381) (layer B.Cu) (net 70)) (segment (start 24.5925 140.9381) (end 19.2122 135.5578) (width 0.381) (layer B.Cu) (net 70)) (segment (start 24.5925 153.3777) (end 24.5925 140.9381) (width 0.381) (layer B.Cu) (net 70)) (segment (start 29 157.7852) (end 24.5925 153.3777) (width 0.381) (layer B.Cu) (net 70)) (segment (start 29 159.5) (end 29 157.7852) (width 0.381) (layer B.Cu) (net 70)) (segment (start 245.01 128.78) (end 245.01 131.32) (width 0.381) (layer B.Cu) (net 70)) (segment (start 143.5019 161.2148) (end 79 161.2148) (width 0.381) (layer B.Cu) (net 70)) (segment (start 149.0818 155.6349) (end 143.5019 161.2148) (width 0.381) (layer B.Cu) (net 70)) (segment (start 191.0458 155.6349) (end 149.0818 155.6349) (width 0.381) (layer B.Cu) (net 70)) (segment (start 194 152.6807) (end 191.0458 155.6349) (width 0.381) (layer B.Cu) (net 70)) (segment (start 194 143.03) (end 194 152.6807) (width 0.381) (layer B.Cu) (net 70)) (segment (start 202.5437 134.4863) (end 194 143.03) (width 0.381) (layer B.Cu) (net 70)) (segment (start 211.4032 134.4863) (end 202.5437 134.4863) (width 0.381) (layer B.Cu) (net 70)) (segment (start 213.9587 131.9308) (end 211.4032 134.4863) (width 0.381) (layer B.Cu) (net 70)) (segment (start 223.9137 131.9308) (end 213.9587 131.9308) (width 0.381) (layer B.Cu) (net 70)) (segment (start 225.0709 133.088) (end 223.9137 131.9308) (width 0.381) (layer B.Cu) (net 70)) (segment (start 243.242 133.088) (end 225.0709 133.088) (width 0.381) (layer B.Cu) (net 70)) (segment (start 245.01 131.32) (end 243.242 133.088) (width 0.381) (layer B.Cu) (net 70)) (segment (start 59 159.5) (end 49 159.5) (width 0.381) (layer B.Cu) (net 70)) (segment (start 79 159.5) (end 79 160.3574) (width 0.381) (layer B.Cu) (net 70)) (segment (start 79 160.3574) (end 79 161.2148) (width 0.381) (layer B.Cu) (net 70)) (segment (start 72.8422 160.3574) (end 71.9848 159.5) (width 0.381) (layer B.Cu) (net 70)) (segment (start 79 160.3574) (end 72.8422 160.3574) (width 0.381) (layer B.Cu) (net 70)) (segment (start 69 159.5) (end 71.9848 159.5) (width 0.381) (layer B.Cu) (net 70)) (segment (start 219 159.5) (end 209 159.5) (width 0.381) (layer F.Cu) (net 71)) (segment (start 229 159.5) (end 229 157.7852) (width 0.381) (layer B.Cu) (net 71)) (segment (start 219 159.5) (end 219 157.7852) (width 0.381) (layer B.Cu) (net 71)) (segment (start 224.0804 152.8656) (end 223.9196 152.8656) (width 0.381) (layer B.Cu) (net 71)) (segment (start 229 157.7852) (end 224.0804 152.8656) (width 0.381) (layer B.Cu) (net 71)) (segment (start 223.9196 134.5896) (end 223.9196 152.8656) (width 0.381) (layer B.Cu) (net 71)) (segment (start 222.41 133.08) (end 223.9196 134.5896) (width 0.381) (layer B.Cu) (net 71)) (segment (start 223.9196 152.8656) (end 219 157.7852) (width 0.381) (layer B.Cu) (net 71)) (segment (start 229 159.5) (end 239 159.5) (width 0.381) (layer F.Cu) (net 71)) (segment (start 259 159.5) (end 269 159.5) (width 0.381) (layer F.Cu) (net 71)) (segment (start 269 159.5) (end 279 159.5) (width 0.381) (layer F.Cu) (net 71)) (segment (start 239 159.5) (end 249 159.5) (width 0.381) (layer F.Cu) (net 71)) (segment (start 249 159.5) (end 259 159.5) (width 0.381) (layer F.Cu) (net 71)) (via (at 46.7355 117.1664) (size 0.889) (layers F.Cu B.Cu) (net 72)) (segment (start 215.24 111.13) (end 214.1602 111.13) (width 0.254) (layer F.Cu) (net 72)) (segment (start 43.68 124) (end 42.41 125.27) (width 0.254) (layer B.Cu) (net 72)) (segment (start 43.68 120.2219) (end 43.68 124) (width 0.254) (layer B.Cu) (net 72)) (segment (start 46.7355 117.1664) (end 43.68 120.2219) (width 0.254) (layer B.Cu) (net 72)) (segment (start 205.3363 119.9539) (end 214.1602 111.13) (width 0.254) (layer F.Cu) (net 72)) (segment (start 163.7895 119.9539) (end 205.3363 119.9539) (width 0.254) (layer F.Cu) (net 72)) (segment (start 163.2898 119.4542) (end 163.7895 119.9539) (width 0.254) (layer F.Cu) (net 72)) (segment (start 75.686 119.4542) (end 163.2898 119.4542) (width 0.254) (layer F.Cu) (net 72)) (segment (start 75.0777 120.0625) (end 75.686 119.4542) (width 0.254) (layer F.Cu) (net 72)) (segment (start 73.1045 120.0625) (end 75.0777 120.0625) (width 0.254) (layer F.Cu) (net 72)) (segment (start 70.7115 117.6695) (end 73.1045 120.0625) (width 0.254) (layer F.Cu) (net 72)) (segment (start 70.7115 117.4112) (end 70.7115 117.6695) (width 0.254) (layer F.Cu) (net 72)) (segment (start 67.3533 114.053) (end 70.7115 117.4112) (width 0.254) (layer F.Cu) (net 72)) (segment (start 49.8489 114.053) (end 67.3533 114.053) (width 0.254) (layer F.Cu) (net 72)) (segment (start 46.7355 117.1664) (end 49.8489 114.053) (width 0.254) (layer F.Cu) (net 72)) (via (at 46.7255 113.9784) (size 0.889) (layers F.Cu B.Cu) (net 73)) (segment (start 41.14 119.5639) (end 46.7255 113.9784) (width 0.254) (layer B.Cu) (net 73)) (segment (start 41.14 124) (end 41.14 119.5639) (width 0.254) (layer B.Cu) (net 73)) (segment (start 39.87 125.27) (end 41.14 124) (width 0.254) (layer B.Cu) (net 73)) (segment (start 204.396 119.434) (end 215.24 108.59) (width 0.254) (layer F.Cu) (net 73)) (segment (start 164.8008 119.434) (end 204.396 119.434) (width 0.254) (layer F.Cu) (net 73)) (segment (start 164.3127 118.9459) (end 164.8008 119.434) (width 0.254) (layer F.Cu) (net 73)) (segment (start 75.4755 118.9459) (end 164.3127 118.9459) (width 0.254) (layer F.Cu) (net 73)) (segment (start 74.8672 119.5542) (end 75.4755 118.9459) (width 0.254) (layer F.Cu) (net 73)) (segment (start 73.315 119.5542) (end 74.8672 119.5542) (width 0.254) (layer F.Cu) (net 73)) (segment (start 71.2198 117.459) (end 73.315 119.5542) (width 0.254) (layer F.Cu) (net 73)) (segment (start 71.2198 117.2007) (end 71.2198 117.459) (width 0.254) (layer F.Cu) (net 73)) (segment (start 67.5638 113.5447) (end 71.2198 117.2007) (width 0.254) (layer F.Cu) (net 73)) (segment (start 47.1592 113.5447) (end 67.5638 113.5447) (width 0.254) (layer F.Cu) (net 73)) (segment (start 46.7255 113.9784) (end 47.1592 113.5447) (width 0.254) (layer F.Cu) (net 73)) (via (at 74.3516 118.7284) (size 0.889) (layers F.Cu B.Cu) (net 74)) (segment (start 70.35 122.73) (end 74.3516 118.7284) (width 0.254) (layer B.Cu) (net 74)) (segment (start 74.6581 118.4219) (end 74.3516 118.7284) (width 0.254) (layer F.Cu) (net 74)) (segment (start 165.8133 118.4219) (end 74.6581 118.4219) (width 0.254) (layer F.Cu) (net 74)) (segment (start 166.279 118.8876) (end 165.8133 118.4219) (width 0.254) (layer F.Cu) (net 74)) (segment (start 189.6176 118.8876) (end 166.279 118.8876) (width 0.254) (layer F.Cu) (net 74)) (segment (start 202.4552 106.05) (end 189.6176 118.8876) (width 0.254) (layer F.Cu) (net 74)) (segment (start 215.24 106.05) (end 202.4552 106.05) (width 0.254) (layer F.Cu) (net 74)) (via (at 73.5094 117.8863) (size 0.889) (layers F.Cu B.Cu) (net 75)) (segment (start 69.189 122.2067) (end 73.5094 117.8863) (width 0.254) (layer B.Cu) (net 75)) (segment (start 69.189 124.109) (end 69.189 122.2067) (width 0.254) (layer B.Cu) (net 75)) (segment (start 70.35 125.27) (end 69.189 124.109) (width 0.254) (layer B.Cu) (net 75)) (segment (start 166.7756 117.8863) (end 73.5094 117.8863) (width 0.254) (layer F.Cu) (net 75)) (segment (start 167.2685 118.3792) (end 166.7756 117.8863) (width 0.254) (layer F.Cu) (net 75)) (segment (start 188.0154 118.3792) (end 167.2685 118.3792) (width 0.254) (layer F.Cu) (net 75)) (segment (start 202.8846 103.51) (end 188.0154 118.3792) (width 0.254) (layer F.Cu) (net 75)) (segment (start 215.24 103.51) (end 202.8846 103.51) (width 0.254) (layer F.Cu) (net 75)) (via (at 72.0456 117.117) (size 0.889) (layers F.Cu B.Cu) (net 76)) (segment (start 71.7875 117.117) (end 72.0456 117.117) (width 0.254) (layer B.Cu) (net 76)) (segment (start 66.6329 122.2716) (end 71.7875 117.117) (width 0.254) (layer B.Cu) (net 76)) (segment (start 66.6329 124.0929) (end 66.6329 122.2716) (width 0.254) (layer B.Cu) (net 76)) (segment (start 67.81 125.27) (end 66.6329 124.0929) (width 0.254) (layer B.Cu) (net 76)) (segment (start 212.2913 98.0213) (end 215.24 100.97) (width 0.254) (layer F.Cu) (net 76)) (segment (start 166.9503 98.0213) (end 212.2913 98.0213) (width 0.254) (layer F.Cu) (net 76)) (segment (start 152.2996 112.672) (end 166.9503 98.0213) (width 0.254) (layer F.Cu) (net 76)) (segment (start 77.7335 112.672) (end 152.2996 112.672) (width 0.254) (layer F.Cu) (net 76)) (segment (start 74.3019 116.1036) (end 77.7335 112.672) (width 0.254) (layer F.Cu) (net 76)) (segment (start 74.3019 116.256) (end 74.3019 116.1036) (width 0.254) (layer F.Cu) (net 76)) (segment (start 73.5204 117.0375) (end 74.3019 116.256) (width 0.254) (layer F.Cu) (net 76)) (segment (start 72.1251 117.0375) (end 73.5204 117.0375) (width 0.254) (layer F.Cu) (net 76)) (segment (start 72.0456 117.117) (end 72.1251 117.0375) (width 0.254) (layer F.Cu) (net 76)) (segment (start 215.24 99.2311) (end 215.24 98.43) (width 0.254) (layer B.Cu) (net 77)) (segment (start 203.3834 111.0877) (end 215.24 99.2311) (width 0.254) (layer B.Cu) (net 77)) (segment (start 176.5976 111.0877) (end 203.3834 111.0877) (width 0.254) (layer B.Cu) (net 77)) (segment (start 171.5043 116.181) (end 176.5976 111.0877) (width 0.254) (layer B.Cu) (net 77)) (segment (start 170.3226 116.181) (end 171.5043 116.181) (width 0.254) (layer B.Cu) (net 77)) (segment (start 169.541 116.9626) (end 170.3226 116.181) (width 0.254) (layer B.Cu) (net 77)) (segment (start 169.541 116.9874) (end 169.541 116.9626) (width 0.254) (layer B.Cu) (net 77)) (segment (start 161.7612 124.7672) (end 169.541 116.9874) (width 0.254) (layer B.Cu) (net 77)) (segment (start 97.6652 124.7672) (end 161.7612 124.7672) (width 0.254) (layer B.Cu) (net 77)) (segment (start 91.6673 130.7651) (end 97.6652 124.7672) (width 0.254) (layer B.Cu) (net 77)) (segment (start 86.3283 130.7651) (end 91.6673 130.7651) (width 0.254) (layer B.Cu) (net 77)) (segment (start 85.4209 129.8577) (end 86.3283 130.7651) (width 0.254) (layer B.Cu) (net 77)) (segment (start 71.3431 129.8577) (end 85.4209 129.8577) (width 0.254) (layer B.Cu) (net 77)) (segment (start 70.9812 130.2196) (end 71.3431 129.8577) (width 0.254) (layer B.Cu) (net 77)) (segment (start 69.7306 130.2196) (end 70.9812 130.2196) (width 0.254) (layer B.Cu) (net 77)) (segment (start 68.9496 129.4386) (end 69.7306 130.2196) (width 0.254) (layer B.Cu) (net 77)) (segment (start 68.9496 128.4343) (end 68.9496 129.4386) (width 0.254) (layer B.Cu) (net 77)) (segment (start 68.1614 127.6461) (end 68.9496 128.4343) (width 0.254) (layer B.Cu) (net 77)) (segment (start 65.1061 127.6461) (end 68.1614 127.6461) (width 0.254) (layer B.Cu) (net 77)) (segment (start 62.73 125.27) (end 65.1061 127.6461) (width 0.254) (layer B.Cu) (net 77)) (segment (start 166 95.89) (end 215.24 95.89) (width 0.254) (layer F.Cu) (net 78)) (segment (start 160.8205 101.0695) (end 166 95.89) (width 0.254) (layer F.Cu) (net 78)) (segment (start 143.4703 101.0695) (end 160.8205 101.0695) (width 0.254) (layer F.Cu) (net 78)) (segment (start 140.9812 98.5804) (end 143.4703 101.0695) (width 0.254) (layer F.Cu) (net 78)) (segment (start 139.7115 98.5804) (end 140.9812 98.5804) (width 0.254) (layer F.Cu) (net 78)) (segment (start 138.9496 99.3423) (end 139.7115 98.5804) (width 0.254) (layer F.Cu) (net 78)) (segment (start 138.9496 100.3221) (end 138.9496 99.3423) (width 0.254) (layer F.Cu) (net 78)) (segment (start 128.537 110.7347) (end 138.9496 100.3221) (width 0.254) (layer F.Cu) (net 78)) (segment (start 78.9357 110.7347) (end 128.537 110.7347) (width 0.254) (layer F.Cu) (net 78)) (segment (start 73.7936 115.8768) (end 78.9357 110.7347) (width 0.254) (layer F.Cu) (net 78)) (segment (start 73.7936 116.0455) (end 73.7936 115.8768) (width 0.254) (layer F.Cu) (net 78)) (segment (start 73.3099 116.5292) (end 73.7936 116.0455) (width 0.254) (layer F.Cu) (net 78)) (segment (start 72.6258 116.5292) (end 73.3099 116.5292) (width 0.254) (layer F.Cu) (net 78)) (segment (start 69.0864 112.9898) (end 72.6258 116.5292) (width 0.254) (layer F.Cu) (net 78)) (segment (start 49.8972 112.9898) (end 69.0864 112.9898) (width 0.254) (layer F.Cu) (net 78)) (segment (start 43.95 107.0426) (end 49.8972 112.9898) (width 0.254) (layer F.Cu) (net 78)) (segment (start 43.95 106.4301) (end 43.95 107.0426) (width 0.254) (layer F.Cu) (net 78)) (segment (start 43.1391 105.6192) (end 43.95 106.4301) (width 0.254) (layer F.Cu) (net 78)) (segment (start 42.2341 105.6192) (end 43.1391 105.6192) (width 0.254) (layer F.Cu) (net 78)) (segment (start 41.571 106.2823) (end 42.2341 105.6192) (width 0.254) (layer F.Cu) (net 78)) (segment (start 41.571 121.891) (end 41.571 106.2823) (width 0.254) (layer F.Cu) (net 78)) (segment (start 42.41 122.73) (end 41.571 121.891) (width 0.254) (layer F.Cu) (net 78)) (via (at 72.9678 115.7034) (size 0.889) (layers F.Cu B.Cu) (net 79)) (segment (start 85.9 102.7712) (end 72.9678 115.7034) (width 0.254) (layer F.Cu) (net 79)) (segment (start 100.8346 102.7712) (end 85.9 102.7712) (width 0.254) (layer F.Cu) (net 79)) (segment (start 110.2558 93.35) (end 100.8346 102.7712) (width 0.254) (layer F.Cu) (net 79)) (segment (start 215.24 93.35) (end 110.2558 93.35) (width 0.254) (layer F.Cu) (net 79)) (segment (start 75.1941 120.4259) (end 72.89 122.73) (width 0.254) (layer B.Cu) (net 79)) (segment (start 75.1941 117.9297) (end 75.1941 120.4259) (width 0.254) (layer B.Cu) (net 79)) (segment (start 72.9678 115.7034) (end 75.1941 117.9297) (width 0.254) (layer B.Cu) (net 79)) (zone (net 0) (net_name "") (layer B.Cu) (tstamp 554E4CD1) (hatch edge 0.508) (connect_pads (clearance 0.508)) (min_thickness 0.254) (keepout (tracks not_allowed) (vias not_allowed) (copperpour allowed)) (fill (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508)) (polygon (pts (xy 288 140) (xy 284 140) (xy 284 156) (xy 288 156) ) ) ) (zone (net 0) (net_name "") (layer F.Cu) (tstamp 554E4CD1) (hatch edge 0.508) (connect_pads (clearance 0.508)) (min_thickness 0.254) (keepout (tracks not_allowed) (vias not_allowed) (copperpour allowed)) (fill (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508)) (polygon (pts (xy 288 140) (xy 284 140) (xy 284 156) (xy 288 156) ) ) ) ) |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | update=17/05/2015 11:44:30 version=1 last_client=eeschema [cvpcb] version=1 NetIExt=net [cvpcb/libraries] EquName1=devcms [pcbnew] version=1 LastNetListRead= UseCmpFile=1 PadDrill=0.600000000000 PadDrillOvalY=0.600000000000 PadSizeH=1.500000000000 PadSizeV=1.500000000000 PcbTextSizeV=1.500000000000 PcbTextSizeH=1.500000000000 PcbTextThickness=0.300000000000 ModuleTextSizeV=1.000000000000 ModuleTextSizeH=1.000000000000 ModuleTextSizeThickness=0.150000000000 SolderMaskClearance=0.000000000000 SolderMaskMinWidth=0.000000000000 DrawSegmentWidth=0.200000000000 BoardOutlineThickness=0.100000000000 ModuleOutlineThickness=0.150000000000 [pcbnew/libraries] LibDir=customlibraries LibName1=sockets LibName2=connect LibName3=discret LibName4=pin_array LibName5=divers LibName6=smd_capacitors LibName7=smd_resistors LibName8=smd_crystal&oscillator LibName9=smd_dil LibName10=smd_transistors LibName11=libcms LibName12=display LibName13=pdp8footprintlib2 LibName14=led LibName15=dip_sockets LibName16=pga_sockets LibName17=valves [general] version=1 [eeschema] version=1 LibDir=customlibraries NetFmtName= RptD_X=0 RptD_Y=100 RptLab=1 LabSize=60 [eeschema/libraries] LibName1=power LibName2=device LibName3=transistors LibName4=conn LibName5=linear LibName6=regul LibName7=74xx LibName8=cmos4000 LibName9=adc-dac LibName10=memory LibName11=xilinx LibName12=special LibName13=microcontrollers LibName14=dsp LibName15=microchip LibName16=analog_switches LibName17=motorola LibName18=texas LibName19=intel LibName20=audio LibName21=interface LibName22=digital-audio LibName23=philips LibName24=display LibName25=cypress LibName26=siliconi LibName27=opto LibName28=atmel LibName29=contrib LibName30=valves LibName31=pdp8_library |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | (rules PCB PDP8 (snap_angle fortyfive_degree ) (autoroute_settings (fanout off) (autoroute on) (postroute on) (vias on) (via_costs 50) (plane_via_costs 5) (start_ripup_costs 100) (start_pass_no 19938) (layer_rule F.Cu (active on) (preferred_direction horizontal) (preferred_direction_trace_costs 1.0) (against_preferred_direction_trace_costs 3.9) ) (layer_rule B.Cu (active on) (preferred_direction vertical) (preferred_direction_trace_costs 1.0) (against_preferred_direction_trace_costs 1.3) ) ) (rule (width 254.0) (clear 254.2) (clear 127.0 (type smd_to_turn_gap)) (clear 63.6 (type smd_smd)) ) (padstack "Via[0-1]_889:635_um" (shape (circle F.Cu 889.0 0.0 0.0) ) (shape (circle B.Cu 889.0 0.0 0.0) ) (attach off) ) (padstack "Via[0-1]_889:0_um" (shape (circle F.Cu 889.0 0.0 0.0) ) (shape (circle B.Cu 889.0 0.0 0.0) ) (attach off) ) (via "Via[0-1]_889:635_um" "Via[0-1]_889:635_um" default ) (via "Via[0-1]_889:0_um" "Via[0-1]_889:0_um" default ) (via "Via[0-1]_889:635_um-kicad_default" "Via[0-1]_889:635_um" "kicad_default" ) (via "Via[0-1]_889:0_um-kicad_default" "Via[0-1]_889:0_um" "kicad_default" ) (via_rule default "Via[0-1]_889:635_um" ) (via_rule "kicad_default" "Via[0-1]_889:635_um-kicad_default" ) (class default (clearance_class default) (via_rule default) (rule (width 254.0) ) (circuit (use_layer F.Cu B.Cu) ) ) (class "kicad_default" "N-0000023" "N-0000028" "N-0000029" "N-0000035" "N-0000039" "N-0000040" "N-0000041" "N-0000042" "N-0000043" "N-0000046" "N-0000048" "N-0000049" "N-0000050" "N-0000053" "N-0000054" "N-0000055" "N-0000056" "N-0000057" "N-0000059" "N-0000060" "N-0000061" "N-0000062" "N-0000063" "N-0000065" "N-0000066" "N-0000067" "N-0000068" "N-0000069" "N-0000070" "N-0000071" "N-0000072" "N-0000073" "N-0000074" "N-0000079" "N-0000085" "N-0000086" "N-0000087" "N-0000088" "N-0000089" "N-0000090" "N-0000091" "N-0000092" "N-0000093" RX "SPARE_IO" TX col1 col10 col11 col12 col1a col2 col2a col3 col4 col5 col6 col7 col8 col9 led1 led2 led3 led4 led5 led6 led7 led8 xled1 xled2 xled3 xled4 xled5 xled6 xled7 xled8 (clearance_class "kicad_default") (via_rule kicad_default) (rule (width 254.0) ) (circuit (use_layer F.Cu B.Cu) ) ) (class fat +3.3V +5V GND row1 row2 row3 (clearance_class default) (via_rule default) (rule (width 381.0) ) (circuit (use_layer F.Cu B.Cu) ) ) ) |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 | EESchema Schematic File Version 2 LIBS:power LIBS:device LIBS:transistors LIBS:conn LIBS:linear LIBS:regul LIBS:74xx LIBS:cmos4000 LIBS:adc-dac LIBS:memory LIBS:xilinx LIBS:special LIBS:microcontrollers LIBS:dsp LIBS:microchip LIBS:analog_switches LIBS:motorola LIBS:texas LIBS:intel LIBS:audio LIBS:interface LIBS:digital-audio LIBS:philips LIBS:display LIBS:cypress LIBS:siliconi LIBS:opto LIBS:atmel LIBS:contrib LIBS:valves LIBS:pdp8_library LIBS:PDP8-cache EELAYER 27 0 EELAYER END $Descr A4 11693 8268 encoding utf-8 Sheet 1 1 Title "" Date "11 may 2015" Rev "" Comp "" Comment1 "" Comment2 "" Comment3 "" Comment4 "" $EndDescr $Comp L LED DPC1 U 1 1 548EF34A P 5500 900 F 0 "DPC1" H 5500 1000 50 0000 C CNN F 1 "LED" H 5500 800 50 0000 C CNN F 2 "~" H 5500 900 60 0000 C CNN F 3 "~" H 5500 900 60 0000 C CNN 1 5500 900 0 1 1 0 $EndComp $Comp L LED DPC2 U 1 1 548EF399 P 5800 900 F 0 "DPC2" H 5800 1000 50 0000 C CNN F 1 "LED" H 5800 800 50 0000 C CNN F 2 "~" H 5800 900 60 0000 C CNN F 3 "~" H 5800 900 60 0000 C CNN 1 5800 900 0 1 1 0 $EndComp $Comp L LED DPC3 U 1 1 548EF3AC P 6100 900 F 0 "DPC3" H 6100 1000 50 0000 C CNN F 1 "LED" H 6100 800 50 0000 C CNN F 2 "~" H 6100 900 60 0000 C CNN F 3 "~" H 6100 900 60 0000 C CNN 1 6100 900 0 1 1 0 $EndComp $Comp L LED DPC4 U 1 1 548EF3B2 P 6400 900 F 0 "DPC4" H 6400 1000 50 0000 C CNN F 1 "LED" H 6400 800 50 0000 C CNN F 2 "~" H 6400 900 60 0000 C CNN F 3 "~" H 6400 900 60 0000 C CNN 1 6400 900 0 1 1 0 $EndComp $Comp L LED DPC5 U 1 1 548EF3B8 P 6700 900 F 0 "DPC5" H 6700 1000 50 0000 C CNN F 1 "LED" H 6700 800 50 0000 C CNN F 2 "~" H 6700 900 60 0000 C CNN F 3 "~" H 6700 900 60 0000 C CNN 1 6700 900 0 1 1 0 $EndComp $Comp L LED DPC6 U 1 1 548EF3BE P 7000 900 F 0 "DPC6" H 7000 1000 50 0000 C CNN F 1 "LED" H 7000 800 50 0000 C CNN F 2 "~" H 7000 900 60 0000 C CNN F 3 "~" H 7000 900 60 0000 C CNN 1 7000 900 0 1 1 0 $EndComp $Comp L LED DPC7 U 1 1 548EF3C4 P 7300 900 F 0 "DPC7" H 7300 1000 50 0000 C CNN F 1 "LED" H 7300 800 50 0000 C CNN F 2 "~" H 7300 900 60 0000 C CNN F 3 "~" H 7300 900 60 0000 C CNN 1 7300 900 0 1 1 0 $EndComp $Comp L LED DPC8 U 1 1 548EF3CA P 7600 900 F 0 "DPC8" H 7600 1000 50 0000 C CNN F 1 "LED" H 7600 800 50 0000 C CNN F 2 "~" H 7600 900 60 0000 C CNN F 3 "~" H 7600 900 60 0000 C CNN 1 7600 900 0 1 1 0 $EndComp $Comp L LED DPC9 U 1 1 548EF3D0 P 7900 900 F 0 "DPC9" H 7900 1000 50 0000 C CNN F 1 "LED" H 7900 800 50 0000 C CNN F 2 "~" H 7900 900 60 0000 C CNN F 3 "~" H 7900 900 60 0000 C CNN 1 7900 900 0 1 1 0 $EndComp $Comp L LED DPC10 U 1 1 548EF3D6 P 8200 900 F 0 "DPC10" H 8200 1000 50 0000 C CNN F 1 "LED" H 8200 800 50 0000 C CNN F 2 "~" H 8200 900 60 0000 C CNN F 3 "~" H 8200 900 60 0000 C CNN 1 8200 900 0 1 1 0 $EndComp $Comp L LED DPC11 U 1 1 548EF3DC P 8500 900 F 0 "DPC11" H 8500 1000 50 0000 C CNN F 1 "LED" H 8500 800 50 0000 C CNN F 2 "~" H 8500 900 60 0000 C CNN F 3 "~" H 8500 900 60 0000 C CNN 1 8500 900 0 1 1 0 $EndComp $Comp L LED DPC12 U 1 1 548EF3E2 P 8800 900 F 0 "DPC12" H 8800 1000 50 0000 C CNN F 1 "LED" H 8800 800 50 0000 C CNN F 2 "~" H 8800 900 60 0000 C CNN F 3 "~" H 8800 900 60 0000 C CNN 1 8800 900 0 1 1 0 $EndComp $Comp L LED DMA1 U 1 1 548EF463 P 5500 1550 F 0 "DMA1" H 5500 1650 50 0000 C CNN F 1 "LED" H 5500 1450 50 0000 C CNN F 2 "~" H 5500 1550 60 0000 C CNN F 3 "~" H 5500 1550 60 0000 C CNN 1 5500 1550 0 -1 -1 0 $EndComp $Comp L LED DMA2 U 1 1 548EF47C P 5800 1550 F 0 "DMA2" H 5800 1650 50 0000 C CNN F 1 "LED" H 5800 1450 50 0000 C CNN F 2 "~" H 5800 1550 60 0000 C CNN F 3 "~" H 5800 1550 60 0000 C CNN 1 5800 1550 0 -1 -1 0 $EndComp $Comp L LED DMA3 U 1 1 548EF482 P 6100 1550 F 0 "DMA3" H 6100 1650 50 0000 C CNN F 1 "LED" H 6100 1450 50 0000 C CNN F 2 "~" H 6100 1550 60 0000 C CNN F 3 "~" H 6100 1550 60 0000 C CNN 1 6100 1550 0 -1 -1 0 $EndComp $Comp L LED DMA4 U 1 1 548EF488 P 6400 1550 F 0 "DMA4" H 6400 1650 50 0000 C CNN F 1 "LED" H 6400 1450 50 0000 C CNN F 2 "~" H 6400 1550 60 0000 C CNN F 3 "~" H 6400 1550 60 0000 C CNN 1 6400 1550 0 -1 -1 0 $EndComp $Comp L LED DMA5 U 1 1 548EF48E P 6700 1550 F 0 "DMA5" H 6700 1650 50 0000 C CNN F 1 "LED" H 6700 1450 50 0000 C CNN F 2 "~" H 6700 1550 60 0000 C CNN F 3 "~" H 6700 1550 60 0000 C CNN 1 6700 1550 0 -1 -1 0 $EndComp $Comp L LED DMA6 U 1 1 548EF494 P 7000 1550 F 0 "DMA6" H 7000 1650 50 0000 C CNN F 1 "LED" H 7000 1450 50 0000 C CNN F 2 "~" H 7000 1550 60 0000 C CNN F 3 "~" H 7000 1550 60 0000 C CNN 1 7000 1550 0 -1 -1 0 $EndComp $Comp L LED DMA7 U 1 1 548EF49A P 7300 1550 F 0 "DMA7" H 7300 1650 50 0000 C CNN F 1 "LED" H 7300 1450 50 0000 C CNN F 2 "~" H 7300 1550 60 0000 C CNN F 3 "~" H 7300 1550 60 0000 C CNN 1 7300 1550 0 -1 -1 0 $EndComp $Comp L LED DMA8 U 1 1 548EF4A0 P 7600 1550 F 0 "DMA8" H 7600 1650 50 0000 C CNN F 1 "LED" H 7600 1450 50 0000 C CNN F 2 "~" H 7600 1550 60 0000 C CNN F 3 "~" H 7600 1550 60 0000 C CNN 1 7600 1550 0 -1 -1 0 $EndComp $Comp L LED DMA9 U 1 1 548EF4A6 P 7900 1550 F 0 "DMA9" H 7900 1650 50 0000 C CNN F 1 "LED" H 7900 1450 50 0000 C CNN F 2 "~" H 7900 1550 60 0000 C CNN F 3 "~" H 7900 1550 60 0000 C CNN 1 7900 1550 0 -1 -1 0 $EndComp $Comp L LED DMA10 U 1 1 548EF4AC P 8200 1550 F 0 "DMA10" H 8200 1650 50 0000 C CNN F 1 "LED" H 8200 1450 50 0000 C CNN F 2 "~" H 8200 1550 60 0000 C CNN F 3 "~" H 8200 1550 60 0000 C CNN 1 8200 1550 0 -1 -1 0 $EndComp $Comp L LED DMA11 U 1 1 548EF4B2 P 8500 1550 F 0 "DMA11" H 8500 1650 50 0000 C CNN F 1 "LED" H 8500 1450 50 0000 C CNN F 2 "~" H 8500 1550 60 0000 C CNN F 3 "~" H 8500 1550 60 0000 C CNN 1 8500 1550 0 -1 -1 0 $EndComp $Comp L LED DMA12 U 1 1 548EF4B8 P 8800 1550 F 0 "DMA12" H 8800 1650 50 0000 C CNN F 1 "LED" H 8800 1450 50 0000 C CNN F 2 "~" H 8800 1550 60 0000 C CNN F 3 "~" H 8800 1550 60 0000 C CNN 1 8800 1550 0 -1 -1 0 $EndComp $Comp L LED DMB1 U 1 1 548EF56F P 5500 2200 F 0 "DMB1" H 5500 2300 50 0000 C CNN F 1 "LED" H 5500 2100 50 0000 C CNN F 2 "~" H 5500 2200 60 0000 C CNN F 3 "~" H 5500 2200 60 0000 C CNN 1 5500 2200 0 1 1 0 $EndComp $Comp L LED DMB2 U 1 1 548EF588 P 5800 2200 F 0 "DMB2" H 5800 2300 50 0000 C CNN F 1 "LED" H 5800 2100 50 0000 C CNN F 2 "~" H 5800 2200 60 0000 C CNN F 3 "~" H 5800 2200 60 0000 C CNN 1 5800 2200 0 1 1 0 $EndComp $Comp L LED DMB3 U 1 1 548EF58E P 6100 2200 F 0 "DMB3" H 6100 2300 50 0000 C CNN F 1 "LED" H 6100 2100 50 0000 C CNN F 2 "~" H 6100 2200 60 0000 C CNN F 3 "~" H 6100 2200 60 0000 C CNN 1 6100 2200 0 1 1 0 $EndComp $Comp L LED DMB4 U 1 1 548EF594 P 6400 2200 F 0 "DMB4" H 6400 2300 50 0000 C CNN F 1 "LED" H 6400 2100 50 0000 C CNN F 2 "~" H 6400 2200 60 0000 C CNN F 3 "~" H 6400 2200 60 0000 C CNN 1 6400 2200 0 1 1 0 $EndComp $Comp L LED DMB5 U 1 1 548EF59A P 6700 2200 F 0 "DMB5" H 6700 2300 50 0000 C CNN F 1 "LED" H 6700 2100 50 0000 C CNN F 2 "~" H 6700 2200 60 0000 C CNN F 3 "~" H 6700 2200 60 0000 C CNN 1 6700 2200 0 1 1 0 $EndComp $Comp L LED DMB6 U 1 1 548EF5A0 P 7000 2200 F 0 "DMB6" H 7000 2300 50 0000 C CNN F 1 "LED" H 7000 2100 50 0000 C CNN F 2 "~" H 7000 2200 60 0000 C CNN F 3 "~" H 7000 2200 60 0000 C CNN 1 7000 2200 0 1 1 0 $EndComp $Comp L LED DMB7 U 1 1 548EF5A6 P 7300 2200 F 0 "DMB7" H 7300 2300 50 0000 C CNN F 1 "LED" H 7300 2100 50 0000 C CNN F 2 "~" H 7300 2200 60 0000 C CNN F 3 "~" H 7300 2200 60 0000 C CNN 1 7300 2200 0 1 1 0 $EndComp $Comp L LED DMB8 U 1 1 548EF5AC P 7600 2200 F 0 "DMB8" H 7600 2300 50 0000 C CNN F 1 "LED" H 7600 2100 50 0000 C CNN F 2 "~" H 7600 2200 60 0000 C CNN F 3 "~" H 7600 2200 60 0000 C CNN 1 7600 2200 0 1 1 0 $EndComp $Comp L LED DMB9 U 1 1 548EF5B2 P 7900 2200 F 0 "DMB9" H 7900 2300 50 0000 C CNN F 1 "LED" H 7900 2100 50 0000 C CNN F 2 "~" H 7900 2200 60 0000 C CNN F 3 "~" H 7900 2200 60 0000 C CNN 1 7900 2200 0 1 1 0 $EndComp $Comp L LED DMB10 U 1 1 548EF5B8 P 8200 2200 F 0 "DMB10" H 8200 2300 50 0000 C CNN F 1 "LED" H 8200 2100 50 0000 C CNN F 2 "~" H 8200 2200 60 0000 C CNN F 3 "~" H 8200 2200 60 0000 C CNN 1 8200 2200 0 1 1 0 $EndComp $Comp L LED DMB11 U 1 1 548EF5BE P 8500 2200 F 0 "DMB11" H 8500 2300 50 0000 C CNN F 1 "LED" H 8500 2100 50 0000 C CNN F 2 "~" H 8500 2200 60 0000 C CNN F 3 "~" H 8500 2200 60 0000 C CNN 1 8500 2200 0 1 1 0 $EndComp $Comp L LED DMB12 U 1 1 548EF5C4 P 8800 2200 F 0 "DMB12" H 8800 2300 50 0000 C CNN F 1 "LED" H 8800 2100 50 0000 C CNN F 2 "~" H 8800 2200 60 0000 C CNN F 3 "~" H 8800 2200 60 0000 C CNN 1 8800 2200 0 1 1 0 $EndComp $Comp L LED DAC1 U 1 1 548EF5CC P 5500 2850 F 0 "DAC1" H 5500 2950 50 0000 C CNN F 1 "LED" H 5500 2750 50 0000 C CNN F 2 "~" H 5500 2850 60 0000 C CNN F 3 "~" H 5500 2850 60 0000 C CNN 1 5500 2850 0 -1 -1 0 $EndComp $Comp L LED DAC2 U 1 1 548EF5E5 P 5800 2850 F 0 "DAC2" H 5800 2950 50 0000 C CNN F 1 "LED" H 5800 2750 50 0000 C CNN F 2 "~" H 5800 2850 60 0000 C CNN F 3 "~" H 5800 2850 60 0000 C CNN 1 5800 2850 0 -1 -1 0 $EndComp $Comp L LED DAC3 U 1 1 548EF5EB P 6100 2850 F 0 "DAC3" H 6100 2950 50 0000 C CNN F 1 "LED" H 6100 2750 50 0000 C CNN F 2 "~" H 6100 2850 60 0000 C CNN F 3 "~" H 6100 2850 60 0000 C CNN 1 6100 2850 0 -1 -1 0 $EndComp $Comp L LED DAC4 U 1 1 548EF5F1 P 6400 2850 F 0 "DAC4" H 6400 2950 50 0000 C CNN F 1 "LED" H 6400 2750 50 0000 C CNN F 2 "~" H 6400 2850 60 0000 C CNN F 3 "~" H 6400 2850 60 0000 C CNN 1 6400 2850 0 -1 -1 0 $EndComp $Comp L LED DAC5 U 1 1 548EF5F7 P 6700 2850 F 0 "DAC5" H 6700 2950 50 0000 C CNN F 1 "LED" H 6700 2750 50 0000 C CNN F 2 "~" H 6700 2850 60 0000 C CNN F 3 "~" H 6700 2850 60 0000 C CNN 1 6700 2850 0 -1 -1 0 $EndComp $Comp L LED DAC6 U 1 1 548EF5FD P 7000 2850 F 0 "DAC6" H 7000 2950 50 0000 C CNN F 1 "LED" H 7000 2750 50 0000 C CNN F 2 "~" H 7000 2850 60 0000 C CNN F 3 "~" H 7000 2850 60 0000 C CNN 1 7000 2850 0 -1 -1 0 $EndComp $Comp L LED DAC7 U 1 1 548EF603 P 7300 2850 F 0 "DAC7" H 7300 2950 50 0000 C CNN F 1 "LED" H 7300 2750 50 0000 C CNN F 2 "~" H 7300 2850 60 0000 C CNN F 3 "~" H 7300 2850 60 0000 C CNN 1 7300 2850 0 -1 -1 0 $EndComp $Comp L LED DAC8 U 1 1 548EF609 P 7600 2850 F 0 "DAC8" H 7600 2950 50 0000 C CNN F 1 "LED" H 7600 2750 50 0000 C CNN F 2 "~" H 7600 2850 60 0000 C CNN F 3 "~" H 7600 2850 60 0000 C CNN 1 7600 2850 0 -1 -1 0 $EndComp $Comp L LED DAC9 U 1 1 548EF60F P 7900 2850 F 0 "DAC9" H 7900 2950 50 0000 C CNN F 1 "LED" H 7900 2750 50 0000 C CNN F 2 "~" H 7900 2850 60 0000 C CNN F 3 "~" H 7900 2850 60 0000 C CNN 1 7900 2850 0 -1 -1 0 $EndComp $Comp L LED DAC10 U 1 1 548EF615 P 8200 2850 F 0 "DAC10" H 8200 2950 50 0000 C CNN F 1 "LED" H 8200 2750 50 0000 C CNN F 2 "~" H 8200 2850 60 0000 C CNN F 3 "~" H 8200 2850 60 0000 C CNN 1 8200 2850 0 -1 -1 0 $EndComp $Comp L LED DAC11 U 1 1 548EF61B P 8500 2850 F 0 "DAC11" H 8500 2950 50 0000 C CNN F 1 "LED" H 8500 2750 50 0000 C CNN F 2 "~" H 8500 2850 60 0000 C CNN F 3 "~" H 8500 2850 60 0000 C CNN 1 8500 2850 0 -1 -1 0 $EndComp $Comp L LED DAC12 U 1 1 548EF621 P 8800 2850 F 0 "DAC12" H 8800 2950 50 0000 C CNN F 1 "LED" H 8800 2750 50 0000 C CNN F 2 "~" H 8800 2850 60 0000 C CNN F 3 "~" H 8800 2850 60 0000 C CNN 1 8800 2850 0 -1 -1 0 $EndComp $Comp L LED DMQ1 U 1 1 548EF629 P 5500 3600 F 0 "DMQ1" H 5500 3700 50 0000 C CNN F 1 "LED" H 5500 3500 50 0000 C CNN F 2 "~" H 5500 3600 60 0000 C CNN F 3 "~" H 5500 3600 60 0000 C CNN 1 5500 3600 0 1 1 0 $EndComp $Comp L LED DMQ2 U 1 1 548EF642 P 5800 3600 F 0 "DMQ2" H 5800 3700 50 0000 C CNN F 1 "LED" H 5800 3500 50 0000 C CNN F 2 "~" H 5800 3600 60 0000 C CNN F 3 "~" H 5800 3600 60 0000 C CNN 1 5800 3600 0 1 1 0 $EndComp $Comp L LED DMQ3 U 1 1 548EF648 P 6100 3600 F 0 "DMQ3" H 6100 3700 50 0000 C CNN F 1 "LED" H 6100 3500 50 0000 C CNN F 2 "~" H 6100 3600 60 0000 C CNN F 3 "~" H 6100 3600 60 0000 C CNN 1 6100 3600 0 1 1 0 $EndComp $Comp L LED DMQ4 U 1 1 548EF64E P 6400 3600 F 0 "DMQ4" H 6400 3700 50 0000 C CNN F 1 "LED" H 6400 3500 50 0000 C CNN F 2 "~" H 6400 3600 60 0000 C CNN F 3 "~" H 6400 3600 60 0000 C CNN 1 6400 3600 0 1 1 0 $EndComp $Comp L LED DMQ5 U 1 1 548EF654 P 6700 3600 F 0 "DMQ5" H 6700 3700 50 0000 C CNN F 1 "LED" H 6700 3500 50 0000 C CNN F 2 "~" H 6700 3600 60 0000 C CNN F 3 "~" H 6700 3600 60 0000 C CNN 1 6700 3600 0 1 1 0 $EndComp $Comp L LED DMQ6 U 1 1 548EF65A P 7000 3600 F 0 "DMQ6" H 7000 3700 50 0000 C CNN F 1 "LED" H 7000 3500 50 0000 C CNN F 2 "~" H 7000 3600 60 0000 C CNN F 3 "~" H 7000 3600 60 0000 C CNN 1 7000 3600 0 1 1 0 $EndComp $Comp L LED DMQ7 U 1 1 548EF660 P 7300 3600 F 0 "DMQ7" H 7300 3700 50 0000 C CNN F 1 "LED" H 7300 3500 50 0000 C CNN F 2 "~" H 7300 3600 60 0000 C CNN F 3 "~" H 7300 3600 60 0000 C CNN 1 7300 3600 0 1 1 0 $EndComp $Comp L LED DMQ8 U 1 1 548EF666 P 7600 3600 F 0 "DMQ8" H 7600 3700 50 0000 C CNN F 1 "LED" H 7600 3500 50 0000 C CNN F 2 "~" H 7600 3600 60 0000 C CNN F 3 "~" H 7600 3600 60 0000 C CNN 1 7600 3600 0 1 1 0 $EndComp $Comp L LED DMQ9 U 1 1 548EF66C P 7900 3600 F 0 "DMQ9" H 7900 3700 50 0000 C CNN F 1 "LED" H 7900 3500 50 0000 C CNN F 2 "~" H 7900 3600 60 0000 C CNN F 3 "~" H 7900 3600 60 0000 C CNN 1 7900 3600 0 1 1 0 $EndComp $Comp L LED DMQ10 U 1 1 548EF672 P 8200 3600 F 0 "DMQ10" H 8200 3700 50 0000 C CNN F 1 "LED" H 8200 3500 50 0000 C CNN F 2 "~" H 8200 3600 60 0000 C CNN F 3 "~" H 8200 3600 60 0000 C CNN 1 8200 3600 0 1 1 0 $EndComp $Comp L LED DMQ11 U 1 1 548EF678 P 8500 3600 F 0 "DMQ11" H 8500 3700 50 0000 C CNN F 1 "LED" H 8500 3500 50 0000 C CNN F 2 "~" H 8500 3600 60 0000 C CNN F 3 "~" H 8500 3600 60 0000 C CNN 1 8500 3600 0 1 1 0 $EndComp $Comp L LED DMQ12 U 1 1 548EF67E P 8800 3600 F 0 "DMQ12" H 8800 3700 50 0000 C CNN F 1 "LED" H 8800 3500 50 0000 C CNN F 2 "~" H 8800 3600 60 0000 C CNN F 3 "~" H 8800 3600 60 0000 C CNN 1 8800 3600 0 1 1 0 $EndComp $Comp L LED DLINK1 U 1 1 548EF686 P 5200 2850 F 0 "DLINK1" H 5200 2950 50 0000 C CNN F 1 "LED" H 5200 2750 50 0000 C CNN F 2 "~" H 5200 2850 60 0000 C CNN F 3 "~" H 5200 2850 60 0000 C CNN 1 5200 2850 0 1 1 0 $EndComp $Comp L LED DSC1 U 1 1 548EF6A1 P 3350 3600 F 0 "DSC1" H 3350 3700 50 0000 C CNN F 1 "LED" H 3350 3500 50 0000 C CNN F 2 "~" H 3350 3600 60 0000 C CNN F 3 "~" H 3350 3600 60 0000 C CNN 1 3350 3600 0 1 1 0 $EndComp $Comp L LED DSC2 U 1 1 548EF6BA P 3650 3600 F 0 "DSC2" H 3650 3700 50 0000 C CNN F 1 "LED" H 3650 3500 50 0000 C CNN F 2 "~" H 3650 3600 60 0000 C CNN F 3 "~" H 3650 3600 60 0000 C CNN 1 3650 3600 0 1 1 0 $EndComp $Comp L LED DSC3 U 1 1 548EF6C0 P 3950 3600 F 0 "DSC3" H 3950 3700 50 0000 C CNN F 1 "LED" H 3950 3500 50 0000 C CNN F 2 "~" H 3950 3600 60 0000 C CNN F 3 "~" H 3950 3600 60 0000 C CNN 1 3950 3600 0 1 1 0 $EndComp $Comp L LED DSC4 U 1 1 548EF6C6 P 4250 3600 F 0 "DSC4" H 4250 3700 50 0000 C CNN F 1 "LED" H 4250 3500 50 0000 C CNN F 2 "~" H 4250 3600 60 0000 C CNN F 3 "~" H 4250 3600 60 0000 C CNN 1 4250 3600 0 1 1 0 $EndComp $Comp L LED DSC5 U 1 1 548EF6CC P 4550 3600 F 0 "DSC5" H 4550 3700 50 0000 C CNN F 1 "LED" H 4550 3500 50 0000 C CNN F 2 "~" H 4550 3600 60 0000 C CNN F 3 "~" H 4550 3600 60 0000 C CNN 1 4550 3600 0 1 1 0 $EndComp $Comp L LED DDF1 U 1 1 548EF6DA P 3350 900 F 0 "DDF1" H 3350 1000 50 0000 C CNN F 1 "LED" H 3350 800 50 0000 C CNN F 2 "~" H 3350 900 60 0000 C CNN F 3 "~" H 3350 900 60 0000 C CNN 1 3350 900 0 1 1 0 $EndComp $Comp L LED DDF2 U 1 1 548EF6F3 P 3650 900 F 0 "DDF2" H 3650 1000 50 0000 C CNN F 1 "LED" H 3650 800 50 0000 C CNN F 2 "~" H 3650 900 60 0000 C CNN F 3 "~" H 3650 900 60 0000 C CNN 1 3650 900 0 1 1 0 $EndComp $Comp L LED DDF3 U 1 1 548EF6F9 P 3950 900 F 0 "DDF3" H 3950 1000 50 0000 C CNN F 1 "LED" H 3950 800 50 0000 C CNN F 2 "~" H 3950 900 60 0000 C CNN F 3 "~" H 3950 900 60 0000 C CNN 1 3950 900 0 1 1 0 $EndComp $Comp L LED DIF1 U 1 1 548EF701 P 4250 900 F 0 "DIF1" V 4250 1000 50 0000 C CNN F 1 "LED" H 4250 800 50 0000 C CNN F 2 "~" H 4250 900 60 0000 C CNN F 3 "~" H 4250 900 60 0000 C CNN 1 4250 900 0 1 1 0 $EndComp $Comp L LED DIF2 U 1 1 548EF71A P 4550 900 F 0 "DIF2" H 4550 1000 50 0000 C CNN F 1 "LED" H 4550 800 50 0000 C CNN F 2 "~" H 4550 900 60 0000 C CNN F 3 "~" H 4550 900 60 0000 C CNN 1 4550 900 0 1 1 0 $EndComp $Comp L LED DIF3 U 1 1 548EF720 P 4850 900 F 0 "DIF3" H 4850 1000 50 0000 C CNN F 1 "LED" H 4850 800 50 0000 C CNN F 2 "~" H 4850 900 60 0000 C CNN F 3 "~" H 4850 900 60 0000 C CNN 1 4850 900 0 1 1 0 $EndComp $Comp L LED DAND1 U 1 1 548EF728 P 9500 1150 F 0 "DAND1" H 9500 1250 50 0000 C CNN F 1 "LED" H 9500 1050 50 0000 C CNN F 2 "~" H 9500 1150 60 0000 C CNN F 3 "~" H 9500 1150 60 0000 C CNN 1 9500 1150 1 0 0 -1 $EndComp $Comp L LED DTAD1 U 1 1 548EF735 P 9500 1500 F 0 "DTAD1" H 9500 1600 50 0000 C CNN F 1 "LED" H 9500 1400 50 0000 C CNN F 2 "~" H 9500 1500 60 0000 C CNN F 3 "~" H 9500 1500 60 0000 C CNN 1 9500 1500 1 0 0 -1 $EndComp $Comp L LED DISZ1 U 1 1 548EF73B P 9500 1850 F 0 "DISZ1" H 9500 1950 50 0000 C CNN F 1 "LED" H 9500 1750 50 0000 C CNN F 2 "~" H 9500 1850 60 0000 C CNN F 3 "~" H 9500 1850 60 0000 C CNN 1 9500 1850 1 0 0 -1 $EndComp $Comp L LED DDCA1 U 1 1 548EF741 P 9500 2200 F 0 "DDCA1" H 9500 2300 50 0000 C CNN F 1 "LED" H 9500 2100 50 0000 C CNN F 2 "~" H 9500 2200 60 0000 C CNN F 3 "~" H 9500 2200 60 0000 C CNN 1 9500 2200 1 0 0 -1 $EndComp $Comp L LED DJMS1 U 1 1 548EF777 P 9500 2550 F 0 "DJMS1" H 9500 2650 50 0000 C CNN F 1 "LED" H 9500 2450 50 0000 C CNN F 2 "~" H 9500 2550 60 0000 C CNN F 3 "~" H 9500 2550 60 0000 C CNN 1 9500 2550 1 0 0 -1 $EndComp $Comp L LED DJMP1 U 1 1 548EF77D P 9500 2900 F 0 "DJMP1" H 9500 3000 50 0000 C CNN F 1 "LED" H 9500 2800 50 0000 C CNN F 2 "~" H 9500 2900 60 0000 C CNN F 3 "~" H 9500 2900 60 0000 C CNN 1 9500 2900 1 0 0 -1 $EndComp $Comp L LED DIOT1 U 1 1 548EF783 P 9500 3250 F 0 "DIOT1" H 9500 3350 50 0000 C CNN F 1 "LED" H 9500 3150 50 0000 C CNN F 2 "~" H 9500 3250 60 0000 C CNN F 3 "~" H 9500 3250 60 0000 C CNN 1 9500 3250 1 0 0 -1 $EndComp $Comp L LED DOPR1 U 1 1 548EF789 P 9500 3600 F 0 "DOPR1" H 9500 3700 50 0000 C CNN F 1 "LED" H 9500 3500 50 0000 C CNN F 2 "~" H 9500 3600 60 0000 C CNN F 3 "~" H 9500 3600 60 0000 C CNN 1 9500 3600 1 0 0 -1 $EndComp $Comp L LED DFETCH1 U 1 1 548EF7CB P 10150 1150 F 0 "DFETCH1" H 10150 1250 50 0000 C CNN F 1 "LED" H 10150 1050 50 0000 C CNN F 2 "~" H 10150 1150 60 0000 C CNN F 3 "~" H 10150 1150 60 0000 C CNN 1 10150 1150 1 0 0 -1 $EndComp $Comp L LED DEXEC1 U 1 1 548EF7D1 P 10150 1500 F 0 "DEXEC1" H 10150 1600 50 0000 C CNN F 1 "LED" H 10150 1400 50 0000 C CNN F 2 "~" H 10150 1500 60 0000 C CNN F 3 "~" H 10150 1500 60 0000 C CNN 1 10150 1500 1 0 0 -1 $EndComp $Comp L LED DDEFER1 U 1 1 548EF7D7 P 10150 1850 F 0 "DDEFER1" H 10150 1950 50 0000 C CNN F 1 "LED" H 10150 1750 50 0000 C CNN F 2 "~" H 10150 1850 60 0000 C CNN F 3 "~" H 10150 1850 60 0000 C CNN 1 10150 1850 1 0 0 -1 $EndComp $Comp L LED DWRDCT1 U 1 1 548EF7DD P 10150 2200 F 0 "DWRDCT1" H 10150 2300 50 0000 C CNN F 1 "LED" H 10150 2100 50 0000 C CNN F 2 "~" H 10150 2200 60 0000 C CNN F 3 "~" H 10150 2200 60 0000 C CNN 1 10150 2200 1 0 0 -1 $EndComp $Comp L LED DCURAD1 U 1 1 548EF7E3 P 10150 2900 F 0 "DCURAD1" H 10150 3000 50 0000 C CNN F 1 "LED" H 10150 2800 50 0000 C CNN F 2 "~" H 10150 2900 60 0000 C CNN F 3 "~" H 10150 2900 60 0000 C CNN 1 10150 2900 1 0 0 -1 $EndComp $Comp L LED DBREAK1 U 1 1 548EF7E9 P 10150 3250 F 0 "DBREAK1" H 10150 3350 50 0000 C CNN F 1 "LED" H 10150 3150 50 0000 C CNN F 2 "~" H 10150 3250 60 0000 C CNN F 3 "~" H 10150 3250 60 0000 C CNN 1 10150 3250 1 0 0 -1 $EndComp $Comp L LED DION1 U 1 1 548EF837 P 10800 1150 F 0 "DION1" H 10800 1250 50 0000 C CNN F 1 "LED" H 10800 1050 50 0000 C CNN F 2 "~" H 10800 1150 60 0000 C CNN F 3 "~" H 10800 1150 60 0000 C CNN 1 10800 1150 1 0 0 -1 $EndComp $Comp L LED DPAUSE1 U 1 1 548EF83D P 10800 1500 F 0 "DPAUSE1" H 10800 1600 50 0000 C CNN F 1 "LED" H 10800 1400 50 0000 C CNN F 2 "~" H 10800 1500 60 0000 C CNN F 3 "~" H 10800 1500 60 0000 C CNN 1 10800 1500 1 0 0 -1 $EndComp $Comp L LED DRUN1 U 1 1 548EF843 P 10800 1850 F 0 "DRUN1" H 10800 1950 50 0000 C CNN F 1 "LED" H 10800 1750 50 0000 C CNN F 2 "~" H 10800 1850 60 0000 C CNN F 3 "~" H 10800 1850 60 0000 C CNN 1 10800 1850 1 0 0 -1 $EndComp $Comp L SWITCH_INV SW19 U 1 1 548EF86F P 7400 4800 F 0 "SW19" H 7200 4950 50 0000 C CNN F 1 "START" H 7250 4650 50 0000 C CNN F 2 "~" H 7400 4800 60 0000 C CNN F 3 "~" H 7400 4800 60 0000 C CNN 1 7400 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW20 U 1 1 548EF87C P 7900 4800 F 0 "SW20" H 7700 4950 50 0000 C CNN F 1 "LOAD_ADD" H 7750 4650 50 0000 C CNN F 2 "~" H 7900 4800 60 0000 C CNN F 3 "~" H 7900 4800 60 0000 C CNN 1 7900 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW21 U 1 1 548EF882 P 8400 4800 F 0 "SW21" H 8200 4950 50 0000 C CNN F 1 "DEP" H 8250 4650 50 0000 C CNN F 2 "~" H 8400 4800 60 0000 C CNN F 3 "~" H 8400 4800 60 0000 C CNN 1 8400 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW22 U 1 1 548EF888 P 8900 4800 F 0 "SW22" H 8700 4950 50 0000 C CNN F 1 "EXAM" H 8750 4650 50 0000 C CNN F 2 "~" H 8900 4800 60 0000 C CNN F 3 "~" H 8900 4800 60 0000 C CNN 1 8900 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW23 U 1 1 548EF88E P 9400 4800 F 0 "SW23" H 9200 4950 50 0000 C CNN F 1 "CONT" H 9250 4650 50 0000 C CNN F 2 "~" H 9400 4800 60 0000 C CNN F 3 "~" H 9400 4800 60 0000 C CNN 1 9400 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW24 U 1 1 548EF894 P 9900 4800 F 0 "SW24" H 9700 4950 50 0000 C CNN F 1 "STOP" H 9750 4650 50 0000 C CNN F 2 "~" H 9900 4800 60 0000 C CNN F 3 "~" H 9900 4800 60 0000 C CNN 1 9900 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW25 U 1 1 548EF89A P 10400 4800 F 0 "SW25" H 10200 4950 50 0000 C CNN F 1 "SING_STEP" H 10250 4650 50 0000 C CNN F 2 "~" H 10400 4800 60 0000 C CNN F 3 "~" H 10400 4800 60 0000 C CNN 1 10400 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW26 U 1 1 548EF8A0 P 10900 4800 F 0 "SW26" H 10700 4950 50 0000 C CNN F 1 "SING_INST" H 10750 4650 50 0000 C CNN F 2 "~" H 10900 4800 60 0000 C CNN F 3 "~" H 10900 4800 60 0000 C CNN 1 10900 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW7 U 1 1 548EFAF8 P 5050 6300 F 0 "SW7" H 4850 6450 50 0000 C CNN F 1 "SR1" H 4900 6150 50 0000 C CNN F 2 "~" H 5050 6300 60 0000 C CNN F 3 "~" H 5050 6300 60 0000 C CNN 1 5050 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW8 U 1 1 548EFB27 P 5500 6300 F 0 "SW8" H 5300 6450 50 0000 C CNN F 1 "SR2" H 5350 6150 50 0000 C CNN F 2 "~" H 5500 6300 60 0000 C CNN F 3 "~" H 5500 6300 60 0000 C CNN 1 5500 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW9 U 1 1 548EFB2D P 5950 6300 F 0 "SW9" H 5750 6450 50 0000 C CNN F 1 "SR3" H 5800 6150 50 0000 C CNN F 2 "~" H 5950 6300 60 0000 C CNN F 3 "~" H 5950 6300 60 0000 C CNN 1 5950 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW10 U 1 1 548EFB33 P 6400 6300 F 0 "SW10" H 6200 6450 50 0000 C CNN F 1 "SR4" H 6250 6150 50 0000 C CNN F 2 "~" H 6400 6300 60 0000 C CNN F 3 "~" H 6400 6300 60 0000 C CNN 1 6400 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW11 U 1 1 548EFB42 P 6900 6300 F 0 "SW11" H 6700 6450 50 0000 C CNN F 1 "SR5" H 6750 6150 50 0000 C CNN F 2 "~" H 6900 6300 60 0000 C CNN F 3 "~" H 6900 6300 60 0000 C CNN 1 6900 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW12 U 1 1 548EFB48 P 7350 6300 F 0 "SW12" H 7150 6450 50 0000 C CNN F 1 "SR6" H 7200 6150 50 0000 C CNN F 2 "~" H 7350 6300 60 0000 C CNN F 3 "~" H 7350 6300 60 0000 C CNN 1 7350 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW13 U 1 1 548EFB4E P 7800 6300 F 0 "SW13" H 7600 6450 50 0000 C CNN F 1 "SR7" H 7650 6150 50 0000 C CNN F 2 "~" H 7800 6300 60 0000 C CNN F 3 "~" H 7800 6300 60 0000 C CNN 1 7800 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW14 U 1 1 548EFB54 P 8250 6300 F 0 "SW14" H 8050 6450 50 0000 C CNN F 1 "SR8" H 8100 6150 50 0000 C CNN F 2 "~" H 8250 6300 60 0000 C CNN F 3 "~" H 8250 6300 60 0000 C CNN 1 8250 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW15 U 1 1 548EFB5A P 8750 6300 F 0 "SW15" H 8550 6450 50 0000 C CNN F 1 "SR9" H 8600 6150 50 0000 C CNN F 2 "~" H 8750 6300 60 0000 C CNN F 3 "~" H 8750 6300 60 0000 C CNN 1 8750 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW16 U 1 1 548EFB60 P 9200 6300 F 0 "SW16" H 9000 6450 50 0000 C CNN F 1 "SR10" H 9050 6150 50 0000 C CNN F 2 "~" H 9200 6300 60 0000 C CNN F 3 "~" H 9200 6300 60 0000 C CNN 1 9200 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW17 U 1 1 548EFB66 P 9650 6300 F 0 "SW17" H 9450 6450 50 0000 C CNN F 1 "SR11" H 9500 6150 50 0000 C CNN F 2 "~" H 9650 6300 60 0000 C CNN F 3 "~" H 9650 6300 60 0000 C CNN 1 9650 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW18 U 1 1 548EFB6C P 10100 6300 F 0 "SW18" H 9900 6450 50 0000 C CNN F 1 "SR12" H 9950 6150 50 0000 C CNN F 2 "~" H 10100 6300 60 0000 C CNN F 3 "~" H 10100 6300 60 0000 C CNN 1 10100 6300 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW1 U 1 1 548EFBFD P 3900 4800 F 0 "SW1" H 3700 4950 50 0000 C CNN F 1 "DF1" H 3750 4650 50 0000 C CNN F 2 "~" H 3900 4800 60 0000 C CNN F 3 "~" H 3900 4800 60 0000 C CNN 1 3900 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW2 U 1 1 548EFC03 P 4350 4800 F 0 "SW2" H 4150 4950 50 0000 C CNN F 1 "DF2" H 4200 4650 50 0000 C CNN F 2 "~" H 4350 4800 60 0000 C CNN F 3 "~" H 4350 4800 60 0000 C CNN 1 4350 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW3 U 1 1 548EFC09 P 4800 4800 F 0 "SW3" H 4600 4950 50 0000 C CNN F 1 "DF3" H 4650 4650 50 0000 C CNN F 2 "~" H 4800 4800 60 0000 C CNN F 3 "~" H 4800 4800 60 0000 C CNN 1 4800 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW4 U 1 1 548EFC0F P 5250 4800 F 0 "SW4" H 5050 4950 50 0000 C CNN F 1 "IF1" H 5100 4650 50 0000 C CNN F 2 "~" H 5250 4800 60 0000 C CNN F 3 "~" H 5250 4800 60 0000 C CNN 1 5250 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW5 U 1 1 548EFC15 P 5750 4800 F 0 "SW5" H 5550 4950 50 0000 C CNN F 1 "IF2" H 5600 4650 50 0000 C CNN F 2 "~" H 5750 4800 60 0000 C CNN F 3 "~" H 5750 4800 60 0000 C CNN 1 5750 4800 0 -1 -1 0 $EndComp $Comp L SWITCH_INV SW6 U 1 1 548EFC1B P 6200 4800 F 0 "SW6" H 6000 4950 50 0000 C CNN F 1 "IF3" H 6050 4650 50 0000 C CNN F 2 "~" H 6200 4800 60 0000 C CNN F 3 "~" H 6200 4800 60 0000 C CNN 1 6200 4800 0 -1 -1 0 $EndComp $Comp L RASPI_MODEL_B_PLUS_GPIO P1 U 1 1 548F13F7 P 1850 2150 F 0 "P1" H 1850 3200 60 0000 C CNN F 1 "RASPI_MODEL_B_PLUS_GPIO" V 1850 2150 20 0000 C CNN F 2 "~" H 1850 2150 60 0000 C CNN F 3 "~" H 1850 2150 60 0000 C CNN 1 1850 2150 1 0 0 -1 $EndComp Text GLabel 4700 1600 2 60 Input ~ 0 led1 Text GLabel 4700 1700 2 60 Input ~ 0 led2 Text GLabel 4700 1800 2 60 Input ~ 0 led3 Text GLabel 4700 1900 2 60 Input ~ 0 led4 Text GLabel 4700 2000 2 60 Input ~ 0 led5 Text GLabel 4700 2100 2 60 Input ~ 0 led6 Text GLabel 4700 2200 2 60 Input ~ 0 led7 Text GLabel 4700 2300 2 60 Input ~ 0 led8 Text GLabel 800 1300 0 60 Input ~ 0 col1a Text GLabel 800 1400 0 60 Input ~ 0 col2a Text GLabel 800 1500 0 60 Input ~ 0 col3 Text GLabel 800 2600 0 60 Input ~ 0 col4 Text GLabel 800 2700 0 60 Input ~ 0 col5 Text GLabel 2900 2400 2 60 Input ~ 0 col6 Text GLabel 2900 2300 2 60 Input ~ 0 col7 Text GLabel 800 2200 0 60 Input ~ 0 col8 Text GLabel 800 2100 0 60 Input ~ 0 col9 Text GLabel 800 2300 0 60 Input ~ 0 col10 Text GLabel 2900 2700 2 60 Input ~ 0 col11 Text GLabel 800 2800 0 60 Input ~ 0 col12 Text GLabel 2900 2900 2 60 Input ~ 0 row1 Text GLabel 800 1700 0 60 Input ~ 0 row2 Text GLabel 2900 1700 2 60 Input ~ 0 row3 Text Notes 650 800 0 31 ~ 0 Driving LEDs: a matrix of LED8 X COL12\nSensing switches: a matrix of ROW3 X COL12 Text GLabel 8900 700 2 60 Input ~ 0 led1 Text GLabel 8900 1750 2 60 Input ~ 0 led2 Text GLabel 8900 2000 2 60 Input ~ 0 led3 Text GLabel 8900 3050 2 60 Input ~ 0 led4 Text GLabel 8900 3400 2 60 Input ~ 0 led5 Text GLabel 3300 1150 0 60 Input ~ 0 col1 Text GLabel 3600 1300 0 60 Input ~ 0 col2 Text GLabel 3900 1150 0 60 Input ~ 0 col3 Text GLabel 4200 1300 0 60 Input ~ 0 col4 Text GLabel 4500 1150 0 60 Input ~ 0 col5 Text GLabel 4800 1300 0 60 Input ~ 0 col6 Text GLabel 7250 1150 0 60 Input ~ 0 col7 Text GLabel 7550 1300 0 60 Input ~ 0 col8 Text GLabel 7850 1150 0 60 Input ~ 0 col9 Text GLabel 8150 1300 0 60 Input ~ 0 col10 Text GLabel 8450 1150 0 60 Input ~ 0 col11 Text GLabel 8750 1300 0 60 Input ~ 0 col12 Text GLabel 5450 3850 0 60 Input ~ 0 col1 Text GLabel 5750 4000 0 60 Input ~ 0 col2 Text GLabel 6050 3850 0 60 Input ~ 0 col3 Text GLabel 6350 4000 0 60 Input ~ 0 col4 Text GLabel 6650 3850 0 60 Input ~ 0 col5 Text GLabel 3300 4000 0 60 Input ~ 0 col6 Text GLabel 3600 3850 0 60 Input ~ 0 col7 Text GLabel 3900 4000 0 60 Input ~ 0 col8 Text GLabel 4200 3850 0 60 Input ~ 0 col9 Text GLabel 4500 4000 0 60 Input ~ 0 col10 Text GLabel 8450 3850 0 60 Input ~ 0 col11 Text GLabel 8750 4000 0 60 Input ~ 0 col12 Text GLabel 9300 1050 1 60 Input ~ 0 led6 Text GLabel 9750 1150 1 60 Input ~ 0 col1 Text GLabel 9750 1500 1 60 Input ~ 0 col2 Text GLabel 9750 1850 1 60 Input ~ 0 col3 Text GLabel 9750 2200 1 60 Input ~ 0 col4 Text GLabel 9750 2550 1 60 Input ~ 0 col5 Text GLabel 9750 2900 1 60 Input ~ 0 col6 Text GLabel 9750 3250 1 60 Input ~ 0 col7 Text GLabel 9750 3600 1 60 Input ~ 0 col8 Text GLabel 9950 1050 1 60 Input ~ 0 led6 Text GLabel 10400 1150 1 60 Input ~ 0 col9 Text GLabel 10400 1500 1 60 Input ~ 0 col10 Text GLabel 10400 1850 1 60 Input ~ 0 col11 Text GLabel 10400 2200 1 60 Input ~ 0 col12 Text GLabel 9950 2750 1 60 Input ~ 0 led7 Text GLabel 10400 2900 1 60 Input ~ 0 col1 Text GLabel 10400 3250 1 60 Input ~ 0 col2 Text GLabel 10600 1050 1 60 Input ~ 0 led7 Text GLabel 11050 1150 1 60 Input ~ 0 col3 Text GLabel 11050 1500 1 60 Input ~ 0 col4 Text GLabel 11050 1850 1 60 Input ~ 0 col5 Text GLabel 4600 3400 2 60 Input ~ 0 led7 Text GLabel 3300 700 0 60 Input ~ 0 led8 Text GLabel 5150 2650 0 60 Input ~ 0 led8 Text GLabel 5150 3050 0 60 Input ~ 0 col7 Text GLabel 5450 1150 0 60 Input ~ 0 col1 Text GLabel 5750 1300 0 60 Input ~ 0 col2 Text GLabel 6050 1150 0 60 Input ~ 0 col3 Text GLabel 6350 1300 0 60 Input ~ 0 col4 Text GLabel 6650 1150 0 60 Input ~ 0 col5 Text GLabel 6950 1300 0 60 Input ~ 0 col6 Text GLabel 7250 2450 0 60 Input ~ 0 col7 Text GLabel 7550 2600 0 60 Input ~ 0 col8 Text GLabel 7850 2450 0 60 Input ~ 0 col9 Text GLabel 8150 2600 0 60 Input ~ 0 col10 Text GLabel 8450 2450 0 60 Input ~ 0 col11 Text GLabel 8750 2600 0 60 Input ~ 0 col12 Text GLabel 6950 2600 0 60 Input ~ 0 col6 Text GLabel 5450 2450 0 60 Input ~ 0 col1 Text GLabel 5750 2600 0 60 Input ~ 0 col2 Text GLabel 6050 2450 0 60 Input ~ 0 col3 Text GLabel 6350 2600 0 60 Input ~ 0 col4 Text GLabel 6650 2450 0 60 Input ~ 0 col5 Text GLabel 7250 3850 0 60 Input ~ 0 col7 Text GLabel 7550 4000 0 60 Input ~ 0 col8 Text GLabel 7850 3850 0 60 Input ~ 0 col9 Text GLabel 8150 4000 0 60 Input ~ 0 col10 Text GLabel 6950 4000 0 60 Input ~ 0 col6 Text GLabel 4900 5750 0 60 Input ~ 0 row1 Text GLabel 4650 7050 2 60 Input ~ 0 col1 Text GLabel 5100 7050 2 60 Input ~ 0 col2 Text GLabel 5550 7050 2 60 Input ~ 0 col3 Text GLabel 6000 7050 2 60 Input ~ 0 col4 Text GLabel 6500 7050 2 60 Input ~ 0 col5 Text GLabel 9250 7050 2 60 Input ~ 0 col11 Text GLabel 9700 7050 2 60 Input ~ 0 col12 Text GLabel 7400 7050 2 60 Input ~ 0 col7 Text GLabel 7850 7050 2 60 Input ~ 0 col8 Text GLabel 8350 7050 2 60 Input ~ 0 col9 Text GLabel 8800 7050 2 60 Input ~ 0 col10 Text GLabel 6950 7050 2 60 Input ~ 0 col6 Text GLabel 3500 5550 2 60 Input ~ 0 col1 Text GLabel 3950 5550 2 60 Input ~ 0 col2 Text GLabel 4400 5550 2 60 Input ~ 0 col3 Text GLabel 4850 5550 2 60 Input ~ 0 col4 Text GLabel 5350 5550 2 60 Input ~ 0 col5 Text GLabel 5800 5550 2 60 Input ~ 0 col6 Text GLabel 3750 4250 0 60 Input ~ 0 row2 Text GLabel 7250 4250 0 60 Input ~ 0 row3 Text GLabel 7000 5550 2 60 Input ~ 0 col1 Text GLabel 7500 5550 2 60 Input ~ 0 col2 Text GLabel 8000 5550 2 60 Input ~ 0 col3 Text GLabel 8500 5550 2 60 Input ~ 0 col4 Text GLabel 9000 5550 2 60 Input ~ 0 col5 Text GLabel 9500 5550 2 60 Input ~ 0 col6 Text GLabel 10000 5550 2 60 Input ~ 0 col7 Text GLabel 10500 5550 2 60 Input ~ 0 col8 $Comp L DIODE D1 U 1 1 54904DF0 P 3700 5350 F 0 "D1" H 3700 5450 40 0000 C CNN F 1 "1N4148" H 3700 5250 40 0000 C CNN F 2 "~" H 3700 5350 60 0000 C CNN F 3 "~" H 3700 5350 60 0000 C CNN 1 3700 5350 1 0 0 -1 $EndComp $Comp L DIODE D2 U 1 1 5490504C P 4150 5350 F 0 "D2" H 4150 5450 40 0000 C CNN F 1 "1N4148" H 4150 5250 40 0000 C CNN F 2 "~" H 4150 5350 60 0000 C CNN F 3 "~" H 4150 5350 60 0000 C CNN 1 4150 5350 1 0 0 -1 $EndComp $Comp L DIODE D3 U 1 1 54905056 P 4600 5350 F 0 "D3" H 4600 5450 40 0000 C CNN F 1 "1N4148" H 4600 5250 40 0000 C CNN F 2 "~" H 4600 5350 60 0000 C CNN F 3 "~" H 4600 5350 60 0000 C CNN 1 4600 5350 1 0 0 -1 $EndComp $Comp L DIODE D4 U 1 1 5490505E P 5050 5350 F 0 "D4" H 5050 5450 40 0000 C CNN F 1 "1N4148" H 5050 5250 40 0000 C CNN F 2 "~" H 5050 5350 60 0000 C CNN F 3 "~" H 5050 5350 60 0000 C CNN 1 5050 5350 1 0 0 -1 $EndComp $Comp L DIODE D5 U 1 1 54905068 P 5550 5350 F 0 "D5" H 5550 5450 40 0000 C CNN F 1 "1N4148" H 5550 5250 40 0000 C CNN F 2 "~" H 5550 5350 60 0000 C CNN F 3 "~" H 5550 5350 60 0000 C CNN 1 5550 5350 1 0 0 -1 $EndComp $Comp L DIODE D6 U 1 1 5490506E P 6000 5350 F 0 "D6" H 6000 5450 40 0000 C CNN F 1 "1N4148" H 6000 5250 40 0000 C CNN F 2 "~" H 6000 5350 60 0000 C CNN F 3 "~" H 6000 5350 60 0000 C CNN 1 6000 5350 1 0 0 -1 $EndComp $Comp L DIODE D7 U 1 1 549055F9 P 4850 6850 F 0 "D7" H 4850 6950 40 0000 C CNN F 1 "1N4148" H 4850 6750 40 0000 C CNN F 2 "~" H 4850 6850 60 0000 C CNN F 3 "~" H 4850 6850 60 0000 C CNN 1 4850 6850 1 0 0 -1 $EndComp $Comp L DIODE D8 U 1 1 549055FF P 5300 6850 F 0 "D8" H 5300 6950 40 0000 C CNN F 1 "1N4148" H 5300 6750 40 0000 C CNN F 2 "~" H 5300 6850 60 0000 C CNN F 3 "~" H 5300 6850 60 0000 C CNN 1 5300 6850 1 0 0 -1 $EndComp $Comp L DIODE D9 U 1 1 54905605 P 5750 6850 F 0 "D9" H 5750 6950 40 0000 C CNN F 1 "1N4148" H 5750 6750 40 0000 C CNN F 2 "~" H 5750 6850 60 0000 C CNN F 3 "~" H 5750 6850 60 0000 C CNN 1 5750 6850 1 0 0 -1 $EndComp $Comp L DIODE D10 U 1 1 5490560B P 6200 6850 F 0 "D10" H 6200 6950 40 0000 C CNN F 1 "1N4148" H 6200 6750 40 0000 C CNN F 2 "~" H 6200 6850 60 0000 C CNN F 3 "~" H 6200 6850 60 0000 C CNN 1 6200 6850 1 0 0 -1 $EndComp $Comp L DIODE D11 U 1 1 54905611 P 6700 6850 F 0 "D11" H 6700 6950 40 0000 C CNN F 1 "1N4148" H 6700 6750 40 0000 C CNN F 2 "~" H 6700 6850 60 0000 C CNN F 3 "~" H 6700 6850 60 0000 C CNN 1 6700 6850 1 0 0 -1 $EndComp $Comp L DIODE D12 U 1 1 54905640 P 7150 6850 F 0 "D12" H 7150 6950 40 0000 C CNN F 1 "1N4148" H 7150 6750 40 0000 C CNN F 2 "~" H 7150 6850 60 0000 C CNN F 3 "~" H 7150 6850 60 0000 C CNN 1 7150 6850 1 0 0 -1 $EndComp $Comp L DIODE D13 U 1 1 54905646 P 7600 6850 F 0 "D13" H 7600 6950 40 0000 C CNN F 1 "1N4148" H 7600 6750 40 0000 C CNN F 2 "~" H 7600 6850 60 0000 C CNN F 3 "~" H 7600 6850 60 0000 C CNN 1 7600 6850 1 0 0 -1 $EndComp $Comp L DIODE D14 U 1 1 5490564C P 8050 6850 F 0 "D14" H 8050 6950 40 0000 C CNN F 1 "1N4148" H 8050 6750 40 0000 C CNN F 2 "~" H 8050 6850 60 0000 C CNN F 3 "~" H 8050 6850 60 0000 C CNN 1 8050 6850 1 0 0 -1 $EndComp $Comp L DIODE D15 U 1 1 54905652 P 8550 6850 F 0 "D15" H 8550 6950 40 0000 C CNN F 1 "1N4148" H 8550 6750 40 0000 C CNN F 2 "~" H 8550 6850 60 0000 C CNN F 3 "~" H 8550 6850 60 0000 C CNN 1 8550 6850 1 0 0 -1 $EndComp $Comp L DIODE D16 U 1 1 54905658 P 9000 6850 F 0 "D16" H 9000 6950 40 0000 C CNN F 1 "1N4148" H 9000 6750 40 0000 C CNN F 2 "~" H 9000 6850 60 0000 C CNN F 3 "~" H 9000 6850 60 0000 C CNN 1 9000 6850 1 0 0 -1 $EndComp $Comp L DIODE D17 U 1 1 5490565E P 9450 6850 F 0 "D17" H 9450 6950 40 0000 C CNN F 1 "1N4148" H 9450 6750 40 0000 C CNN F 2 "~" H 9450 6850 60 0000 C CNN F 3 "~" H 9450 6850 60 0000 C CNN 1 9450 6850 1 0 0 -1 $EndComp $Comp L DIODE D18 U 1 1 54905664 P 9900 6850 F 0 "D18" H 9900 6950 40 0000 C CNN F 1 "1N4148" H 9900 6750 40 0000 C CNN F 2 "~" H 9900 6850 60 0000 C CNN F 3 "~" H 9900 6850 60 0000 C CNN 1 9900 6850 1 0 0 -1 $EndComp $Comp L DIODE D19 U 1 1 549070C3 P 7200 5350 F 0 "D19" H 7200 5450 40 0000 C CNN F 1 "1N4148" H 7200 5250 40 0000 C CNN F 2 "~" H 7200 5350 60 0000 C CNN F 3 "~" H 7200 5350 60 0000 C CNN 1 7200 5350 1 0 0 -1 $EndComp $Comp L DIODE D20 U 1 1 549070C9 P 7700 5350 F 0 "D20" H 7700 5450 40 0000 C CNN F 1 "1N4148" H 7700 5250 40 0000 C CNN F 2 "~" H 7700 5350 60 0000 C CNN F 3 "~" H 7700 5350 60 0000 C CNN 1 7700 5350 1 0 0 -1 $EndComp $Comp L DIODE D21 U 1 1 549070CF P 8200 5350 F 0 "D21" H 8200 5450 40 0000 C CNN F 1 "1N4148" H 8200 5250 40 0000 C CNN F 2 "~" H 8200 5350 60 0000 C CNN F 3 "~" H 8200 5350 60 0000 C CNN 1 8200 5350 1 0 0 -1 $EndComp $Comp L DIODE D22 U 1 1 549070D5 P 8700 5350 F 0 "D22" H 8700 5450 40 0000 C CNN F 1 "1N4148" H 8700 5250 40 0000 C CNN F 2 "~" H 8700 5350 60 0000 C CNN F 3 "~" H 8700 5350 60 0000 C CNN 1 8700 5350 1 0 0 -1 $EndComp $Comp L DIODE D23 U 1 1 549070DB P 9200 5350 F 0 "D23" H 9200 5450 40 0000 C CNN F 1 "1N4148" H 9200 5250 40 0000 C CNN F 2 "~" H 9200 5350 60 0000 C CNN F 3 "~" H 9200 5350 60 0000 C CNN 1 9200 5350 1 0 0 -1 $EndComp $Comp L DIODE D24 U 1 1 549070E1 P 9700 5350 F 0 "D24" H 9700 5450 40 0000 C CNN F 1 "1N4148" H 9700 5250 40 0000 C CNN F 2 "~" H 9700 5350 60 0000 C CNN F 3 "~" H 9700 5350 60 0000 C CNN 1 9700 5350 1 0 0 -1 $EndComp $Comp L DIODE D25 U 1 1 549070E7 P 10200 5350 F 0 "D25" H 10200 5450 40 0000 C CNN F 1 "1N4148" H 10200 5250 40 0000 C CNN F 2 "~" H 10200 5350 60 0000 C CNN F 3 "~" H 10200 5350 60 0000 C CNN 1 10200 5350 1 0 0 -1 $EndComp $Comp L DIODE D26 U 1 1 549070ED P 10700 5350 F 0 "D26" H 10700 5450 40 0000 C CNN F 1 "1N4148" H 10700 5250 40 0000 C CNN F 2 "~" H 10700 5350 60 0000 C CNN F 3 "~" H 10700 5350 60 0000 C CNN 1 10700 5350 1 0 0 -1 $EndComp $Comp L R R1 U 1 1 5490833D P 2800 4150 F 0 "R1" V 2880 4150 40 0000 C CNN F 1 "390" V 2807 4151 40 0000 C CNN F 2 "~" V 2730 4150 30 0000 C CNN F 3 "~" H 2800 4150 30 0000 C CNN 1 2800 4150 1 0 0 -1 $EndComp $Comp L R R2 U 1 1 5490834A P 2800 5700 F 0 "R2" V 2880 5700 40 0000 C CNN F 1 "390" V 2807 5701 40 0000 C CNN F 2 "~" V 2730 5700 30 0000 C CNN F 3 "~" H 2800 5700 30 0000 C CNN 1 2800 5700 -1 0 0 1 $EndComp $Comp L R R3 U 1 1 54908350 P 1100 1500 F 0 "R3" V 1180 1500 40 0000 C CNN F 1 "390" V 1107 1501 40 0000 C CNN F 2 "~" V 1030 1500 30 0000 C CNN F 3 "~" H 1100 1500 30 0000 C CNN 1 1100 1500 0 -1 -1 0 $EndComp $Comp L R R4 U 1 1 54908356 P 1100 2600 F 0 "R4" V 1180 2600 40 0000 C CNN F 1 "390" V 1107 2601 40 0000 C CNN F 2 "~" V 1030 2600 30 0000 C CNN F 3 "~" H 1100 2600 30 0000 C CNN 1 1100 2600 0 -1 -1 0 $EndComp $Comp L R R5 U 1 1 5490835C P 1100 2700 F 0 "R5" V 1180 2700 40 0000 C CNN F 1 "390" V 1107 2701 40 0000 C CNN F 2 "~" V 1030 2700 30 0000 C CNN F 3 "~" H 1100 2700 30 0000 C CNN 1 1100 2700 0 -1 -1 0 $EndComp $Comp L R R6 U 1 1 54908362 P 2600 2400 F 0 "R6" V 2680 2400 40 0000 C CNN F 1 "390" V 2607 2401 40 0000 C CNN F 2 "~" V 2530 2400 30 0000 C CNN F 3 "~" H 2600 2400 30 0000 C CNN 1 2600 2400 0 1 1 0 $EndComp $Comp L R R7 U 1 1 54908368 P 2600 2300 F 0 "R7" V 2680 2300 40 0000 C CNN F 1 "390" V 2607 2301 40 0000 C CNN F 2 "~" V 2530 2300 30 0000 C CNN F 3 "~" H 2600 2300 30 0000 C CNN 1 2600 2300 0 -1 -1 0 $EndComp $Comp L R R8 U 1 1 5490836E P 1100 2200 F 0 "R8" V 1180 2200 40 0000 C CNN F 1 "390" V 1107 2201 40 0000 C CNN F 2 "~" V 1030 2200 30 0000 C CNN F 3 "~" H 1100 2200 30 0000 C CNN 1 1100 2200 0 1 1 0 $EndComp $Comp L R R9 U 1 1 54908374 P 1100 2100 F 0 "R9" V 1180 2100 40 0000 C CNN F 1 "390" V 1107 2101 40 0000 C CNN F 2 "~" V 1030 2100 30 0000 C CNN F 3 "~" H 1100 2100 30 0000 C CNN 1 1100 2100 0 1 1 0 $EndComp $Comp L R R10 U 1 1 5490837A P 1100 2300 F 0 "R10" V 1180 2300 40 0000 C CNN F 1 "390" V 1107 2301 40 0000 C CNN F 2 "~" V 1030 2300 30 0000 C CNN F 3 "~" H 1100 2300 30 0000 C CNN 1 1100 2300 0 1 1 0 $EndComp $Comp L R R11 U 1 1 54908380 P 2600 2700 F 0 "R11" V 2680 2700 40 0000 C CNN F 1 "390" V 2607 2701 40 0000 C CNN F 2 "~" V 2530 2700 30 0000 C CNN F 3 "~" H 2600 2700 30 0000 C CNN 1 2600 2700 0 -1 -1 0 $EndComp $Comp L R R12 U 1 1 54908386 P 1100 2800 F 0 "R12" V 1180 2800 40 0000 C CNN F 1 "390" V 1107 2801 40 0000 C CNN F 2 "~" V 1030 2800 30 0000 C CNN F 3 "~" H 1100 2800 30 0000 C CNN 1 1100 2800 0 1 1 0 $EndComp $Comp L R R_ROW1 U 1 1 5490838C P 2600 2900 F 0 "R_ROW1" V 2680 2900 40 0000 C CNN F 1 "1K" V 2607 2901 40 0000 C CNN F 2 "~" V 2530 2900 30 0000 C CNN F 3 "~" H 2600 2900 30 0000 C CNN 1 2600 2900 0 -1 -1 0 $EndComp $Comp L R R_ROW2 U 1 1 5490839E P 1100 1700 F 0 "R_ROW2" V 1180 1700 40 0000 C CNN F 1 "1K" V 1107 1701 40 0000 C CNN F 2 "~" V 1030 1700 30 0000 C CNN F 3 "~" H 1100 1700 30 0000 C CNN 1 1100 1700 0 1 1 0 $EndComp $Comp L R R_ROW3 U 1 1 549083A4 P 2600 1700 F 0 "R_ROW3" V 2680 1700 40 0000 C CNN F 1 "1K" V 2607 1701 40 0000 C CNN F 2 "~" V 2530 1700 30 0000 C CNN F 3 "~" H 2600 1700 30 0000 C CNN 1 2600 1700 0 -1 -1 0 $EndComp $Comp L UDN2981A P2 U 1 1 54B17386 P 4250 2000 F 0 "P2" H 4250 2550 30 0000 C CNN F 1 "UDN2981A" H 4250 1450 30 0000 C CNN F 2 "~" H 4250 2000 60 0000 C CNN F 3 "~" H 4250 2000 60 0000 C CNN 1 4250 2000 1 0 0 -1 $EndComp Text GLabel 3800 1600 0 60 Input ~ 0 xled1 Text GLabel 3800 1700 0 60 Input ~ 0 xled2 Text GLabel 3800 1800 0 60 Input ~ 0 xled3 Text GLabel 3800 1900 0 60 Input ~ 0 xled4 Text GLabel 3800 2000 0 60 Input ~ 0 xled5 Text GLabel 3800 2100 0 60 Input ~ 0 xled6 Text GLabel 3800 2200 0 60 Input ~ 0 xled7 Text GLabel 3800 2300 0 60 Input ~ 0 xled8 Text GLabel 2900 3000 2 60 Input ~ 0 xled1 Text GLabel 2900 3100 2 60 Input ~ 0 xled2 Text GLabel 800 1900 0 60 Input ~ 0 xled3 Text GLabel 2900 1900 2 60 Input ~ 0 xled4 Text GLabel 2900 2000 2 60 Input ~ 0 xled5 Text GLabel 2900 2200 2 60 Input ~ 0 xled6 Text GLabel 800 3000 0 60 Input ~ 0 xled7 Text GLabel 800 1800 0 60 Input ~ 0 xled8 NoConn ~ 2250 2500 NoConn ~ 1450 2500 $Comp L GND #PWR01 U 1 1 54B19131 P 2300 2600 F 0 "#PWR01" H 2300 2600 30 0001 C CNN F 1 "GND" H 2300 2530 30 0001 C CNN F 2 "" H 2300 2600 60 0000 C CNN F 3 "" H 2300 2600 60 0000 C CNN 1 2300 2600 0 -1 -1 0 $EndComp $Comp L GND #PWR02 U 1 1 54B1913E P 2300 2100 F 0 "#PWR02" H 2300 2100 30 0001 C CNN F 1 "GND" H 2300 2030 30 0001 C CNN F 2 "" H 2300 2100 60 0000 C CNN F 3 "" H 2300 2100 60 0000 C CNN 1 2300 2100 0 -1 -1 0 $EndComp $Comp L GND #PWR03 U 1 1 54B19150 P 1400 1600 F 0 "#PWR03" H 1400 1600 30 0001 C CNN F 1 "GND" H 1400 1530 30 0001 C CNN F 2 "" H 1400 1600 60 0000 C CNN F 3 "" H 1400 1600 60 0000 C CNN 1 1400 1600 0 1 1 0 $EndComp $Comp L GND #PWR04 U 1 1 54B19156 P 2300 1400 F 0 "#PWR04" H 2300 1400 30 0001 C CNN F 1 "GND" H 2300 1330 30 0001 C CNN F 2 "" H 2300 1400 60 0000 C CNN F 3 "" H 2300 1400 60 0000 C CNN 1 2300 1400 0 -1 -1 0 $EndComp $Comp L GND #PWR05 U 1 1 54B19903 P 1400 3100 F 0 "#PWR05" H 1400 3100 30 0001 C CNN F 1 "GND" H 1400 3030 30 0001 C CNN F 2 "" H 1400 3100 60 0000 C CNN F 3 "" H 1400 3100 60 0000 C CNN 1 1400 3100 0 1 1 0 $EndComp NoConn ~ 2250 2800 $Comp L +3.3V #PWR06 U 1 1 54B1C371 P 1350 1100 F 0 "#PWR06" H 1350 1060 30 0001 C CNN F 1 "+3.3V" H 1350 1210 30 0000 C CNN F 2 "" H 1350 1100 60 0000 C CNN F 3 "" H 1350 1100 60 0000 C CNN 1 1350 1100 1 0 0 -1 $EndComp $Comp L GND #PWR07 U 1 1 54B1C4F8 P 4750 2550 F 0 "#PWR07" H 4750 2550 30 0001 C CNN F 1 "GND" H 4750 2480 30 0001 C CNN F 2 "" H 4750 2550 60 0000 C CNN F 3 "" H 4750 2550 60 0000 C CNN 1 4750 2550 0 -1 -1 0 $EndComp NoConn ~ 4000 4300 NoConn ~ 4450 4300 NoConn ~ 4900 4300 NoConn ~ 5350 4300 NoConn ~ 5850 4300 NoConn ~ 6300 4300 NoConn ~ 7500 4300 NoConn ~ 8000 4300 NoConn ~ 8500 4300 NoConn ~ 9000 4300 NoConn ~ 9500 4300 NoConn ~ 10000 4300 NoConn ~ 10500 4300 NoConn ~ 11000 4300 NoConn ~ 10200 5800 NoConn ~ 9750 5800 NoConn ~ 9300 5800 NoConn ~ 8850 5800 NoConn ~ 8350 5800 NoConn ~ 7900 5800 NoConn ~ 7450 5800 NoConn ~ 7000 5800 NoConn ~ 6500 5800 NoConn ~ 5150 5800 NoConn ~ 5600 5800 NoConn ~ 6050 5800 $Comp L CONN_1 M1 U 1 1 54B1CC4A P 6150 7400 F 0 "M1" H 6230 7400 40 0000 L CNN F 1 "M" H 6150 7455 30 0001 C CNN F 2 "" H 6150 7400 60 0000 C CNN F 3 "" H 6150 7400 60 0000 C CNN 1 6150 7400 0 -1 -1 0 $EndComp $Comp L CONN_1 M2 U 1 1 54B1CC76 P 6250 7400 F 0 "M2" H 6330 7400 40 0000 L CNN F 1 "M" H 6250 7455 30 0001 C CNN F 2 "" H 6250 7400 60 0000 C CNN F 3 "" H 6250 7400 60 0000 C CNN 1 6250 7400 0 -1 -1 0 $EndComp $Comp L CONN_1 M3 U 1 1 54B1CC7C P 6350 7400 F 0 "M3" H 6430 7400 40 0000 L CNN F 1 "M" H 6350 7455 30 0001 C CNN F 2 "" H 6350 7400 60 0000 C CNN F 3 "" H 6350 7400 60 0000 C CNN 1 6350 7400 0 -1 -1 0 $EndComp $Comp L CONN_1 M4 U 1 1 54B1CC82 P 6450 7400 F 0 "M4" H 6530 7400 40 0000 L CNN F 1 "M" H 6450 7455 30 0001 C CNN F 2 "" H 6450 7400 60 0000 C CNN F 3 "" H 6450 7400 60 0000 C CNN 1 6450 7400 0 -1 -1 0 $EndComp NoConn ~ 6150 7550 NoConn ~ 6250 7550 NoConn ~ 6350 7550 NoConn ~ 6450 7550 $Comp L +5V #PWR08 U 1 1 54BCFC39 P 2400 1100 F 0 "#PWR08" H 2400 1190 20 0001 C CNN F 1 "+5V" H 2400 1190 30 0000 C CNN F 2 "" H 2400 1100 60 0000 C CNN F 3 "" H 2400 1100 60 0000 C CNN 1 2400 1100 1 0 0 -1 $EndComp Text GLabel 2750 1500 2 60 Input ~ 0 TX Text GLabel 2750 1600 2 60 Input ~ 0 RX Text GLabel 1350 2900 0 60 Input ~ 0 SPARE_IO Text GLabel 2300 7600 0 60 Input ~ 0 TX Text GLabel 2300 7500 0 60 Input ~ 0 RX $Comp L GND #PWR09 U 1 1 54BD292E P 2850 7100 F 0 "#PWR09" H 2850 7100 30 0001 C CNN F 1 "GND" H 2850 7030 30 0001 C CNN F 2 "" H 2850 7100 60 0000 C CNN F 3 "" H 2850 7100 60 0000 C CNN 1 2850 7100 -1 0 0 1 $EndComp NoConn ~ 1450 2400 NoConn ~ 2250 1800 $Comp L CONN_1 M5 U 1 1 54BD36C6 P 6550 7400 F 0 "M5" H 6630 7400 40 0000 L CNN F 1 "M" H 6550 7455 30 0001 C CNN F 2 "" H 6550 7400 60 0000 C CNN F 3 "" H 6550 7400 60 0000 C CNN 1 6550 7400 0 -1 -1 0 $EndComp $Comp L CONN_1 M6 U 1 1 54BD36CC P 6650 7400 F 0 "M6" H 6730 7400 40 0000 L CNN F 1 "M" H 6650 7455 30 0001 C CNN F 2 "" H 6650 7400 60 0000 C CNN F 3 "" H 6650 7400 60 0000 C CNN 1 6650 7400 0 -1 -1 0 $EndComp NoConn ~ 6550 7550 NoConn ~ 6650 7550 $Comp L CONN_1 M7 U 1 1 54BD36D2 P 6750 7400 F 0 "M7" H 6830 7400 40 0000 L CNN F 1 "M" H 6750 7455 30 0001 C CNN F 2 "" H 6750 7400 60 0000 C CNN F 3 "" H 6750 7400 60 0000 C CNN 1 6750 7400 0 -1 -1 0 $EndComp NoConn ~ 6750 7550 $Comp L +5V #PWR010 U 1 1 54BD75EA P 3400 2500 F 0 "#PWR010" H 3400 2590 20 0001 C CNN F 1 "+5V" H 3400 2590 30 0000 C CNN F 2 "" H 3400 2500 60 0000 C CNN F 3 "" H 3400 2500 60 0000 C CNN 1 3400 2500 -1 0 0 1 $EndComp $Comp L DIODE DZ1 U 1 1 54BD85A3 P 3600 2400 F 0 "DZ1" H 3600 2500 40 0000 C CNN F 1 "ZENER" H 3600 2300 40 0000 C CNN F 2 "~" H 3600 2400 60 0000 C CNN F 3 "~" H 3600 2400 60 0000 C CNN 1 3600 2400 1 0 0 -1 $EndComp $Comp L CONN_20X2 P3 U 1 1 554E0D39 P 1650 5050 F 0 "P3" H 1650 6100 60 0000 C CNN F 1 "EXPANSION_20X2" V 1650 5050 50 0000 C CNN F 2 "" H 1650 5050 60 0000 C CNN F 3 "" H 1650 5050 60 0000 C CNN 1 1650 5050 1 0 0 -1 $EndComp $Comp L +5V #PWR011 U 1 1 554E0D4F P 1100 4100 F 0 "#PWR011" H 1100 4190 20 0001 C CNN F 1 "+5V" H 1100 4190 30 0000 C CNN F 2 "" H 1100 4100 60 0000 C CNN F 3 "" H 1100 4100 60 0000 C CNN 1 1100 4100 0 -1 -1 0 $EndComp NoConn ~ 1250 4200 NoConn ~ 2050 4200 $Comp L +3.3V #PWR012 U 1 1 554E0D7A P 1100 4300 F 0 "#PWR012" H 1100 4260 30 0001 C CNN F 1 "+3.3V" H 1100 4410 30 0000 C CNN F 2 "" H 1100 4300 60 0000 C CNN F 3 "" H 1100 4300 60 0000 C CNN 1 1100 4300 0 -1 -1 0 $EndComp $Comp L GND #PWR013 U 1 1 554E0D8A P 1100 4400 F 0 "#PWR013" H 1100 4400 30 0001 C CNN F 1 "GND" H 1100 4330 30 0001 C CNN F 2 "" H 1100 4400 60 0000 C CNN F 3 "" H 1100 4400 60 0000 C CNN 1 1100 4400 0 1 1 0 $EndComp Text GLabel 1100 4800 0 60 Input ~ 0 SPARE_IO Text GLabel 1100 4500 0 60 Input ~ 0 led7 Text GLabel 1100 4600 0 60 Input ~ 0 led8 Text GLabel 1100 4900 0 60 Input ~ 0 col1 Text GLabel 1100 5000 0 60 Input ~ 0 col2 Text GLabel 1100 5100 0 60 Input ~ 0 col3 Text GLabel 1100 5200 0 60 Input ~ 0 col4 Text GLabel 1100 5300 0 60 Input ~ 0 col5 Text GLabel 1100 5400 0 60 Input ~ 0 col6 Text GLabel 1100 5500 0 60 Input ~ 0 col7 Text GLabel 1100 5600 0 60 Input ~ 0 col8 Text GLabel 1100 5700 0 60 Input ~ 0 col9 Text GLabel 1100 5800 0 60 Input ~ 0 col10 Text GLabel 1100 5900 0 60 Input ~ 0 col11 Text GLabel 1100 6000 0 60 Input ~ 0 col12 Text GLabel 1100 4700 0 60 Input ~ 0 row2 $Comp L CONN_4 P5 U 1 1 554E5206 P 3250 7450 F 0 "P5" V 3200 7450 50 0000 C CNN F 1 "SERIAL 5V TTL" V 3300 7450 50 0000 C CNN F 2 "" H 3250 7450 60 0000 C CNN F 3 "" H 3250 7450 60 0000 C CNN 1 3250 7450 1 0 0 -1 $EndComp $Comp L +5V #PWR014 U 1 1 554E5213 P 2800 7400 F 0 "#PWR014" H 2800 7490 20 0001 C CNN F 1 "+5V" H 2800 7490 30 0000 C CNN F 2 "" H 2800 7400 60 0000 C CNN F 3 "" H 2800 7400 60 0000 C CNN 1 2800 7400 0 -1 -1 0 $EndComp $Comp L R R_S1 U 1 1 554E5219 P 2600 7500 F 0 "R_S1" V 2680 7500 40 0000 C CNN F 1 "300" V 2607 7501 40 0000 C CNN F 2 "~" V 2530 7500 30 0000 C CNN F 3 "~" H 2600 7500 30 0000 C CNN 1 2600 7500 0 1 1 0 $EndComp $Comp L R R_S2 U 1 1 554E5233 P 2600 7300 F 0 "R_S2" V 2680 7300 40 0000 C CNN F 1 "620" V 2607 7301 40 0000 C CNN F 2 "~" V 2530 7300 30 0000 C CNN F 3 "~" H 2600 7300 30 0000 C CNN 1 2600 7300 0 1 1 0 $EndComp Text GLabel 2800 3850 1 60 Input ~ 0 col1 Text GLabel 2800 6000 3 60 Input ~ 0 col2 Text GLabel 2700 4400 1 60 Input ~ 0 col1a Text GLabel 2700 5450 3 60 Input ~ 0 col2a Text GLabel 2900 4400 1 60 Input ~ 0 TX Text GLabel 2900 5450 3 60 Input ~ 0 RX Text Notes 1100 3700 0 31 ~ 0 2 Expansion ports Text Notes 2350 6250 1 31 ~ 0 Serial Port Option jumper.\nWarning: enabling Serial Port requires modification on Raspberry Pi.\nWarning2: circuit board traces 1-2 are added\non the PiDP circuit board to enable default option \n(no serial port, unmodified RPI). Cut traces and \njumper 2-3 to enable serial port after \nmodifying the RPi. Text Notes 2250 6800 0 31 ~ 0 5V TTL compatible serial port (option). \nWarning: requires mod on RPi (remove R23/24)\n & trace cut/jumper on PiDP\nWarning: do not install resistors R_S1/R_S2 until \n this mod has been done\n $Comp L LED DPAUSE2 U 1 1 554E5897 P 10800 2750 F 0 "DPAUSE2" H 10800 2850 50 0000 C CNN F 1 "LED" H 10800 2650 50 0000 C CNN F 2 "~" H 10800 2750 60 0000 C CNN F 3 "~" H 10800 2750 60 0000 C CNN 1 10800 2750 1 0 0 -1 $EndComp $Comp L LED DRUN2 U 1 1 554E589D P 10800 3100 F 0 "DRUN2" H 10800 3200 50 0000 C CNN F 1 "LED" H 10800 3000 50 0000 C CNN F 2 "~" H 10800 3100 60 0000 C CNN F 3 "~" H 10800 3100 60 0000 C CNN 1 10800 3100 1 0 0 -1 $EndComp Text GLabel 10600 2600 1 60 Input ~ 0 led7 Text GLabel 11050 2750 1 60 Input ~ 0 col4 Text GLabel 11050 3100 1 60 Input ~ 0 col5 Text Notes 10550 2250 0 60 ~ 0 LEDs ONLY for\nStraight Eight: $Comp L CONN_3 J_COL1 U 1 1 554F46DF P 2800 4800 F 0 "J_COL1" V 2750 4800 50 0000 C CNN F 1 "CONN_3" V 2850 4800 40 0000 C CNN F 2 "" H 2800 4800 60 0000 C CNN F 3 "" H 2800 4800 60 0000 C CNN 1 2800 4800 0 -1 1 0 $EndComp $Comp L CONN_3 J_COL2 U 1 1 554F46EE P 2800 5050 F 0 "J_COL2" V 2750 5050 50 0000 C CNN F 1 "CONN_3" V 2850 5050 40 0000 C CNN F 2 "" H 2800 5050 60 0000 C CNN F 3 "" H 2800 5050 60 0000 C CNN 1 2800 5050 0 -1 -1 0 $EndComp Wire Wire Line 9300 1050 9300 3600 Connection ~ 9300 1150 Connection ~ 9300 1500 Connection ~ 9300 1850 Connection ~ 9300 2200 Connection ~ 9300 2550 Connection ~ 9300 2900 Connection ~ 9300 3250 Wire Wire Line 9950 1050 9950 2200 Connection ~ 9950 1150 Connection ~ 9950 1500 Connection ~ 9950 1850 Wire Wire Line 9950 2750 9950 3250 Connection ~ 9950 2900 Wire Wire Line 10600 1050 10600 1850 Connection ~ 10600 1150 Connection ~ 10600 1500 Wire Wire Line 11000 1150 11050 1150 Wire Wire Line 11000 1500 11050 1500 Wire Wire Line 11000 1850 11050 1850 Wire Wire Line 10350 1150 10400 1150 Wire Wire Line 10350 1500 10400 1500 Wire Wire Line 10350 1850 10400 1850 Wire Wire Line 10350 2200 10400 2200 Wire Wire Line 9700 1150 9750 1150 Wire Wire Line 9700 1500 9750 1500 Wire Wire Line 9700 1850 9750 1850 Wire Wire Line 9700 2200 9750 2200 Wire Wire Line 9700 2550 9750 2550 Wire Wire Line 9700 2900 9750 2900 Wire Wire Line 9700 3250 9750 3250 Wire Wire Line 9700 3600 9750 3600 Wire Wire Line 5500 3050 8900 3050 Connection ~ 8800 3050 Connection ~ 8500 3050 Connection ~ 8200 3050 Connection ~ 7900 3050 Connection ~ 7600 3050 Connection ~ 7300 3050 Connection ~ 7000 3050 Connection ~ 6700 3050 Connection ~ 6400 3050 Connection ~ 6100 3050 Connection ~ 5800 3050 Wire Wire Line 5500 2000 8900 2000 Connection ~ 5800 2000 Connection ~ 6100 2000 Connection ~ 6400 2000 Connection ~ 6700 2000 Connection ~ 7000 2000 Connection ~ 7300 2000 Connection ~ 7600 2000 Connection ~ 7900 2000 Connection ~ 8200 2000 Connection ~ 8500 2000 Connection ~ 8800 2000 Wire Wire Line 5500 1750 8900 1750 Connection ~ 8800 1750 Connection ~ 8500 1750 Connection ~ 8200 1750 Connection ~ 7900 1750 Connection ~ 7600 1750 Connection ~ 7300 1750 Connection ~ 7000 1750 Connection ~ 6700 1750 Connection ~ 6400 1750 Connection ~ 6100 1750 Connection ~ 5800 1750 Wire Wire Line 5500 700 8900 700 Connection ~ 5800 700 Connection ~ 6100 700 Connection ~ 6400 700 Connection ~ 6700 700 Connection ~ 7000 700 Connection ~ 7300 700 Connection ~ 7600 700 Connection ~ 7900 700 Connection ~ 8200 700 Connection ~ 8500 700 Connection ~ 8800 700 Wire Wire Line 5500 3400 8900 3400 Connection ~ 8800 3400 Connection ~ 8500 3400 Connection ~ 8200 3400 Connection ~ 7900 3400 Connection ~ 7600 3400 Connection ~ 7300 3400 Connection ~ 7000 3400 Connection ~ 6700 3400 Connection ~ 6400 3400 Connection ~ 6100 3400 Connection ~ 5800 3400 Wire Wire Line 6950 1300 7000 1300 Wire Wire Line 7000 1100 7000 1350 Wire Wire Line 7250 1150 7300 1150 Wire Wire Line 7300 1100 7300 1350 Wire Wire Line 7550 1300 7600 1300 Wire Wire Line 7600 1100 7600 1350 Wire Wire Line 7850 1150 7900 1150 Wire Wire Line 7900 1100 7900 1350 Wire Wire Line 8150 1300 8200 1300 Wire Wire Line 8200 1100 8200 1350 Wire Wire Line 8450 1150 8500 1150 Wire Wire Line 8500 1100 8500 1350 Wire Wire Line 8750 1300 8800 1300 Wire Wire Line 8800 1100 8800 1350 Wire Wire Line 10350 2900 10400 2900 Wire Wire Line 10350 3250 10400 3250 Wire Wire Line 5450 3850 5500 3850 Wire Wire Line 5500 3850 5500 3800 Wire Wire Line 5750 4000 5800 4000 Wire Wire Line 5800 4000 5800 3800 Wire Wire Line 6050 3850 6100 3850 Wire Wire Line 6100 3850 6100 3800 Wire Wire Line 6350 4000 6400 4000 Wire Wire Line 6400 4000 6400 3800 Wire Wire Line 6650 3850 6700 3850 Wire Wire Line 6700 3850 6700 3800 Wire Wire Line 8150 4000 8200 4000 Wire Wire Line 8200 4000 8200 3800 Wire Wire Line 8450 3850 8500 3850 Wire Wire Line 8500 3850 8500 3800 Wire Wire Line 8750 4000 8800 4000 Wire Wire Line 8800 4000 8800 3800 Wire Wire Line 3300 4000 3350 4000 Wire Wire Line 3350 4000 3350 3800 Wire Wire Line 3600 3850 3650 3850 Wire Wire Line 3650 3850 3650 3800 Wire Wire Line 3900 4000 3950 4000 Wire Wire Line 3950 4000 3950 3800 Wire Wire Line 4200 3850 4250 3850 Wire Wire Line 4250 3850 4250 3800 Wire Wire Line 4500 4000 4550 4000 Wire Wire Line 4550 4000 4550 3800 Wire Wire Line 3350 3400 4600 3400 Connection ~ 4550 3400 Connection ~ 4250 3400 Connection ~ 3950 3400 Connection ~ 3650 3400 Wire Wire Line 3300 700 4850 700 Connection ~ 3350 700 Connection ~ 3650 700 Connection ~ 3950 700 Connection ~ 4250 700 Connection ~ 4550 700 Wire Wire Line 3300 1150 3350 1150 Wire Wire Line 3350 1150 3350 1100 Wire Wire Line 3600 1300 3650 1300 Wire Wire Line 3650 1300 3650 1100 Wire Wire Line 3900 1150 3950 1150 Wire Wire Line 3950 1150 3950 1100 Wire Wire Line 4200 1300 4250 1300 Wire Wire Line 4250 1300 4250 1100 Wire Wire Line 4500 1150 4550 1150 Wire Wire Line 4550 1150 4550 1100 Wire Wire Line 4800 1300 4850 1300 Wire Wire Line 4850 1300 4850 1100 Wire Wire Line 5150 2650 5200 2650 Wire Wire Line 5150 3050 5200 3050 Wire Wire Line 5450 1150 5500 1150 Wire Wire Line 5500 1100 5500 1350 Wire Wire Line 5750 1300 5800 1300 Wire Wire Line 5800 1100 5800 1350 Wire Wire Line 6050 1150 6100 1150 Wire Wire Line 6100 1100 6100 1350 Wire Wire Line 6350 1300 6400 1300 Wire Wire Line 6400 1100 6400 1350 Wire Wire Line 6650 1150 6700 1150 Wire Wire Line 6700 1100 6700 1350 Wire Wire Line 5450 2450 5500 2450 Wire Wire Line 5500 2400 5500 2650 Wire Wire Line 5750 2600 5800 2600 Wire Wire Line 5800 2400 5800 2650 Wire Wire Line 6050 2450 6100 2450 Wire Wire Line 6100 2400 6100 2650 Wire Wire Line 6350 2600 6400 2600 Wire Wire Line 6400 2400 6400 2650 Wire Wire Line 6650 2450 6700 2450 Wire Wire Line 6700 2400 6700 2650 Wire Wire Line 6950 2600 7000 2600 Wire Wire Line 7000 2400 7000 2650 Wire Wire Line 7250 2450 7300 2450 Wire Wire Line 7300 2400 7300 2650 Wire Wire Line 7550 2600 7600 2600 Wire Wire Line 7600 2400 7600 2650 Wire Wire Line 7850 2450 7900 2450 Wire Wire Line 7900 2400 7900 2650 Wire Wire Line 8150 2600 8200 2600 Wire Wire Line 8200 2400 8200 2650 Wire Wire Line 8450 2450 8500 2450 Wire Wire Line 8500 2400 8500 2650 Wire Wire Line 8750 2600 8800 2600 Wire Wire Line 8800 2400 8800 2650 Wire Wire Line 6950 4000 7000 4000 Wire Wire Line 7000 4000 7000 3800 Wire Wire Line 7250 3850 7300 3850 Wire Wire Line 7300 3850 7300 3800 Wire Wire Line 7550 4000 7600 4000 Wire Wire Line 7600 4000 7600 3800 Wire Wire Line 7850 3850 7900 3850 Wire Wire Line 7900 3850 7900 3800 Wire Wire Line 3750 4250 6100 4250 Wire Wire Line 3800 4250 3800 4300 Wire Wire Line 4250 4250 4250 4300 Connection ~ 3800 4250 Wire Wire Line 4700 4250 4700 4300 Connection ~ 4250 4250 Wire Wire Line 5150 4250 5150 4300 Connection ~ 4700 4250 Wire Wire Line 5650 4250 5650 4300 Connection ~ 5150 4250 Wire Wire Line 6100 4250 6100 4300 Connection ~ 5650 4250 Wire Wire Line 7250 4250 10800 4250 Wire Wire Line 7300 4250 7300 4300 Wire Wire Line 7800 4250 7800 4300 Connection ~ 7300 4250 Wire Wire Line 8300 4250 8300 4300 Connection ~ 7800 4250 Wire Wire Line 8800 4250 8800 4300 Connection ~ 8300 4250 Wire Wire Line 9300 4250 9300 4300 Connection ~ 8800 4250 Wire Wire Line 9800 4250 9800 4300 Connection ~ 9300 4250 Wire Wire Line 10300 4250 10300 4300 Connection ~ 9800 4250 Wire Wire Line 10800 4250 10800 4300 Connection ~ 10300 4250 Wire Wire Line 4900 5750 10000 5750 Wire Wire Line 4950 5750 4950 5800 Wire Wire Line 5400 5750 5400 5800 Connection ~ 4950 5750 Wire Wire Line 5850 5750 5850 5800 Connection ~ 5400 5750 Wire Wire Line 6300 5750 6300 5800 Connection ~ 5850 5750 Wire Wire Line 6800 5750 6800 5800 Connection ~ 6300 5750 Wire Wire Line 7250 5750 7250 5800 Connection ~ 6800 5750 Wire Wire Line 7700 5750 7700 5800 Connection ~ 7250 5750 Wire Wire Line 8150 5750 8150 5800 Connection ~ 7700 5750 Wire Wire Line 8650 5750 8650 5800 Connection ~ 8150 5750 Wire Wire Line 9100 5750 9100 5800 Connection ~ 8650 5750 Wire Wire Line 9550 5750 9550 5800 Connection ~ 9100 5750 Wire Wire Line 10000 5750 10000 5800 Connection ~ 9550 5750 Wire Wire Line 3500 5550 3500 5350 Wire Wire Line 3950 5350 3950 5550 Wire Wire Line 4400 5350 4400 5550 Wire Wire Line 4850 5350 4850 5550 Wire Wire Line 5350 5350 5350 5550 Wire Wire Line 5800 5350 5800 5550 Wire Wire Line 4650 7050 4650 6850 Wire Wire Line 5100 7050 5100 6850 Wire Wire Line 5550 7050 5550 6850 Wire Wire Line 6000 7050 6000 6850 Wire Wire Line 6500 7050 6500 6850 Wire Wire Line 6950 7050 6950 6850 Wire Wire Line 7400 7050 7400 6850 Wire Wire Line 7850 7050 7850 6850 Wire Wire Line 8350 7050 8350 6850 Wire Wire Line 8800 7050 8800 6850 Wire Wire Line 9250 7050 9250 6850 Wire Wire Line 9700 7050 9700 6850 Wire Wire Line 10100 6850 10100 6800 Wire Wire Line 9650 6850 9650 6800 Wire Wire Line 9200 6850 9200 6800 Wire Wire Line 8750 6850 8750 6800 Wire Wire Line 8250 6850 8250 6800 Wire Wire Line 7800 6850 7800 6800 Wire Wire Line 7350 6850 7350 6800 Wire Wire Line 6900 6850 6900 6800 Wire Wire Line 6400 6850 6400 6800 Wire Wire Line 5950 6850 5950 6800 Wire Wire Line 5500 6850 5500 6800 Wire Wire Line 5050 6850 5050 6800 Wire Wire Line 7000 5350 7000 5550 Wire Wire Line 7500 5350 7500 5550 Wire Wire Line 8000 5350 8000 5550 Wire Wire Line 8500 5350 8500 5550 Wire Wire Line 9000 5350 9000 5550 Wire Wire Line 9500 5350 9500 5550 Wire Wire Line 10000 5350 10000 5550 Wire Wire Line 10500 5350 10500 5550 Wire Wire Line 10900 5350 10900 5300 Wire Wire Line 10400 5350 10400 5300 Wire Wire Line 9900 5350 9900 5300 Wire Wire Line 9400 5350 9400 5300 Wire Wire Line 8900 5350 8900 5300 Wire Wire Line 8400 5350 8400 5300 Wire Wire Line 7900 5350 7900 5300 Wire Wire Line 7400 5350 7400 5300 Wire Wire Line 4600 1600 4700 1600 Wire Wire Line 4600 1700 4700 1700 Wire Wire Line 4600 1800 4700 1800 Wire Wire Line 4600 1900 4700 1900 Wire Wire Line 4600 2000 4700 2000 Wire Wire Line 4600 2100 4700 2100 Wire Wire Line 4600 2200 4700 2200 Wire Wire Line 4600 2300 4700 2300 Wire Wire Line 3800 1600 3900 1600 Wire Wire Line 3800 1700 3900 1700 Wire Wire Line 3800 1800 3900 1800 Wire Wire Line 3800 1900 3900 1900 Wire Wire Line 3800 2000 3900 2000 Wire Wire Line 3800 2100 3900 2100 Wire Wire Line 3800 2200 3900 2200 Wire Wire Line 3800 2300 3900 2300 Wire Wire Line 2250 1400 2300 1400 Wire Wire Line 2250 2100 2300 2100 Wire Wire Line 2250 2600 2300 2600 Wire Wire Line 1450 1600 1400 1600 Wire Wire Line 1400 3100 1450 3100 Wire Wire Line 2850 2300 2900 2300 Wire Wire Line 850 2200 800 2200 Wire Wire Line 850 2100 800 2100 Wire Wire Line 850 2300 800 2300 Wire Wire Line 2850 2700 2900 2700 Wire Wire Line 850 2800 800 2800 Wire Wire Line 2850 2900 2900 2900 Wire Wire Line 850 1700 800 1700 Wire Wire Line 2850 1700 2900 1700 Wire Wire Line 800 1500 850 1500 Wire Wire Line 800 2600 850 2600 Wire Wire Line 800 2700 850 2700 Wire Wire Line 2900 2400 2850 2400 Wire Wire Line 1350 1100 1350 1200 Wire Wire Line 4750 2550 4600 2550 Wire Wire Line 4600 2550 4600 2400 Wire Wire Line 3900 5300 3900 5350 Wire Wire Line 4350 5300 4350 5350 Wire Wire Line 4800 5300 4800 5350 Wire Wire Line 5250 5300 5250 5350 Wire Wire Line 5750 5300 5750 5350 Wire Wire Line 6200 5300 6200 5350 Wire Wire Line 2250 1200 2400 1200 Wire Wire Line 2400 1200 2400 1100 Wire Wire Line 800 1900 1450 1900 Wire Wire Line 800 1800 1450 1800 Wire Wire Line 1350 1500 1450 1500 Wire Wire Line 1350 1700 1450 1700 Wire Wire Line 1350 2100 1450 2100 Wire Wire Line 1350 2200 1450 2200 Wire Wire Line 1350 2600 1450 2600 Wire Wire Line 1350 2700 1450 2700 Wire Wire Line 1350 2800 1450 2800 Wire Wire Line 1350 2900 1450 2900 Wire Wire Line 800 3000 1450 3000 Wire Wire Line 2250 1500 2750 1500 Wire Wire Line 2250 1600 2750 1600 Wire Wire Line 2250 1700 2350 1700 Wire Wire Line 2250 2200 2900 2200 Wire Wire Line 2250 1900 2900 1900 Wire Wire Line 2250 2000 2900 2000 Wire Wire Line 2250 2300 2350 2300 Wire Wire Line 2250 2700 2350 2700 Wire Wire Line 2250 2900 2350 2900 Wire Wire Line 2250 3000 2900 3000 Wire Wire Line 2250 3100 2900 3100 Wire Wire Line 1350 2300 1450 2300 Wire Wire Line 2250 2400 2350 2400 Wire Wire Line 2850 7100 2850 7300 Connection ~ 1350 1200 Connection ~ 2250 1200 Wire Wire Line 2250 1200 2250 1300 Wire Wire Line 3800 2400 3900 2400 Wire Wire Line 3400 2500 3400 2400 Connection ~ 5500 1150 Connection ~ 5800 1300 Connection ~ 6100 1150 Connection ~ 6400 1300 Connection ~ 6700 1150 Connection ~ 7000 1300 Connection ~ 7300 1150 Connection ~ 7600 1300 Connection ~ 5500 2450 Connection ~ 6100 2450 Connection ~ 6700 2450 Connection ~ 7300 2450 Connection ~ 5800 2600 Connection ~ 6400 2600 Connection ~ 7000 2600 Connection ~ 7600 2600 Connection ~ 7900 2450 Connection ~ 8200 2600 Connection ~ 8500 2450 Connection ~ 8800 2600 Connection ~ 7900 1150 Connection ~ 8200 1300 Connection ~ 8500 1150 Connection ~ 8800 1300 Wire Wire Line 1100 4100 2050 4100 Connection ~ 1250 4100 Wire Wire Line 1100 4300 2050 4300 Connection ~ 1250 4300 Wire Wire Line 1100 4400 2050 4400 Connection ~ 1250 4400 Wire Wire Line 1100 4500 2050 4500 Connection ~ 1250 4500 Wire Wire Line 1100 4600 2050 4600 Connection ~ 1250 4600 Wire Wire Line 1100 4700 2050 4700 Connection ~ 1250 4700 Connection ~ 1250 4800 Wire Wire Line 1100 4900 2050 4900 Connection ~ 1250 4900 Wire Wire Line 1100 4800 2050 4800 Wire Wire Line 1100 5000 2050 5000 Connection ~ 1250 5000 Wire Wire Line 1100 5100 2050 5100 Connection ~ 1250 5100 Wire Wire Line 1100 5200 2050 5200 Connection ~ 1250 5200 Wire Wire Line 1100 5300 2050 5300 Connection ~ 1250 5300 Wire Wire Line 1100 5400 2050 5400 Connection ~ 1250 5400 Wire Wire Line 1100 5500 2050 5500 Connection ~ 1250 5500 Wire Wire Line 1100 5600 2050 5600 Connection ~ 1250 5600 Wire Wire Line 1100 5700 2050 5700 Connection ~ 1250 5700 Wire Wire Line 1100 5800 2050 5800 Connection ~ 1250 5800 Wire Wire Line 1100 5900 2050 5900 Connection ~ 1250 5900 Wire Wire Line 1100 6000 2050 6000 Connection ~ 1250 6000 Wire Wire Line 2300 7600 2900 7600 Wire Wire Line 2850 7500 2900 7500 Wire Wire Line 2800 7400 2900 7400 Wire Wire Line 2850 7300 2900 7300 Wire Wire Line 2350 7500 2300 7500 Wire Wire Line 800 1400 1450 1400 Wire Wire Line 11000 2750 11050 2750 Wire Wire Line 11000 3100 11050 3100 Wire Wire Line 10600 2600 10600 3100 Connection ~ 10600 2750 Wire Notes Line 11200 2100 10500 2100 Wire Notes Line 10500 2100 10500 3300 Wire Notes Line 10500 3300 11200 3300 Wire Notes Line 11200 3300 11200 2100 Wire Notes Line 1750 6650 3600 6650 Wire Notes Line 3600 6650 3600 7700 Wire Notes Line 3600 7700 1800 7700 Wire Notes Line 1800 7700 1800 6650 Wire Notes Line 2250 6300 3000 6300 Wire Notes Line 3000 6300 3000 3550 Wire Notes Line 3000 3550 2250 3550 Wire Notes Line 2250 3550 2250 6300 Wire Wire Line 2700 5400 2700 5450 Wire Wire Line 2800 5400 2800 5450 Wire Wire Line 2900 5400 2900 5450 Wire Wire Line 2800 5950 2800 6000 Wire Wire Line 2800 3850 2800 3900 Wire Wire Line 2700 4400 2700 4450 Wire Wire Line 2800 4400 2800 4450 Wire Wire Line 2900 4400 2900 4450 Wire Wire Line 2900 7500 2900 7450 Wire Wire Line 2900 7450 2350 7450 Wire Wire Line 2350 7450 2350 7300 Wire Wire Line 1450 1300 800 1300 Wire Wire Line 1350 1200 1450 1200 NoConn ~ 1450 2000 Wire Wire Line 2900 4450 2800 4450 Wire Wire Line 2800 5400 2900 5400 Wire Wire Line 3400 2400 3500 2400 Wire Wire Line 3500 2400 3500 2600 Wire Wire Line 3500 2600 3800 2600 Wire Wire Line 3800 2600 3800 2400 $EndSCHEMATC |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 | (session PDP8.ses (base_design PDP8.dsn) (placement (resolution um 10) (component R3 (place R9 579200 -1029400 back 270) (place R1 376000 -1029400 back 90) (place R2 401400 -1029400 back 90) (place R3 426800 -1029400 back 90) (place R4 452200 -1029400 back 90) (place R5 477600 -1029400 back 90) (place R6 503000 -1029400 back 90) (place R7 528400 -1029400 back 270) (place R8 553800 -1029400 back 270) (place R10 604600 -1029400 back 270) (place R11 630000 -1029400 back 270) (place R12 655400 -1029400 back 270) (place R_ROW1 789000 -1330800 front 0) (place R_ROW2 187500 -1295000 front 180) (place R_ROW3 2186000 -1330800 front 0) (place R_S1 187500 -1330000 front 0) (place R_S2 187500 -1365000 front 0) ) (component "DIP-18__300" (place P2 2190500 -1009700 back 270) ) (component 1pin (place M1 130000 -680000 front 0) (place M2 130000 -1590000 front 0) (place M3 2850000 -680000 front 0) (place M4 2860000 -1590000 front 0) (place M5 2080000 -680000 front 0) (place M6 2850000 -1320000 front 0) (place M7 2080000 -1320000 front 0) ) (component D2 (place D23 2490000 -1365000 front 0) (place D24 2590000 -1365000 front 0) (place D22 2390000 -1365000 front 0) (place D25 2690000 -1365000 front 0) (place D26 2790000 -1365000 front 0) (place D12 1390000 -1365000 front 0) (place D2 390000 -1365000 front 0) (place D3 490000 -1365000 front 0) (place D4 590000 -1365000 front 0) (place D5 690000 -1365000 front 0) (place D6 790000 -1365000 front 0) (place D7 890000 -1365000 front 0) (place D8 990000 -1365000 front 0) (place D9 1090000 -1365000 front 0) (place D10 1190000 -1365000 front 0) (place D11 1290000 -1365000 front 0) (place D1 290000 -1365000 front 0) (place D13 1490000 -1365000 front 0) (place D14 1590000 -1365000 front 0) (place D15 1690000 -1365000 front 0) (place D16 1790000 -1365000 front 0) (place D17 1890000 -1365000 front 0) (place D18 1990000 -1365000 front 0) (place D19 2090000 -1365000 front 0) (place D20 2190000 -1365000 front 0) (place D21 2290000 -1365000 front 0) ) (component RASPI_BPLUS_MIRRORED (place P1 640000 -1240000 back 0) ) (component D3 (place DZ1 2190000 -1170000 front 0) ) (component "LED-3-PDP" (place DMB9 1690000 -998000 front 0) (place DMB10 1790000 -998000 front 0) (place DMB11 1890000 -998000 front 0) (place DMB12 1990000 -998000 front 0) (place DAC1 890000 -1144000 front 0) (place DAC2 990000 -1144000 front 0) (place DAC3 1090000 -1144000 front 0) (place DAC4 1190000 -1144000 front 0) (place DAC5 1290000 -1144000 front 0) (place DAC6 1390000 -1144000 front 0) (place DAC7 1490000 -1144000 front 0) (place DAC8 1590000 -1144000 front 0) (place DAC9 1690000 -1144000 front 0) (place DAC10 1790000 -1144000 front 0) (place DPC1 890000 -706000 front 0) (place DAC12 1990000 -1144000 front 0) (place DMQ1 890000 -1290000 front 0) (place DMQ2 990000 -1290000 front 0) (place DMQ3 1090000 -1290000 front 0) (place DMQ4 1190000 -1290000 front 0) (place DMQ5 1290000 -1290000 front 0) (place DMQ6 1390000 -1290000 front 0) (place DMQ7 1490000 -1290000 front 0) (place DMQ8 1590000 -1290000 front 0) (place DMQ9 1690000 -1290000 front 0) (place DMQ10 1790000 -1290000 front 0) (place DMQ11 1890000 -1290000 front 0) (place DMQ12 1990000 -1290000 front 0) (place DLINK1 790000 -1144000 front 0) (place DSC1 290000 -1290000 front 0) (place DAC11 1890000 -1144000 front 0) (place DPC2 990000 -706000 front 0) (place DPC3 1090000 -706000 front 0) (place DPC4 1190000 -706000 front 0) (place DPC5 1290000 -706000 front 0) (place DPC6 1390000 -706000 front 0) (place DPC7 1490000 -706000 front 0) (place DPC8 1590000 -706000 front 0) (place DPC9 1690000 -706000 front 0) (place DPC10 1790000 -706000 front 0) (place DPC11 1890000 -706000 front 0) (place DPC12 1990000 -706000 front 0) (place DMA1 890000 -852000 front 0) (place DMA2 990000 -852000 front 0) (place DMA3 1090000 -852000 front 0) (place DMB8 1590000 -998000 front 0) (place DMA5 1290000 -852000 front 0) (place DMA6 1390000 -852000 front 0) (place DMA7 1490000 -852000 front 0) (place DMA8 1590000 -852000 front 0) (place DMA9 1690000 -852000 front 0) (place DMA10 1790000 -852000 front 0) (place DMA11 1890000 -852000 front 0) (place DMA12 1990000 -852000 front 0) (place DMB1 890000 -998000 front 0) (place DMB2 990000 -998000 front 0) (place DMB3 1090000 -998000 front 0) (place DMB4 1190000 -998000 front 0) (place DMB5 1290000 -998000 front 0) (place DMB6 1390000 -998000 front 0) (place DMB7 1490000 -998000 front 0) (place DMA4 1190000 -852000 front 0) (place DRUN1 2790000 -852000 front 0) (place DPAUSE1 2790000 -779000 front 0) (place DION1 2790000 -706000 front 0) (place DBREAK1 2590000 -1071000 front 0) (place DCURAD1 2590000 -998000 front 0) (place DWRDCT1 2590000 -925000 front 0) (place DDEFER1 2590000 -852000 front 0) (place DEXEC1 2590000 -779000 front 0) (place DFETCH1 2590000 -706000 front 0) (place DOPR1 2390000 -1217000 front 0) (place DIOT1 2390000 -1144000 front 0) (place DJMP1 2390000 -1071000 front 0) (place DJMS1 2390000 -998000 front 0) (place DDCA1 2390000 -925000 front 0) (place DSC2 390000 -1290000 front 0) (place DSC4 590000 -1290000 front 0) (place DSC5 690000 -1290000 front 0) (place DDF1 290000 -706000 front 0) (place DDF2 390000 -706000 front 0) (place DDF3 490000 -706000 front 0) (place DSC3 490000 -1290000 front 0) (place DTAD1 2390000 -779000 front 0) (place DAND1 2390000 -706000 front 0) (place DISZ1 2390000 -852000 front 0) (place DIF2 690000 -706000 front 0) (place DIF3 790000 -706000 front 0) (place DIF1 590000 -706000 front 0) ) (component SW_KND2_PDP2 (place SW6 790000 -1595000 front 0) (place SW5 690000 -1595000 front 0) (place SW4 590000 -1595000 front 0) (place SW3 490000 -1595000 front 0) (place SW2 390000 -1595000 front 0) (place SW1 290000 -1595000 front 0) (place SW18 1990000 -1595000 front 0) (place SW17 1890000 -1595000 front 0) (place SW15 1690000 -1595000 front 0) (place SW14 1590000 -1595000 front 0) (place SW13 1490000 -1595000 front 0) (place SW12 1390000 -1595000 front 0) (place SW19 2090000 -1595000 front 0) (place SW20 2190000 -1595000 front 0) (place SW16 1790000 -1595000 front 0) (place SW22 2390000 -1595000 front 0) (place SW23 2490000 -1595000 front 0) (place SW24 2590000 -1595000 front 0) (place SW25 2690000 -1595000 front 0) (place SW26 2790000 -1595000 front 0) (place SW7 890000 -1595000 front 0) (place SW8 990000 -1595000 front 0) (place SW9 1090000 -1595000 front 0) (place SW10 1190000 -1595000 front 0) (place SW11 1290000 -1595000 front 0) (place SW21 2290000 -1595000 front 0) ) (component PIN_ARRAY_4x1 (place P5 115000 -1360000 front 270) ) (component PIN_ARRAY_20X2 (place P3 2539000 -1300500 back 180) ) (component "LED-3-StrEight" (place DPAUSE2 2590000 -1144000 front 0) (place DRUN2 2590000 -1217000 front 0) ) (component PIN_ARRAY_3X1 (place J_COL1 643000 -1118000 back 180) (place J_COL2 643000 -1152000 back 180) ) ) (was_is ) (routes (resolution um 10) (parser (host_cad "KiCad's Pcbnew") (host_version "(2013-07-07 BZR 4022)-stable") ) (library_out (padstack "Via[0-1]_889:635_um" (shape (circle F.Cu 8890 0 0) ) (shape (circle B.Cu 8890 0 0) ) (attach off) ) (padstack "Via[0-1]_889:0_um" (shape (circle F.Cu 8890 0 0) ) (shape (circle B.Cu 8890 0 0) ) (attach off) ) ) (network_out (net +3.3V (wire (path F.Cu 3810 893368 -1227300 913651 -1207017 1290368 -1207017 1308107 -1224756 1308107 -1239060 1377069 -1308022 2011889 -1308022 2044180 -1275731 2336431 -1275731 2348500 -1287800 ) ) (wire (path F.Cu 3810 881300 -1227300 893368 -1227300 ) ) (wire (path B.Cu 3810 2348500 -1287800 2348500 -1313200 ) ) ) (net +5V (wire (path F.Cu 3810 2151900 -1170000 2116585 -1205315 1384946 -1205315 1379892 -1200261 886410 -1200261 869231 -1217440 869231 -1240631 881300 -1252700 ) ) (wire (path F.Cu 3810 855900 -1252700 761300 -1347300 115000 -1347300 ) ) (wire (path B.Cu 3810 881300 -1252700 855900 -1252700 ) ) (wire (path F.Cu 3810 2297700 -1287800 2297700 -1299868 ) ) (wire (path F.Cu 3810 2297700 -1313200 2297700 -1299868 ) ) (wire (path B.Cu 3810 2297700 -1287800 2285632 -1287800 ) ) (wire (path B.Cu 3810 2285632 -1287800 2167832 -1170000 2151900 -1170000 ) ) ) (net GND (wire (path B.Cu 3810 2373900 -1287800 2298356 -1212256 2298356 -977856 2228600 -908100 ) ) (wire (path B.Cu 3810 2373900 -1313200 2373900 -1287800 ) ) (wire (path B.Cu 3810 792400 -1257101 784638 -1264863 664863 -1264863 652700 -1252700 ) ) (wire (path B.Cu 3810 792400 -1257101 792400 -1240000 779700 -1227300 ) ) (wire (path B.Cu 3810 792400 -1257101 800256 -1264957 818243 -1264957 830500 -1252700 ) ) (wire (path B.Cu 3810 115000 -1321900 127068 -1321900 ) ) (wire (path B.Cu 3810 127068 -1321900 130612 -1318356 154053 -1318356 160929 -1325232 160929 -1353471 149400 -1365000 ) ) (wire (path F.Cu 3810 398700 -1227300 411400 -1240000 513000 -1240000 525700 -1252700 ) ) (wire (path F.Cu 3810 364101 -1206624 378024 -1206624 398700 -1227300 ) ) (wire (path F.Cu 3810 652700 -1252700 640631 -1264769 537769 -1264769 525700 -1252700 ) ) (wire (path F.Cu 3810 127068 -1321900 139384 -1321900 254660 -1206624 364101 -1206624 ) ) (wire (path F.Cu 3810 2228600 -908100 2216749 -919951 1100418 -919951 1019637 -839170 511529 -839170 364101 -986598 364101 -1206624 ) ) (wire (path F.Cu 3810 115000 -1321900 127068 -1321900 ) ) ) (net "N-0000023" (wire (path B.Cu 2540 2228100 -1170000 2228100 -1159202 ) ) (wire (path B.Cu 2540 2228100 -1159202 2167001 -1098103 2167001 -922701 2152400 -908100 ) ) ) (net "N-0000028" (wire (path F.Cu 2540 643000 -1118000 631567 -1106567 551911 -1106567 515700 -1070356 515700 -1064381 502323 -1051004 392496 -1051004 376000 -1067500 ) ) ) (net "N-0000029" (wire (path B.Cu 2540 643000 -1152000 631566 -1140566 619213 -1140566 606166 -1127519 606166 -1107927 626625 -1087468 650924 -1087468 666200 -1072192 666200 -1062830 644354 -1040984 427916 -1040984 401400 -1067500 ) ) ) (net "N-0000035" (wire (path F.Cu 2540 115000 -1372700 118419 -1376119 214481 -1376119 225600 -1365000 ) ) (wire (path B.Cu 2540 115000 -1372700 149400 -1338300 149400 -1330000 ) ) ) (net "N-0000039" (wire (path B.Cu 2540 576500 -1252700 563800 -1240000 563800 -1223523 503000 -1162723 503000 -1067500 ) ) ) (net "N-0000040" (wire (path B.Cu 2540 601900 -1227300 542629 -1168029 542629 -1063326 549319 -1056636 593736 -1056636 604600 -1067500 ) ) ) (net "N-0000041" (wire (path B.Cu 2540 449500 -1252700 458311 -1252700 490000 -1284389 490000 -1294620 526180 -1330800 750900 -1330800 ) ) ) (net "N-0000042" (wire (path B.Cu 2540 500300 -1252700 514266 -1238734 530434 -1238734 537535 -1231633 537535 -1220894 492201 -1175560 492201 -1062927 503589 -1051539 614039 -1051539 630000 -1067500 ) ) ) (net "N-0000043" (wire (path B.Cu 2540 601900 -1252700 589200 -1240000 589200 -1221790 528400 -1160990 528400 -1067500 ) ) ) (net "N-0000046" (wire (path F.Cu 2540 754300 -1252700 765788 -1241212 860806 -1241212 868600 -1249006 868600 -1256571 884342 -1272313 977570 -1272313 990000 -1284743 990000 -1294994 1008747 -1313741 2032306 -1313741 2062707 -1344142 2105187 -1344142 2118529 -1330800 2147900 -1330800 ) ) ) (net "N-0000048" (wire (path B.Cu 2540 655400 -1067500 633967 -1046067 432397 -1046067 415681 -1062783 415681 -1072465 475614 -1132398 475614 -1226586 474900 -1227300 ) ) ) (net "N-0000049" (wire (path B.Cu 2540 500300 -1227300 480697 -1207697 480697 -1112509 441005 -1072817 441005 -1063223 447939 -1056289 466389 -1056289 477600 -1067500 ) ) ) (net "N-0000050" (wire (path B.Cu 2540 525700 -1227300 485781 -1187381 485781 -1101081 452200 -1067500 ) ) ) (net "N-0000053" (wire (path B.Cu 2540 790000 -1539200 790000 -1522687 ) ) (wire (path B.Cu 2540 790000 -1522687 825560 -1487127 825560 -1365000 ) ) ) (net "N-0000054" (wire (path B.Cu 2540 627300 -1227300 587011 -1187011 587011 -1100711 553800 -1067500 ) ) ) (net "N-0000055" (wire (path B.Cu 2540 652700 -1227300 594636 -1169236 594636 -1082936 579200 -1067500 ) ) ) (net "N-0000056" (wire (path F.Cu 2540 754300 -1227300 740334 -1241266 698766 -1241266 690800 -1249232 690800 -1256341 674806 -1272335 248265 -1272335 225600 -1295000 ) ) ) (net "N-0000057" (wire (path F.Cu 2540 426800 -1067500 426800 -1142787 496975 -1212962 790762 -1212962 805100 -1227300 ) ) ) (net "N-0000059" (wire (path B.Cu 2540 690000 -1539200 690000 -1522687 ) ) (wire (path B.Cu 2540 690000 -1522687 725560 -1487127 725560 -1365000 ) ) ) (net "N-0000060" (wire (path B.Cu 2540 590000 -1539200 590000 -1522687 ) ) (wire (path B.Cu 2540 590000 -1522687 625560 -1487127 625560 -1365000 ) ) ) (net "N-0000061" (wire (path B.Cu 2540 490000 -1539200 490000 -1522687 ) ) (wire (path B.Cu 2540 490000 -1522687 525560 -1487127 525560 -1365000 ) ) ) (net "N-0000062" (wire (path F.Cu 2540 390000 -1539200 390000 -1522687 ) ) (wire (path F.Cu 2540 390000 -1522687 425560 -1487127 425560 -1365000 ) ) ) (net "N-0000063" (wire (path B.Cu 2540 290000 -1539200 290000 -1522687 ) ) (wire (path B.Cu 2540 290000 -1522687 325560 -1487127 325560 -1365000 ) ) ) (net "N-0000065" (wire (path B.Cu 2540 2390000 -1539200 2390000 -1522687 ) ) (wire (path B.Cu 2540 2390000 -1522687 2425560 -1487127 2425560 -1365000 ) ) ) (net "N-0000066" (wire (path B.Cu 2540 2490000 -1539200 2490000 -1522687 ) ) (wire (path B.Cu 2540 2490000 -1522687 2525560 -1487127 2525560 -1365000 ) ) ) (net "N-0000067" (wire (path B.Cu 2540 2590000 -1539200 2590000 -1522687 ) ) (wire (path B.Cu 2540 2590000 -1522687 2625560 -1487127 2625560 -1365000 ) ) ) (net "N-0000068" (wire (path B.Cu 2540 2690000 -1539200 2690000 -1522687 ) ) (wire (path B.Cu 2540 2690000 -1522687 2725560 -1487127 2725560 -1365000 ) ) ) (net "N-0000069" (wire (path F.Cu 2540 2790000 -1539200 2790000 -1522687 ) ) (wire (path F.Cu 2540 2790000 -1522687 2825560 -1487127 2825560 -1365000 ) ) ) (net "N-0000070" (wire (path F.Cu 2540 2290000 -1539200 2290000 -1522687 ) ) (wire (path F.Cu 2540 2290000 -1522687 2325560 -1487127 2325560 -1365000 ) ) ) (net "N-0000071" (wire (path B.Cu 2540 890000 -1539200 890000 -1522687 ) ) (wire (path B.Cu 2540 890000 -1522687 925560 -1487127 925560 -1365000 ) ) ) (net "N-0000072" (wire (path B.Cu 2540 990000 -1539200 990000 -1522687 ) ) (wire (path B.Cu 2540 990000 -1522687 1025560 -1487127 1025560 -1365000 ) ) ) (net "N-0000073" (wire (path B.Cu 2540 1090000 -1539200 1090000 -1522687 ) ) (wire (path B.Cu 2540 1090000 -1522687 1125560 -1487127 1125560 -1365000 ) ) ) (net "N-0000074" (wire (path B.Cu 2540 1190000 -1539200 1190000 -1522687 ) ) (wire (path B.Cu 2540 1190000 -1522687 1225560 -1487127 1225560 -1365000 ) ) ) (net "N-0000079" (wire (path B.Cu 2540 1290000 -1522687 1325560 -1487127 1325560 -1375798 ) ) (wire (path B.Cu 2540 1325560 -1365000 1325560 -1375798 ) ) (wire (path B.Cu 2540 1290000 -1539200 1290000 -1522687 ) ) ) (net "N-0000085" (wire (path B.Cu 2540 2090000 -1539200 2090000 -1522687 ) ) (wire (path B.Cu 2540 2090000 -1522687 2125560 -1487127 2125560 -1365000 ) ) ) (net "N-0000086" (wire (path B.Cu 2540 2190000 -1539200 2190000 -1522687 ) ) (wire (path B.Cu 2540 2190000 -1522687 2225560 -1487127 2225560 -1365000 ) ) ) (net "N-0000087" (wire (path F.Cu 2540 1390000 -1539200 1390000 -1522687 ) ) (wire (path F.Cu 2540 1390000 -1522687 1425560 -1487127 1425560 -1365000 ) ) ) (net "N-0000088" (wire (path B.Cu 2540 1490000 -1539200 1490000 -1522687 ) ) (wire (path B.Cu 2540 1490000 -1522687 1525560 -1487127 1525560 -1365000 ) ) ) (net "N-0000089" (wire (path F.Cu 2540 1590000 -1539200 1590000 -1522687 ) ) (wire (path F.Cu 2540 1590000 -1522687 1625560 -1487127 1625560 -1365000 ) ) ) (net "N-0000090" (wire (path F.Cu 2540 1690000 -1539200 1690000 -1522687 ) ) (wire (path F.Cu 2540 1690000 -1522687 1725560 -1487127 1725560 -1365000 ) ) ) (net "N-0000091" (wire (path B.Cu 2540 1790000 -1539200 1790000 -1522687 ) ) (wire (path B.Cu 2540 1790000 -1522687 1825560 -1487127 1825560 -1365000 ) ) ) (net "N-0000092" (wire (path B.Cu 2540 1890000 -1539200 1890000 -1522687 ) ) (wire (path B.Cu 2540 1890000 -1522687 1925560 -1487127 1925560 -1365000 ) ) ) (net "N-0000093" (wire (path B.Cu 2540 1990000 -1539200 1990000 -1522687 ) ) (wire (path B.Cu 2540 1990000 -1522687 2025560 -1487127 2025560 -1365000 ) ) ) (net RX (wire (path B.Cu 2540 668400 -1152000 671787 -1148613 732959 -1148613 767000 -1182654 767000 -1240000 779700 -1252700 ) ) (wire (path F.Cu 2540 779700 -1252700 702400 -1330000 225600 -1330000 ) ) ) (net SPARE_IO (wire (path B.Cu 2540 449500 -1227300 463466 -1241266 479661 -1241266 487600 -1249205 487600 -1256169 548876 -1317445 718670 -1317445 721583 -1314532 848598 -1314532 857128 -1323062 926456 -1323062 982540 -1266978 1619792 -1266978 1622826 -1270012 ) ) (wire (path F.Cu 2540 2475500 -1287800 2457712 -1270012 1622826 -1270012 ) ) (via "Via[0-1]_889:635_um" 1622826 -1270012 ) (wire (path F.Cu 2540 2475500 -1287800 2475500 -1313200 ) ) ) (net TX (wire (path B.Cu 2540 668400 -1118000 712498 -1118000 817006 -1222508 817006 -1240794 805100 -1252700 ) ) (wire (path F.Cu 2540 805100 -1252700 716849 -1340951 135623 -1340951 129910 -1335238 110826 -1335238 103482 -1342582 103482 -1386582 115000 -1398100 ) ) ) (net col1 (wire (path F.Cu 2540 902700 -1319828 897072 -1319828 851900 -1365000 ) ) (wire (path F.Cu 2540 2051900 -1365000 2006728 -1319828 902700 -1319828 ) ) (wire (path F.Cu 2540 902700 -1319828 902700 -1290000 ) ) (wire (path F.Cu 2540 2051900 -1365000 2095110 -1365000 2115968 -1344142 2469958 -1344142 2500900 -1313200 ) ) (wire (path F.Cu 2540 902700 -980060 902700 -852000 ) ) (wire (path F.Cu 2540 902700 -998000 902700 -980060 ) ) (wire (path F.Cu 2540 902700 -980060 387240 -980060 376000 -991300 ) ) (wire (path B.Cu 2540 2402700 -766805 2397650 -766805 2390505 -773950 2390505 -807429 2424985 -841909 2424985 -910277 2500900 -986192 2500900 -1287800 ) ) (wire (path B.Cu 2540 2602700 -998000 2590197 -1010503 2572282 -1010503 2450476 -888697 2450476 -809530 2407751 -766805 2402700 -766805 ) ) (wire (path B.Cu 2540 2402700 -766805 2402700 -706000 ) ) (wire (path B.Cu 2540 2500900 -1313200 2500900 -1287800 ) ) (wire (path B.Cu 2540 902700 -852000 897645 -846945 897645 -711055 902700 -706000 ) ) (wire (path B.Cu 2540 902700 -1144000 902700 -998000 ) ) (wire (path B.Cu 2540 376000 -991300 251900 -1115400 251900 -1365000 ) ) (wire (path B.Cu 2540 302700 -706000 302700 -918000 376000 -991300 ) ) (wire (path B.Cu 2540 902700 -1290000 897475 -1284775 897475 -1149225 902700 -1144000 ) ) ) (net col10 (wire (path B.Cu 2540 2602700 -779000 2564706 -816994 2564706 -934782 2729500 -1099576 2729500 -1287800 ) ) (wire (path F.Cu 2540 1802700 -706000 1820450 -723750 2119706 -723750 2149900 -693556 2583066 -693556 2590000 -700490 2590000 -766300 2602700 -779000 ) ) (wire (path B.Cu 2540 1802700 -998000 1802700 -1061727 1707700 -1156727 1701121 -1156727 1690327 -1167521 1690327 -1167769 1621397 -1236699 979385 -1236699 913517 -1302567 872621 -1302567 860054 -1290000 844466 -1290000 ) ) (wire (path B.Cu 2540 844466 -1290000 702700 -1290000 ) ) (wire (path B.Cu 2540 844466 -1290000 844466 -1247966 852432 -1240000 860267 -1240000 867466 -1232801 867466 -1190925 684168 -1007627 620927 -1007627 604600 -991300 ) ) (wire (path B.Cu 2540 1802700 -852000 1802700 -998000 ) ) (wire (path B.Cu 2540 2729500 -1313200 2729500 -1287800 ) ) (wire (path B.Cu 2540 1802700 -1290000 1802700 -1314200 1751900 -1365000 ) ) (wire (path B.Cu 2540 1802700 -1144000 1802700 -1290000 ) ) (wire (path F.Cu 2540 1802700 -998000 1802700 -1144000 ) ) (wire (path B.Cu 2540 1802700 -706000 1802700 -852000 ) ) ) (net col11 (wire (path B.Cu 2540 2754900 -1287800 2754900 -1096506 2590000 -931606 2590000 -864700 2602700 -852000 ) ) (wire (path B.Cu 2540 2754900 -1313200 2754900 -1287800 ) ) (wire (path F.Cu 2540 2602700 -852000 2615335 -864635 2615335 -929633 2607730 -937238 2502897 -937238 2440222 -874563 1925263 -874563 1902700 -852000 ) ) (wire (path B.Cu 2540 1902700 -852000 1902700 -998000 ) ) (wire (path B.Cu 2540 1902700 -706000 1902700 -852000 ) ) (wire (path F.Cu 2540 1902700 -998000 1902700 -1144000 ) ) (wire (path B.Cu 2540 1902700 -706000 1884949 -688249 877805 -688249 683427 -882627 683427 -978664 659879 -1002212 640912 -1002212 630000 -991300 ) ) (wire (path B.Cu 2540 1902700 -1290000 1902700 -1314200 1851900 -1365000 ) ) (wire (path B.Cu 2540 1902700 -1144000 1902700 -1290000 ) ) ) (net col12 (wire (path F.Cu 2540 2002700 -1144000 2002700 -1130259 2030340 -1102619 ) ) (wire (path B.Cu 2540 2002700 -998000 2002700 -1074979 2030340 -1102619 ) ) (wire (path B.Cu 2540 1994465 -839286 1972445 -839286 1965105 -846626 1965105 -960405 2002700 -998000 ) ) (via "Via[0-1]_889:635_um" 2030340 -1102619 ) (wire (path B.Cu 2540 1994465 -839286 1994465 -843765 2002700 -852000 ) ) (wire (path B.Cu 2540 1994465 -718196 1994465 -839286 ) ) (wire (path B.Cu 2540 1994465 -718196 2002700 -709961 2002700 -706000 ) ) (wire (path B.Cu 2540 655400 -991300 655400 -902970 875205 -683165 1903320 -683165 1938351 -718196 1994465 -718196 ) ) (wire (path B.Cu 2540 2780300 -1287800 2780300 -1102600 2602700 -925000 ) ) (wire (path B.Cu 2540 2780300 -1313200 2780300 -1287800 ) ) (wire (path F.Cu 2540 2602700 -925000 2547039 -869339 2020039 -869339 2002700 -852000 ) ) (wire (path B.Cu 2540 1970417 -1302410 1970417 -1346483 1951900 -1365000 ) ) (wire (path B.Cu 2540 2002700 -1144000 1965005 -1181695 1965005 -1296998 1970417 -1302410 ) ) (wire (path B.Cu 2540 1970417 -1302410 1990290 -1302410 2002700 -1290000 ) ) ) (net col1a (wire (path B.Cu 2540 855900 -1227300 832312 -1203712 811814 -1203712 714668 -1106566 637609 -1106566 629033 -1115142 629033 -1118000 ) ) (wire (path B.Cu 2540 617600 -1118000 629033 -1118000 ) ) ) (net col2 (wire (path F.Cu 2540 2151900 -1365000 2140935 -1375965 1985324 -1375965 1953253 -1343894 973006 -1343894 951900 -1365000 ) ) (wire (path F.Cu 2540 2526300 -1313200 2487734 -1351766 2165134 -1351766 2151900 -1365000 ) ) (wire (path B.Cu 2540 2572572 -1058449 2590149 -1058449 2602700 -1071000 ) ) (wire (path B.Cu 2540 2526300 -1287800 2526300 -1104721 2572572 -1058449 ) ) (wire (path B.Cu 2540 2572572 -1058449 2572572 -1017981 2445392 -890801 2445392 -821692 2402700 -779000 ) ) (wire (path B.Cu 2540 401400 -991300 264733 -1127967 264733 -1294831 291142 -1321240 308140 -1321240 351900 -1365000 ) ) (wire (path B.Cu 2540 402700 -706000 402700 -990000 401400 -991300 ) ) (wire (path F.Cu 2540 1002700 -1290000 1002700 -1228440 ) ) (wire (path B.Cu 2540 1002700 -1228440 1002700 -1144000 ) ) (wire (path B.Cu 2540 1002700 -1144000 1002700 -998000 ) ) (via "Via[0-1]_889:635_um" 1002700 -1228440 ) (wire (path F.Cu 2540 1002700 -706000 990172 -693472 654471 -693472 629540 -718403 415103 -718403 402700 -706000 ) ) (wire (path F.Cu 2540 1002700 -998000 1002700 -852000 ) ) (wire (path B.Cu 2540 2526300 -1313200 2526300 -1287800 ) ) (wire (path B.Cu 2540 1002700 -1290000 1002700 -1314200 951900 -1365000 ) ) (wire (path B.Cu 2540 1002700 -852000 1002700 -706000 ) ) ) (net col2a (wire (path F.Cu 2540 617600 -1152000 629033 -1152000 ) ) (wire (path F.Cu 2540 629033 -1152000 629033 -1154858 680123 -1205948 809148 -1205948 830500 -1227300 ) ) ) (net col3 (wire (path B.Cu 2540 426800 -991300 422334 -991300 290000 -1123634 290000 -1295160 338877 -1344037 430937 -1344037 451900 -1365000 ) ) (wire (path B.Cu 2540 502700 -706000 426800 -781900 426800 -991300 ) ) (wire (path F.Cu 2540 2251900 -1365000 2235851 -1381049 1983220 -1381049 1951149 -1348978 1067922 -1348978 1051900 -1365000 ) ) (wire (path B.Cu 2540 2488200 -1316770 2488200 -985930 2402700 -900430 2402700 -852000 ) ) (wire (path B.Cu 2540 2551700 -1313200 2539781 -1325119 2496549 -1325119 2488200 -1316770 ) ) (wire (path B.Cu 2540 2488200 -1316770 2468371 -1336599 2280301 -1336599 2251900 -1365000 ) ) (wire (path B.Cu 2540 2551700 -1287800 2551700 -1313200 ) ) (wire (path F.Cu 2540 1102700 -1290000 1102700 -1228440 ) ) (wire (path B.Cu 2540 1102700 -1144000 1102700 -1228440 ) ) (wire (path B.Cu 2540 1102700 -998000 1102700 -1144000 ) ) (wire (path B.Cu 2540 1102700 -852000 1102700 -998000 ) ) (wire (path F.Cu 2540 1102700 -706000 1080006 -683306 525394 -683306 502700 -706000 ) ) (wire (path F.Cu 2540 2402700 -852000 2414956 -864256 2582306 -864256 2590000 -856562 2590000 -847385 2708089 -729296 2779404 -729296 2802700 -706000 ) ) (wire (path B.Cu 2540 1102700 -706000 1102700 -852000 ) ) (via "Via[0-1]_889:635_um" 1102700 -1228440 ) (wire (path B.Cu 2540 1102700 -1290000 1102700 -1314200 1051900 -1365000 ) ) ) (net col4 (wire (path F.Cu 2540 1151900 -1365000 1141101 -1375799 798427 -1375799 776829 -1354201 562699 -1354201 551900 -1365000 ) ) (wire (path B.Cu 2540 2577100 -1287800 2577100 -1313200 ) ) (wire (path B.Cu 2540 2602700 -1144000 2590000 -1156700 2590000 -1274900 2577100 -1287800 ) ) (wire (path F.Cu 2540 2584450 -1106750 2602700 -1125000 2602700 -1144000 ) ) (wire (path F.Cu 2540 2402700 -925000 2584450 -1106750 ) ) (wire (path F.Cu 2540 2584450 -1106750 2790000 -901200 2790000 -791700 2802700 -779000 ) ) (wire (path F.Cu 2540 1202700 -852000 1246336 -895636 2373336 -895636 2402700 -925000 ) ) (wire (path B.Cu 2540 452200 -991300 452200 -856500 602700 -706000 ) ) (wire (path F.Cu 2540 1202700 -1290000 1202700 -1228440 ) ) (wire (path B.Cu 2540 1202700 -1144000 1202700 -1228440 ) ) (wire (path B.Cu 2540 1202700 -1290000 1202700 -1314200 1151900 -1365000 ) ) (wire (path F.Cu 2540 1202700 -706000 1190492 -718208 1038889 -718208 1009070 -688389 620311 -688389 602700 -706000 ) ) (wire (path B.Cu 2540 2351900 -1365000 2374911 -1341989 2548311 -1341989 2577100 -1313200 ) ) (wire (path B.Cu 2540 1202700 -998000 1202700 -1144000 ) ) (wire (path B.Cu 2540 1202700 -852000 1202700 -998000 ) ) (wire (path B.Cu 2540 1202700 -706000 1202700 -852000 ) ) (via "Via[0-1]_889:635_um" 1202700 -1228440 ) ) (net col5 (wire (path F.Cu 2540 1302700 -998000 1352674 -948026 2352726 -948026 2402700 -998000 ) ) (wire (path F.Cu 2540 2584412 -1179711 2402700 -998000 ) ) (wire (path F.Cu 2540 1285409 -723291 1302700 -706000 ) ) (wire (path F.Cu 2540 702700 -706000 714958 -718258 914410 -718258 915172 -717496 964914 -717496 970709 -723291 1285409 -723291 ) ) (wire (path F.Cu 2540 1302700 -852000 1302700 -740582 1285409 -723291 ) ) (wire (path F.Cu 2540 2602700 -1217000 2602700 -1198000 2584412 -1179711 ) ) (wire (path F.Cu 2540 2802700 -852000 2802700 -961423 2584412 -1179711 ) ) (wire (path B.Cu 2540 702700 -706000 702700 -766200 477600 -991300 ) ) (wire (path B.Cu 2540 2602500 -1287800 2602500 -1313200 ) ) (wire (path B.Cu 2540 2602700 -1217000 2602500 -1217200 2602500 -1287800 ) ) (wire (path F.Cu 2540 1251900 -1365000 1230860 -1386040 672940 -1386040 651900 -1365000 ) ) (wire (path B.Cu 2540 1302700 -1290000 1302700 -1314200 1251900 -1365000 ) ) (wire (path B.Cu 2540 1302700 -1144000 1302700 -1224954 1299214 -1228440 ) ) (wire (path F.Cu 2540 1302700 -1290000 1299214 -1286514 1299214 -1228440 ) ) (wire (path B.Cu 2540 2451900 -1365000 2466850 -1350050 2565650 -1350050 2602500 -1313200 ) ) (via "Via[0-1]_889:635_um" 1299214 -1228440 ) (wire (path B.Cu 2540 1302700 -998000 1302700 -1144000 ) ) (wire (path B.Cu 2540 1302700 -852000 1302700 -998000 ) ) ) (net col6 (wire (path F.Cu 2540 1402700 -998000 1420560 -1015860 1612551 -1015860 1653282 -975129 2125019 -975129 2148688 -998798 2235908 -998798 2287164 -1050054 2381754 -1050054 2402700 -1071000 ) ) (wire (path B.Cu 2540 503000 -991300 765293 -729007 779693 -729007 802700 -706000 ) ) (wire (path B.Cu 2540 311683 -1290000 311683 -1109141 400177 -1020647 473653 -1020647 503000 -991300 ) ) (wire (path F.Cu 2540 1402700 -1228050 1402700 -1290000 ) ) (wire (path B.Cu 2540 1402700 -1144000 1402700 -1228050 ) ) (wire (path B.Cu 2540 751900 -1365000 725853 -1338953 360636 -1338953 311683 -1290000 ) ) (via "Via[0-1]_889:635_um" 1402700 -1228050 ) (wire (path B.Cu 2540 1402700 -998000 1402700 -1144000 ) ) (wire (path B.Cu 2540 1402700 -1290000 1402700 -1314200 1351900 -1365000 ) ) (wire (path F.Cu 2540 2627900 -1287800 2411100 -1071000 2402700 -1071000 ) ) (wire (path F.Cu 2540 1351900 -1365000 1341101 -1354201 1194682 -1354201 1167935 -1380948 767848 -1380948 751900 -1365000 ) ) (wire (path B.Cu 2540 311683 -1290000 302700 -1290000 ) ) (wire (path B.Cu 2540 1402700 -998000 1402700 -852000 ) ) (wire (path B.Cu 2540 1402700 -706000 1402700 -852000 ) ) (wire (path B.Cu 2540 2627900 -1313200 2576100 -1365000 2551900 -1365000 ) ) (wire (path B.Cu 2540 2627900 -1287800 2627900 -1313200 ) ) ) (net col7 (wire (path B.Cu 2540 802700 -1144000 790503 -1156197 771780 -1156197 646395 -1030812 567912 -1030812 528400 -991300 ) ) (wire (path B.Cu 2540 528400 -991300 484585 -1035115 418307 -1035115 387266 -1066156 387266 -1274566 402700 -1290000 ) ) (wire (path B.Cu 2540 1502700 -1290000 1502700 -1314200 1451900 -1365000 ) ) (wire (path F.Cu 2540 1580419 -1215844 2330856 -1215844 2402700 -1144000 ) ) (wire (path F.Cu 2540 1502700 -1290000 1576856 -1215844 1580419 -1215844 ) ) (wire (path F.Cu 2540 2641571 -1299529 2641571 -1301471 2653300 -1313200 ) ) (wire (path F.Cu 2540 2653300 -1287800 2641571 -1299529 ) ) (wire (path F.Cu 2540 2641571 -1299529 2623462 -1299529 2615200 -1291267 2615200 -1284253 2474947 -1144000 2402700 -1144000 ) ) (wire (path B.Cu 2540 1502700 -1144000 1508575 -1144000 1580419 -1215844 ) ) (wire (path B.Cu 2540 1502700 -998000 1502700 -1144000 ) ) (via "Via[0-1]_889:635_um" 1580419 -1215844 ) (wire (path B.Cu 2540 1502700 -852000 1502700 -998000 ) ) (wire (path F.Cu 2540 1502700 -1144000 1490412 -1156288 814988 -1156288 802700 -1144000 ) ) (wire (path B.Cu 2540 2653300 -1313200 2653300 -1363600 2651900 -1365000 ) ) (wire (path B.Cu 2540 1502700 -852000 1502700 -706000 ) ) ) (net col8 (wire (path B.Cu 2540 1602700 -852000 1602700 -706000 ) ) (wire (path B.Cu 2540 1602700 -1010468 1572441 -1010468 1564896 -1002923 1564896 -889804 1602700 -852000 ) ) (wire (path B.Cu 2540 553800 -991300 542967 -980467 523962 -980467 517499 -986930 517499 -992073 483842 -1025730 402357 -1025730 317164 -1110923 317164 -1253492 344426 -1280754 ) ) (wire (path B.Cu 2540 1622028 -1224390 1602700 -1205062 1602700 -1144000 ) ) (via "Via[0-1]_889:635_um" 1622028 -1224390 ) (wire (path F.Cu 2540 1630305 -1232667 1602700 -1260272 1602700 -1290000 ) ) (wire (path F.Cu 2540 2402700 -1217000 2387033 -1232667 1630305 -1232667 ) ) (wire (path F.Cu 2540 1630305 -1232667 1622028 -1224390 ) ) (wire (path B.Cu 2540 1602700 -1010468 1602700 -998000 ) ) (wire (path B.Cu 2540 1602700 -1144000 1602700 -1010468 ) ) (wire (path B.Cu 2540 502700 -1290000 535228 -1322528 720775 -1322528 723687 -1319616 833665 -1319616 864229 -1350180 930720 -1350180 936932 -1356392 936932 -1365769 947424 -1376261 980985 -1376261 1047575 -1309671 1074969 -1309671 1090000 -1294640 1090000 -1285169 1103090 -1272079 1584779 -1272079 1602700 -1290000 ) ) (wire (path F.Cu 2540 502700 -1290000 490476 -1302224 450282 -1302224 425862 -1277804 347376 -1277804 344426 -1280754 ) ) (wire (path B.Cu 2540 1602700 -1290000 1602700 -1314200 1551900 -1365000 ) ) (via "Via[0-1]_889:635_um" 344426 -1280754 ) (wire (path F.Cu 2540 2678700 -1313200 2667097 -1324803 2623000 -1324803 2613934 -1315737 2613934 -1308466 2604702 -1299234 2597766 -1299234 2589800 -1291268 2589800 -1284209 2570520 -1264929 2450628 -1264929 2450628 -1264928 2402700 -1217000 ) ) (wire (path F.Cu 2540 2678700 -1287800 2678700 -1313200 ) ) (wire (path B.Cu 2540 2678700 -1313200 2716105 -1350605 2737505 -1350605 2751900 -1365000 ) ) ) (net col9 (wire (path F.Cu 2540 567816 -1093605 567816 -1002684 579200 -991300 ) ) (wire (path B.Cu 2540 613856 -1290000 613856 -1223086 567816 -1177046 567816 -1093605 ) ) (wire (path F.Cu 2540 2602700 -706000 2585172 -688472 2125676 -688472 2109943 -704205 2066267 -704205 2055364 -693302 1715398 -693302 1702700 -706000 ) ) (wire (path B.Cu 2540 613856 -1290000 602700 -1290000 ) ) (wire (path B.Cu 2540 1693295 -1261413 977441 -1261413 920876 -1317978 859234 -1317978 850612 -1309356 719571 -1309356 716565 -1312362 636218 -1312362 613856 -1290000 ) ) (via "Via[0-1]_889:635_um" 567816 -1093605 ) (wire (path B.Cu 2540 2704100 -1287800 2704100 -1081367 2559498 -936765 2559498 -749202 2602700 -706000 ) ) (wire (path B.Cu 2540 2704100 -1313200 2704100 -1287800 ) ) (wire (path B.Cu 2540 1702700 -1290000 1693295 -1280595 1693295 -1261413 ) ) (wire (path B.Cu 2540 1708751 -1175151 1693295 -1190607 1693295 -1261413 ) ) (via "Via[0-1]_889:635_um" 1708751 -1175151 ) (wire (path F.Cu 2540 1702700 -1144000 1708751 -1150051 1708751 -1175151 ) ) (wire (path B.Cu 2540 1702700 -1290000 1702700 -1314200 1651900 -1365000 ) ) (wire (path B.Cu 2540 1702700 -852000 1702700 -998000 ) ) (wire (path B.Cu 2540 1702700 -706000 1702700 -852000 ) ) (wire (path B.Cu 2540 1702700 -1144000 1702700 -998000 ) ) ) (net led1 (wire (path B.Cu 2540 1977300 -706000 1989496 -693804 2008244 -693804 2146246 -831806 2146246 -866766 2225680 -946200 2231880 -946200 2244891 -959211 2244891 -1095009 2228600 -1111300 ) ) (wire (path B.Cu 2540 1777300 -706000 1789699 -693601 1864901 -693601 1877300 -706000 ) ) (wire (path B.Cu 2540 1777300 -706000 1765105 -693805 1689495 -693805 1677300 -706000 ) ) (wire (path B.Cu 2540 1677300 -706000 1665105 -693805 1589495 -693805 1577300 -706000 ) ) (wire (path B.Cu 2540 1577300 -706000 1565105 -693805 1489495 -693805 1477300 -706000 ) ) (wire (path B.Cu 2540 1477300 -706000 1465105 -693805 1389495 -693805 1377300 -706000 ) ) (wire (path B.Cu 2540 1377300 -706000 1365105 -693805 1289495 -693805 1277300 -706000 ) ) (wire (path B.Cu 2540 1277300 -706000 1265105 -693805 1189495 -693805 1177300 -706000 ) ) (wire (path B.Cu 2540 1177300 -706000 1165105 -693805 1089495 -693805 1077300 -706000 ) ) (wire (path B.Cu 2540 1077300 -706000 1065105 -693805 989495 -693805 977300 -706000 ) ) (wire (path B.Cu 2540 977300 -706000 965105 -693805 889495 -693805 877300 -706000 ) ) (wire (path F.Cu 2540 1977300 -706000 1964948 -718352 1889652 -718352 1877300 -706000 ) ) ) (net led2 (wire (path F.Cu 2540 1277300 -852000 1289496 -864196 1365104 -864196 1377300 -852000 ) ) (wire (path F.Cu 2540 1177300 -852000 1189496 -839804 1265104 -839804 1277300 -852000 ) ) (wire (path F.Cu 2540 1977300 -852000 1964713 -839413 1889887 -839413 1877300 -852000 ) ) (wire (path F.Cu 2540 1877300 -852000 1865104 -839804 1789496 -839804 1777300 -852000 ) ) (wire (path F.Cu 2540 1777300 -852000 1764657 -864643 1689943 -864643 1677300 -852000 ) ) (wire (path F.Cu 2540 1677300 -852000 1665104 -839804 1589496 -839804 1577300 -852000 ) ) (wire (path F.Cu 2540 1577300 -852000 1564657 -864643 1489943 -864643 1477300 -852000 ) ) (wire (path F.Cu 2540 1477300 -852000 1465104 -839804 1389496 -839804 1377300 -852000 ) ) (wire (path B.Cu 2540 1977300 -852000 2020025 -894725 2154577 -894725 2213999 -954147 2213999 -1071299 2228600 -1085900 ) ) (wire (path F.Cu 2540 1177300 -852000 1164995 -864305 1089605 -864305 1077300 -852000 ) ) (wire (path B.Cu 2540 1077300 -852000 1065104 -864196 989496 -864196 977300 -852000 ) ) (wire (path B.Cu 2540 877300 -852000 889496 -864196 965104 -864196 977300 -852000 ) ) ) (net led3 (wire (path F.Cu 2540 1577300 -998000 1564659 -985359 1489941 -985359 1477300 -998000 ) ) (wire (path F.Cu 2540 1477300 -998000 1460021 -980721 1394579 -980721 1377300 -998000 ) ) (wire (path B.Cu 2540 1577300 -998000 1589569 -985731 1665031 -985731 1677300 -998000 ) ) (wire (path F.Cu 2540 1177300 -998000 1189496 -1010196 1265104 -1010196 1277300 -998000 ) ) (wire (path F.Cu 2540 1177300 -998000 1165097 -1010203 1089503 -1010203 1077300 -998000 ) ) (wire (path F.Cu 2540 1377300 -998000 1365104 -1010196 1289496 -1010196 1277300 -998000 ) ) (wire (path F.Cu 2540 1777300 -998000 1789851 -985449 1864749 -985449 1877300 -998000 ) ) (wire (path F.Cu 2540 1677300 -998000 1689496 -1010196 1765104 -1010196 1777300 -998000 ) ) (wire (path F.Cu 2540 977300 -998000 965010 -1010290 889590 -1010290 877300 -998000 ) ) (wire (path F.Cu 2540 1977300 -998000 2001700 -1022400 2231272 -1022400 2239433 -1030561 2239433 -1049667 2228600 -1060500 ) ) (wire (path F.Cu 2540 1877300 -998000 1889730 -985570 1964870 -985570 1977300 -998000 ) ) (wire (path B.Cu 2540 1077300 -998000 1064765 -985465 989835 -985465 977300 -998000 ) ) ) (net led4 (wire (path F.Cu 2540 1977300 -1144000 1977300 -1143582 2047067 -1073815 2189886 -1073815 2189886 -1073814 2228600 -1035100 ) ) (wire (path F.Cu 2540 1377300 -1144000 1365104 -1131804 1289496 -1131804 1277300 -1144000 ) ) (wire (path F.Cu 2540 1477300 -1144000 1465104 -1131804 1389496 -1131804 1377300 -1144000 ) ) (wire (path F.Cu 2540 977300 -1144000 965104 -1131804 889496 -1131804 877300 -1144000 ) ) (wire (path F.Cu 2540 1077300 -1144000 1065104 -1131804 989496 -1131804 977300 -1144000 ) ) (wire (path F.Cu 2540 1777300 -1144000 1765036 -1131736 1689564 -1131736 1677300 -1144000 ) ) (wire (path F.Cu 2540 1177300 -1144000 1165104 -1131804 1089496 -1131804 1077300 -1144000 ) ) (wire (path F.Cu 2540 1277300 -1144000 1265104 -1131804 1189496 -1131804 1177300 -1144000 ) ) (wire (path B.Cu 2540 1877300 -1144000 1889677 -1131623 1964923 -1131623 1977300 -1144000 ) ) (wire (path B.Cu 2540 1877300 -1144000 1864883 -1131583 1789717 -1131583 1777300 -1144000 ) ) (wire (path F.Cu 2540 1677300 -1144000 1665078 -1156222 1589522 -1156222 1577300 -1144000 ) ) (wire (path F.Cu 2540 1577300 -1144000 1565104 -1131804 1489496 -1131804 1477300 -1144000 ) ) ) (net led5 (wire (path F.Cu 2540 2117167 -1175345 2219312 -1073200 2231781 -1073200 2245007 -1059974 2245007 -1026107 2228600 -1009700 ) ) (via "Via[0-1]_889:635_um" 2117167 -1175345 ) (wire (path B.Cu 2540 1977300 -1290000 2091955 -1175345 2117167 -1175345 ) ) (wire (path F.Cu 2540 1277300 -1290000 1265104 -1302196 1189496 -1302196 1177300 -1290000 ) ) (wire (path F.Cu 2540 1077300 -1290000 1089496 -1302196 1165104 -1302196 1177300 -1290000 ) ) (wire (path F.Cu 2540 1977300 -1290000 1964997 -1302303 1889603 -1302303 1877300 -1290000 ) ) (wire (path F.Cu 2540 977300 -1290000 965104 -1277804 889496 -1277804 877300 -1290000 ) ) (wire (path B.Cu 2540 1077300 -1290000 1064887 -1277587 989713 -1277587 977300 -1290000 ) ) (wire (path B.Cu 2540 1377300 -1290000 1364881 -1277581 1289719 -1277581 1277300 -1290000 ) ) (wire (path B.Cu 2540 1477300 -1290000 1489495 -1277805 1565105 -1277805 1577300 -1290000 ) ) (wire (path F.Cu 2540 1777300 -1290000 1765104 -1302196 1689496 -1302196 1677300 -1290000 ) ) (wire (path F.Cu 2540 1577300 -1290000 1589496 -1302196 1665104 -1302196 1677300 -1290000 ) ) (wire (path F.Cu 2540 1877300 -1290000 1865105 -1277805 1789495 -1277805 1777300 -1290000 ) ) (wire (path B.Cu 2540 1477300 -1290000 1465105 -1277805 1389495 -1277805 1377300 -1290000 ) ) ) (net led6 (wire (path F.Cu 2540 2377300 -998000 2242300 -998000 2228600 -984300 ) ) (wire (path F.Cu 2540 2389551 -718251 2565049 -718251 ) ) (wire (path F.Cu 2540 2377300 -706000 2389551 -718251 ) ) (wire (path F.Cu 2540 2377300 -779000 2377300 -730502 2389551 -718251 ) ) (wire (path F.Cu 2540 2565049 -718251 2577300 -706000 ) ) (wire (path F.Cu 2540 2565049 -718251 2565049 -766749 2577300 -779000 ) ) (wire (path B.Cu 2540 2377300 -1144000 2377300 -1217000 ) ) (wire (path B.Cu 2540 2377300 -1071000 2377300 -1144000 ) ) (wire (path F.Cu 2540 2577300 -779000 2577300 -852000 ) ) (wire (path B.Cu 2540 2577300 -852000 2577300 -925000 ) ) (wire (path B.Cu 2540 2377300 -998000 2377300 -1071000 ) ) (wire (path B.Cu 2540 2377300 -925000 2377300 -998000 ) ) (wire (path B.Cu 2540 2377300 -852000 2377300 -925000 ) ) (wire (path B.Cu 2540 2377300 -779000 2377300 -852000 ) ) ) (net led7 (wire (path F.Cu 2540 2228600 -958900 2355540 -958900 2390000 -993360 2390000 -1029700 2577300 -1217000 ) ) (wire (path B.Cu 2540 2577300 -1144000 2577300 -1217000 ) ) (wire (path F.Cu 2540 2777300 -852000 2723300 -852000 2577300 -998000 ) ) (wire (path F.Cu 2540 2777300 -779000 2777300 -852000 ) ) (wire (path B.Cu 2540 2777300 -706000 2777300 -779000 ) ) (wire (path F.Cu 2540 2577300 -1071000 2577300 -998000 ) ) (wire (path B.Cu 2540 2228600 -958900 2239609 -969909 2239609 -1090211 2231220 -1098600 2225885 -1098600 2217524 -1106961 2217524 -1131008 2238917 -1152401 2238917 -1181052 ) ) (wire (path B.Cu 2540 2238917 -1181052 2199421 -1181052 2144442 -1126073 1771310 -1126073 1730490 -1166893 1705331 -1166893 1700493 -1171731 1700493 -1171979 1616142 -1256330 975183 -1256330 918681 -1312832 861276 -1312832 852546 -1304102 717637 -1304102 714460 -1307279 694579 -1307279 677300 -1290000 ) ) (wire (path B.Cu 2540 477300 -1290000 464551 -1302749 390049 -1302749 377300 -1290000 ) ) (wire (path F.Cu 2540 577300 -1290000 565003 -1277703 489597 -1277703 477300 -1290000 ) ) (wire (path F.Cu 2540 677300 -1290000 665104 -1277804 589496 -1277804 577300 -1290000 ) ) (wire (path B.Cu 2540 2399300 -1313200 2387380 -1325120 2368960 -1325120 2361200 -1317360 2361200 -1283347 2258905 -1181052 2238917 -1181052 ) ) (wire (path F.Cu 2540 377300 -1290000 365104 -1302196 289496 -1302196 277300 -1290000 ) ) (wire (path B.Cu 2540 2399300 -1287800 2399300 -1313200 ) ) (wire (path B.Cu 2540 2577300 -1144000 2577300 -1071000 ) ) ) (net led8 (wire (path B.Cu 2540 2217649 -897061 2217649 -922549 2228600 -933500 ) ) (wire (path B.Cu 2540 815189 -694080 831332 -677937 1999705 -677937 2217649 -895881 2217649 -897061 ) ) (wire (path B.Cu 2540 2424700 -1287800 2365104 -1228204 2365104 -1028730 2233435 -897061 2217649 -897061 ) ) (wire (path B.Cu 2540 2424700 -1313200 2424700 -1287800 ) ) (wire (path B.Cu 2540 815189 -694080 814894 -693785 789515 -693785 777300 -706000 ) ) (wire (path B.Cu 2540 777300 -1144000 656489 -1023189 620804 -1023189 593711 -996096 593711 -944853 815189 -723375 815189 -694080 ) ) (wire (path B.Cu 2540 477300 -706000 464624 -693324 389976 -693324 377300 -706000 ) ) (wire (path B.Cu 2540 577300 -706000 564624 -693324 489976 -693324 477300 -706000 ) ) (wire (path B.Cu 2540 377300 -706000 364624 -693324 289976 -693324 277300 -706000 ) ) (wire (path B.Cu 2540 777300 -706000 765104 -693804 689496 -693804 677300 -706000 ) ) (wire (path B.Cu 2540 577300 -706000 589496 -693804 665104 -693804 677300 -706000 ) ) ) (net row1 (wire (path B.Cu 3810 890000 -1595000 890000 -1577852 ) ) (wire (path B.Cu 3810 890000 -1577852 836994 -1524846 836994 -1340694 827100 -1330800 ) ) (wire (path F.Cu 3810 1590000 -1595000 1690000 -1595000 ) ) (wire (path F.Cu 3810 1490000 -1595000 1590000 -1595000 ) ) (wire (path F.Cu 3810 1890000 -1595000 1990000 -1595000 ) ) (wire (path F.Cu 3810 1790000 -1595000 1890000 -1595000 ) ) (wire (path F.Cu 3810 1690000 -1595000 1790000 -1595000 ) ) (wire (path F.Cu 3810 1390000 -1595000 1490000 -1595000 ) ) (wire (path F.Cu 3810 1290000 -1595000 1390000 -1595000 ) ) (wire (path F.Cu 3810 1190000 -1595000 1290000 -1595000 ) ) (wire (path F.Cu 3810 990000 -1595000 890000 -1595000 ) ) (wire (path F.Cu 3810 1090000 -1595000 990000 -1595000 ) ) (wire (path F.Cu 3810 1190000 -1595000 1090000 -1595000 ) ) ) (net row2 (wire (path B.Cu 3810 690000 -1595000 719848 -1595000 ) ) (wire (path B.Cu 3810 790000 -1603574 728422 -1603574 719848 -1595000 ) ) (wire (path B.Cu 3810 790000 -1603574 790000 -1612148 ) ) (wire (path B.Cu 3810 790000 -1595000 790000 -1603574 ) ) (wire (path B.Cu 3810 590000 -1595000 490000 -1595000 ) ) (wire (path B.Cu 3810 2450100 -1313200 2432420 -1330880 2250709 -1330880 2239137 -1319308 2139587 -1319308 2114032 -1344863 2025437 -1344863 1940000 -1430300 1940000 -1526807 1910458 -1556349 1490818 -1556349 1435019 -1612148 790000 -1612148 ) ) (wire (path B.Cu 3810 2450100 -1287800 2450100 -1313200 ) ) (wire (path B.Cu 3810 290000 -1595000 290000 -1577852 ) ) (wire (path B.Cu 3810 290000 -1577852 245925 -1533777 245925 -1409381 192122 -1355578 192122 -1337722 149400 -1295000 ) ) (wire (path F.Cu 3810 290000 -1595000 390000 -1595000 ) ) (wire (path F.Cu 3810 590000 -1595000 690000 -1595000 ) ) (wire (path F.Cu 3810 390000 -1595000 490000 -1595000 ) ) ) (net row3 (wire (path F.Cu 3810 2490000 -1595000 2590000 -1595000 ) ) (wire (path F.Cu 3810 2390000 -1595000 2490000 -1595000 ) ) (wire (path F.Cu 3810 2690000 -1595000 2790000 -1595000 ) ) (wire (path F.Cu 3810 2590000 -1595000 2690000 -1595000 ) ) (wire (path F.Cu 3810 2290000 -1595000 2390000 -1595000 ) ) (wire (path B.Cu 3810 2239196 -1528656 2190000 -1577852 ) ) (wire (path B.Cu 3810 2224100 -1330800 2239196 -1345896 2239196 -1528656 ) ) (wire (path B.Cu 3810 2290000 -1577852 2240804 -1528656 2239196 -1528656 ) ) (wire (path B.Cu 3810 2190000 -1595000 2190000 -1577852 ) ) (wire (path B.Cu 3810 2290000 -1595000 2290000 -1577852 ) ) (wire (path F.Cu 3810 2190000 -1595000 2090000 -1595000 ) ) ) (net xled1 (wire (path F.Cu 2540 467355 -1171664 498489 -1140530 673533 -1140530 707115 -1174112 707115 -1176695 731045 -1200625 750777 -1200625 756860 -1194542 1632898 -1194542 1637895 -1199539 2053363 -1199539 2141602 -1111300 ) ) (wire (path B.Cu 2540 467355 -1171664 436800 -1202219 436800 -1240000 424100 -1252700 ) ) (wire (path F.Cu 2540 2152400 -1111300 2141602 -1111300 ) ) (via "Via[0-1]_889:635_um" 467355 -1171664 ) ) (net xled2 (wire (path F.Cu 2540 467255 -1139784 471592 -1135447 675638 -1135447 712198 -1172007 712198 -1174590 733150 -1195542 748672 -1195542 754755 -1189459 1643127 -1189459 1648008 -1194340 2043960 -1194340 2152400 -1085900 ) ) (wire (path B.Cu 2540 398700 -1252700 411400 -1240000 411400 -1195639 467255 -1139784 ) ) (via "Via[0-1]_889:635_um" 467255 -1139784 ) ) (net xled3 (wire (path F.Cu 2540 2152400 -1060500 2024552 -1060500 1896176 -1188876 1662790 -1188876 1658133 -1184219 746581 -1184219 743516 -1187284 ) ) (wire (path B.Cu 2540 703500 -1227300 743516 -1187284 ) ) (via "Via[0-1]_889:635_um" 743516 -1187284 ) ) (net xled4 (wire (path F.Cu 2540 2152400 -1035100 2028846 -1035100 1880154 -1183792 1672685 -1183792 1667756 -1178863 735094 -1178863 ) ) (wire (path B.Cu 2540 703500 -1252700 691890 -1241090 691890 -1222067 735094 -1178863 ) ) (via "Via[0-1]_889:635_um" 735094 -1178863 ) ) (net xled5 (wire (path F.Cu 2540 720456 -1171170 721251 -1170375 735204 -1170375 743019 -1162560 743019 -1161036 777335 -1126720 1522996 -1126720 1669503 -980213 2122913 -980213 2152400 -1009700 ) ) (wire (path B.Cu 2540 678100 -1252700 666329 -1240929 666329 -1222716 717875 -1171170 720456 -1171170 ) ) (via "Via[0-1]_889:635_um" 720456 -1171170 ) ) (net xled6 (wire (path B.Cu 2540 627300 -1252700 651061 -1276461 681614 -1276461 689496 -1284343 689496 -1294386 697306 -1302196 709812 -1302196 713431 -1298577 854209 -1298577 863283 -1307651 916673 -1307651 976652 -1247672 1617612 -1247672 1695410 -1169874 1695410 -1169626 1703226 -1161810 1715043 -1161810 1765976 -1110877 2033834 -1110877 2152400 -992311 2152400 -984300 ) ) ) (net xled7 (wire (path F.Cu 2540 424100 -1227300 415710 -1218910 415710 -1062823 422341 -1056192 431391 -1056192 439500 -1064301 439500 -1070426 498972 -1129898 690864 -1129898 726258 -1165292 733099 -1165292 737936 -1160455 737936 -1158768 789357 -1107347 1285370 -1107347 1389496 -1003221 1389496 -993423 1397115 -985804 1409812 -985804 1434703 -1010695 1608205 -1010695 1660000 -958900 2152400 -958900 ) ) ) (net xled8 (wire (path B.Cu 2540 729678 -1157034 751941 -1179297 751941 -1204259 728900 -1227300 ) ) (wire (path F.Cu 2540 2152400 -933500 1102558 -933500 1008346 -1027712 859000 -1027712 729678 -1157034 ) ) (via "Via[0-1]_889:635_um" 729678 -1157034 ) ) ) ) ) |
> > > > > > > | 1 2 3 4 5 6 7 | EESchema-DOCLIB Version 2.0 Date: 19/01/2015 21:56:03 # $CMP UDN2981A D UDN2981A $ENDCMP # #End Doc Library |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | EESchema-LIBRARY Version 2.3 Date: 19/01/2015 21:56:03 #encoding utf-8 # # CONN_20X2 # DEF CONN_20X2 P 0 10 Y N 1 F N F0 "P" 0 1050 60 H V C CNN F1 "CONN_20X2" 0 0 50 V V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW S -100 1000 100 -1000 0 1 0 N X P1 1 -400 950 300 R 60 30 1 1 P I X P2 2 400 950 300 L 60 30 1 1 P I X P3 3 -400 850 300 R 60 30 1 1 P I X P4 4 400 850 300 L 60 30 1 1 P I X P5 5 -400 750 300 R 60 30 1 1 P I X P6 6 400 750 300 L 60 30 1 1 P I X P7 7 -400 650 300 R 60 30 1 1 P I X P8 8 400 650 300 L 60 30 1 1 P I X P9 9 -400 550 300 R 60 30 1 1 P I X P10 10 400 550 300 L 60 30 1 1 P I X P20 20 400 50 300 L 60 30 1 1 P I X P30 30 400 -450 300 L 60 30 1 1 P I X P40 40 400 -950 300 L 60 30 1 1 P I X P11 11 -400 450 300 R 60 30 1 1 P I X P21 21 -400 -50 300 R 60 30 1 1 P I X P31 31 -400 -550 300 R 60 30 1 1 P I X P12 12 400 450 300 L 60 30 1 1 P I X P22 22 400 -50 300 L 60 30 1 1 P I X P32 32 400 -550 300 L 60 30 1 1 P I X P13 13 -400 350 300 R 60 30 1 1 P I X P23 23 -400 -150 300 R 60 30 1 1 P I X P33 33 -400 -650 300 R 60 30 1 1 P I X P14 14 400 350 300 L 60 30 1 1 P I X P24 24 400 -150 300 L 60 30 1 1 P I X P34 34 400 -650 300 L 60 30 1 1 P I X P15 15 -400 250 300 R 60 30 1 1 P I X ~ 25 -400 -250 300 R 60 30 1 1 P I X P35 35 -400 -750 300 R 60 30 1 1 P I X P16 16 400 250 300 L 60 30 1 1 P I X P26 26 400 -250 300 L 60 30 1 1 P I X P36 36 400 -750 300 L 60 30 1 1 P I X P17 17 -400 150 300 R 60 30 1 1 P I X P27 27 -400 -350 300 R 60 30 1 1 P I X P37 37 -400 -850 300 R 60 30 1 1 P I X P18 18 400 150 300 L 60 30 1 1 P I X P28 28 400 -350 300 L 60 30 1 1 P I X P38 38 400 -850 300 L 60 30 1 1 P I X P19 19 -400 50 300 R 60 30 1 1 P I X P29 29 -400 -450 300 R 60 30 1 1 P I X P39 39 -400 -950 300 R 60 30 1 1 P I ENDDRAW ENDDEF # # RASPI_MODEL_B_PLUS_GPIO # DEF RASPI_MODEL_B_PLUS_GPIO P 0 10 Y Y 1 F N F0 "P" 0 1050 60 H V C CNN F1 "RASPI_MODEL_B_PLUS_GPIO" 0 0 20 V V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW S -100 1000 100 -1000 0 1 0 N X 3.3v 1 -400 950 300 R 60 30 1 1 w I X 5v 2 400 950 300 L 60 30 1 1 w I X g2 3 -400 850 300 R 60 30 1 1 P I X 5v 4 400 850 300 L 60 30 1 1 P I X g3 5 -400 750 300 R 60 30 1 1 P I X GND 6 400 750 300 L 60 30 1 1 w I X g4 7 -400 650 300 R 60 30 1 1 P I X g14 8 400 650 300 L 60 30 1 1 P I X GND 9 -400 550 300 R 60 30 1 1 P I X g15 10 400 550 300 L 60 30 1 1 P I X GND 20 400 50 300 L 60 30 1 1 P I X GND 30 400 -450 300 L 60 30 1 1 P I X g21 40 400 -950 300 L 60 30 1 1 P I X g17 11 -400 450 300 R 60 30 1 1 P I X g9 21 -400 -50 300 R 60 30 1 1 P I X g6 31 -400 -550 300 R 60 30 1 1 P I X g18 12 400 450 300 L 60 30 1 1 P I X g25 22 400 -50 300 L 60 30 1 1 P I X g12 32 400 -550 300 L 60 30 1 1 P I X g27 13 -400 350 300 R 60 30 1 1 P I X g11 23 -400 -150 300 R 60 30 1 1 P I X g13 33 -400 -650 300 R 60 30 1 1 P I X GND 14 400 350 300 L 60 30 1 1 P I X g8 24 400 -150 300 L 60 30 1 1 P I X GND 34 400 -650 300 L 60 30 1 1 P I X g22 15 -400 250 300 R 60 30 1 1 P I X GND 25 -400 -250 300 R 60 30 1 1 P I X g19 35 -400 -750 300 R 60 30 1 1 P I X g23 16 400 250 300 L 60 30 1 1 P I X g7 26 400 -250 300 L 60 30 1 1 P I X g16 36 400 -750 300 L 60 30 1 1 P I X 3.3v 17 -400 150 300 R 60 30 1 1 P I X n/c 27 -400 -350 300 R 60 30 1 1 P I X g26 37 -400 -850 300 R 60 30 1 1 P I X g24 18 400 150 300 L 60 30 1 1 P I X n/c 28 400 -350 300 L 60 30 1 1 P I X g20 38 400 -850 300 L 60 30 1 1 P I X g10 19 -400 50 300 R 60 30 1 1 P I X g5 29 -400 -450 300 R 60 30 1 1 P I X GND 39 -400 -950 300 R 60 30 1 1 P I ENDDRAW ENDDEF # # UDN2981A # DEF UDN2981A P 0 40 Y Y 1 F N F0 "P" 0 550 30 H V C CNN F1 "UDN2981A" 0 -550 30 H V C CNN F2 "~" 0 0 60 H V C CNN F3 "~" 0 0 60 H V C CNN DRAW S -150 500 150 -500 0 1 0 N X IN1 1 -350 400 200 R 40 20 1 1 I I X IN2 2 -350 300 200 R 40 20 1 1 I I X IN3 3 -350 200 200 R 40 20 1 1 I I X IN4 4 -350 100 200 R 40 20 1 1 I I X IN5 5 -350 0 200 R 40 20 1 1 I I X IN6 6 -350 -100 200 R 40 20 1 1 I I X IN7 7 -350 -200 200 R 40 20 1 1 I I X IN8 8 -350 -300 200 R 40 20 1 1 I I X Vs 9 -350 -400 200 R 40 20 1 1 P I X GND 10 350 -400 200 L 40 20 1 1 P I X OUT8 11 350 -300 200 L 40 20 1 1 O I X OUT7 12 350 -200 200 L 40 20 1 1 O I X OUT6 13 350 -100 200 L 40 20 1 1 O I X OUT5 14 350 0 200 L 40 20 1 1 O I X OUT4 15 350 100 200 L 40 20 1 1 O I X OUT3 16 350 200 200 L 40 20 1 1 O I X OUT2 17 350 300 200 L 40 20 1 1 O I X OUT1 18 350 400 200 L 40 20 1 1 O I ENDDRAW ENDDEF # #End Library |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 | PCBNEW-LibModule-V1 09/05/2015 20:49:52 # encoding utf-8 Units mm $INDEX D2 LED-3-PDP LED-3-StrEight RASPI_BPLUS RASPI_BPLUS_MIRRORED SIL-3PDP SIL-5PDP SW_KND2 SW_KND2_PDP SW_KND2_PDP2 $EndINDEX $MODULE D2 Po 0 0 0 15 54B29F05 00000000 ~~ Li D2 Cd Diode 3 pas Kw DIODE DEV Sc 0 AR Op 0 0 0 T0 0 -0.508 0.25 0.25 0 0.05 N V 21 N "D2" T1 -0.508 0.508 0.381 0.381 0 0.0762 N I 21 N "D***" DS -2.032 1.016 2.032 1.016 0.3048 21 DS -2.032 -1.016 2.032 -1.016 0.3048 21 DS 2.794 0 2.032 0 0.3048 21 DS 2.032 0 2.032 -1.016 0.3048 21 DS -2.032 -1.016 -2.032 0 0.3048 21 DS -2.032 0 -2.794 0 0.3048 21 DS -2.032 0 -2.032 1.016 0.3048 21 DS 2.032 1.016 2.032 0 0.3048 21 DS 1.524 -1.016 1.524 1.016 0.3048 21 DS 1.27 1.016 1.27 -1.016 0.3048 21 $PAD Sh "2" R 1.397 1.397 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 0 "" Po 3.556 0 $EndPAD $PAD Sh "1" C 1.397 1.397 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 0 "" Po -3.81 0 $EndPAD $SHAPE3D Na "discret/diode.wrl" Sc 0.3 0.3 0.3 Of 0 0 0 Ro 0 0 0 $EndSHAPE3D $EndMODULE D2 $MODULE LED-3-PDP Po 0 0 0 15 54BD7621 00000000 ~~ Li LED-3-PDP Cd LED 3mm - Lead pitch 100mil (2,54mm) Kw LED led 3mm 3MM 100mil 2,54mm Sc 0 AR /548EF4B8 Op 0 0 0 T0 0 -5.5372 0.7 0.7 0 0.025 N V 21 N "DMA12" T1 0 2.54 0.762 0.762 0 0.0889 N I 21 N "LED" DS -2.4 1.5 -2.4 -1.5 0.15 21 DS 1.5 2.4 -1.5 2.4 0.15 21 DS 2.4 -1.5 2.4 1.5 0.15 21 DS -1.5 -2.4 1.5 -2.4 0.15 21 DA -1.5 1.5 -1.5 2.4 900 0.15 21 DA 1.5 1.5 2.4 1.5 900 0.15 21 DA -1.5 -1.5 -2.4 -1.5 900 0.15 21 DA 1.5 -1.5 1.5 -2.4 900 0.15 21 $PAD Sh "1" C 1.6764 1.6764 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 2 "led2" Po -1.27 0 $EndPAD $PAD Sh "2" C 1.6764 1.6764 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 1 "N-000004" Po 1.27 0 $EndPAD $SHAPE3D Na "discret/leds/led3_vertical_verde.wrl" Sc 1 1 1 Of 0 0 0 Ro 0 0 0 $EndSHAPE3D $EndMODULE LED-3-PDP $MODULE LED-3-StrEight Po 0 0 0 15 554E561D 00000000 ~~ Li LED-3-StrEight Cd LED Kw LED Sc 0 AR /548EF4B8 Op 0 0 0 T0 0 -5.5372 0.7 0.7 0 0.025 N I 21 N "Str8" T1 0 2.54 0.762 0.762 0 0.0889 N I 21 N "LED" $PAD Sh "1" C 1.6764 1.6764 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 2 "led2" Po -1.27 0 $EndPAD $PAD Sh "2" C 1.6764 1.6764 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 1 "N-000004" Po 1.27 0 $EndPAD $SHAPE3D Na "discret/leds/led3_vertical_verde.wrl" Sc 1 1 1 Of 0 0 0 Ro 0 0 0 $EndSHAPE3D $EndMODULE LED-3-StrEight $MODULE RASPI_BPLUS Po 0 0 0 15 54B191EE 00000000 ~~ Li RASPI_BPLUS Cd Double rangee de contacts 2 x 12 pins Kw CONN Sc 0 AR Op 0 0 0 T0 0 -3.81 1.016 1.016 0 0.27432 N V 21 N "REF*" T1 0 3.81 1.016 1.016 0 0.2032 N V 21 N "PIN_ARRAY_20X2" T2 8 26.5 1 1 0 0.15 N V 21 N "GPIO and mount holes exact, port placement approx." T2 6 20.5 1 1 0 0.15 N V 21 N "COMPONENT SIDE (TOP)" T2 -19 48 1 1 0 0.15 N V 21 N "microUSB" DS -22 52.5 -22 49 0.15 21 DS -22 49 -16 52.5 0.15 21 DS -16 52.5 -16 49 0.15 21 DS -16 49 -22 52.5 0.15 21 T2 0 49 1 1 0 0.15 N V 21 N "HDMI" DS -7 52.5 -7 48.5 0.15 21 DS -7 48.5 6 52.5 0.15 21 DS 6 52.5 6 48.5 0.15 21 DS 6 48.5 -7 52.5 0.15 21 T2 50.5 24 1 1 900 0.15 N V 21 N "USB" T2 50.5 7 1 1 900 0.15 N V 21 N "USB" DS 50.5 18.5 55 18.5 0.15 21 DS 55 18.5 55 29.5 0.15 21 DS 55 29.5 51 29.5 0.15 21 DS 50.5 1.5 55 1.5 0.15 21 DS 55 1.5 55 13 0.15 21 DS 55 13 50.5 13 0.15 21 DS -32.5 -3.5 52.5 -3.5 0.15 21 DS 52.5 -3.5 52.5 52.5 0.15 21 DS 52.5 52.5 32 52.5 0.15 21 DS -32.5 -3.5 -32.5 52.5 0.15 21 DS -32.5 52.5 32.5 52.5 0.15 21 DS 25.4 2.54 -25.4 2.54 0.3048 21 DS 25.4 -2.54 -25.4 -2.54 0.3048 21 DS 25.4 -2.54 25.4 2.54 0.3048 21 DS -25.4 -2.54 -25.4 2.54 0.3048 21 $PAD Sh "1" R 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po -24.13 1.27 $EndPAD $PAD Sh "2" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 1 "GND" Po -24.13 -1.27 $EndPAD $PAD Sh "11" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 18 "PA8_1" Po -11.43 1.27 $EndPAD $PAD Sh "4" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 11 "PA1_1" Po -21.59 -1.27 $EndPAD $PAD Sh "13" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 5 "PA10_1" Po -8.89 1.27 $EndPAD $PAD Sh "6" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 13 "PA3_1" Po -19.05 -1.27 $EndPAD $PAD Sh "15" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 7 "PA12_1" Po -6.35 1.27 $EndPAD $PAD Sh "8" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 15 "PA5_1" Po -16.51 -1.27 $EndPAD $PAD Sh "17" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 9 "PA14_1" Po -3.81 1.27 $EndPAD $PAD Sh "10" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 17 "PA7_1" Po -13.97 -1.27 $EndPAD $PAD Sh "19" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po -1.27 1.27 $EndPAD $PAD Sh "12" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 19 "PA9_1" Po -11.43 -1.27 $EndPAD $PAD Sh "21" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 1.27 1.27 $EndPAD $PAD Sh "14" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 6 "PA11_1" Po -8.89 -1.27 $EndPAD $PAD Sh "23" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 2 "INT1_1" Po 3.81 1.27 $EndPAD $PAD Sh "16" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 8 "PA13_1" Po -6.35 -1.27 $EndPAD $PAD Sh "25" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 6.35 1.27 $EndPAD $PAD Sh "18" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 10 "PA15_1" Po -3.81 -1.27 $EndPAD $PAD Sh "27" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 8.89 1.27 $EndPAD $PAD Sh "20" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po -1.27 -1.27 $EndPAD $PAD Sh "29" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 22 "VCC" Po 11.43 1.27 $EndPAD $PAD Sh "22" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 1.27 -1.27 $EndPAD $PAD Sh "31" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 22 "VCC" Po 13.97 1.27 $EndPAD $PAD Sh "24" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 3 "INT2_1" Po 3.81 -1.27 $EndPAD $PAD Sh "26" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 6.35 -1.27 $EndPAD $PAD Sh "33" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 21 "Tin1_cold_1" Po 16.51 1.27 $EndPAD $PAD Sh "28" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 10 "PA15_1" Po 8.89 -1.27 $EndPAD $PAD Sh "32" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 1 "GND" Po 13.97 -1.27 $EndPAD $PAD Sh "34" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 16.51 -1.27 $EndPAD $PAD Sh "36" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 19.05 -1.27 $EndPAD $PAD Sh "38" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 21.59 -1.27 $EndPAD $PAD Sh "35" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 19.05 1.27 $EndPAD $PAD Sh "37" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 20 "PB4_1" Po 21.59 1.27 $EndPAD $PAD Sh "3" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 4 "PA0_1" Po -21.59 1.27 $EndPAD $PAD Sh "5" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 12 "PA2_1" Po -19.05 1.27 $EndPAD $PAD Sh "7" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 14 "PA4_1" Po -16.51 1.27 $EndPAD $PAD Sh "9" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 16 "PA6_1" Po -13.97 1.27 $EndPAD $PAD Sh "39" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 24.13 1.27 $EndPAD $PAD Sh "40" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 24.13 -1.27 $EndPAD $PAD Sh "30" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 1 "GND" Po 11.43 -1.27 $EndPAD $PAD Sh "2" C 6.2 6.2 0 0 0 Dr 2.75 0 0 At STD N 00E0FFFF Ne 0 "" Po -29 0 $EndPAD $PAD Sh "3" C 6.2 6.2 0 0 0 Dr 2.75 0 0 At STD N 00E0FFFF Ne 0 "" Po 29 0 $EndPAD $PAD Sh "4" C 6.2 6.2 0 0 0 Dr 2.75 0 0 At STD N 00E0FFFF Ne 0 "" Po -29 49 $EndPAD $PAD Sh "5" C 6.2 6.2 0 0 0 Dr 2.75 0 0 At STD N 00E0FFFF Ne 0 "" Po 29 49 $EndPAD $SHAPE3D Na "pin_array/pins_array_20x2.wrl" Sc 1 1 1 Of 0 0 0 Ro 0 0 0 $EndSHAPE3D $EndMODULE RASPI_BPLUS $MODULE RASPI_BPLUS_MIRRORED Po 0 0 0 15 54B2FF09 00000000 ~~ Li RASPI_BPLUS_MIRRORED Cd Double rangee de contacts 2 x 12 pins Kw CONN Sc 0 AR /548F13F7 Op 0 0 0 T0 0 -3.81 1.016 1.016 0 0.27432 N V 21 N "P1" T1 0 3.81 1.016 1.016 0 0.2032 N V 21 N "RASPI_MODEL_B_PLUS_GPIO" T2 49.53 -43.18 1 1 900 0.15 N V 21 N "ETH" DS 48.768 -49.022 53.594 -49.022 0.15 21 DS 53.594 -49.022 53.594 -38.354 0.15 21 DS 53.594 -38.354 49.784 -38.354 0.15 21 T2 7.5 -18 1 1 0 0.15 N V 21 N "GPIO and mount holes exact, port placement approx." T2 0 -24.5 1 1 0 0.15 N V 21 N "RASPI B PLUS (MIRROR IMAGE)" T2 -19 -47 1 1 0 0.15 N V 21 N "microUSB" DS -22 -49.008 -22 -52.508 0.15 21 DS -16 -49.008 -16 -52.508 0.15 21 T2 0 -47 1 1 0 0.15 N V 21 N "HDMI" DS -7 -48.5 -7 -52.5 0.15 21 DS 6 -48.5 6 -52.5 0.15 21 T2 49.5 -3.5 1 1 900 0.15 N V 21 N "USB" T2 49.5 -20.5 1 1 900 0.15 N V 21 N "USB" DS 49.5 -11.032 54 -11.032 0.15 21 DS 54 -11.032 54 -0.032 0.15 21 DS 54 -0.032 50 -0.032 0.15 21 DS 49.5 -28.032 54 -28.032 0.15 21 DS 54 -28.032 54 -16.532 0.15 21 DS 54 -16.532 49.5 -16.532 0.15 21 DS -32.5 3.5 52.5 3.5 0.15 21 DS 52.5 -52.5 52.5 3.5 0.15 21 DS 52.5 -52.5 32 -52.5 0.15 21 DS -32.5 -52.5 -32.5 3.5 0.15 21 DS -32.5 -52.5 32.5 -52.5 0.15 21 DS 25.4 2.54 -25.4 2.54 0.3048 21 DS 25.4 -2.54 -25.4 -2.54 0.3048 21 DS 25.4 -2.54 25.4 2.54 0.3048 21 DS -25.4 -2.54 -25.4 2.54 0.3048 21 $PAD Sh "1" R 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 1 "+3.3V" Po -24.13 -1.27 $EndPAD $PAD Sh "2" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po -24.13 1.27 $EndPAD $PAD Sh "11" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 21 "xled4" Po -11.43 -1.27 $EndPAD $PAD Sh "4" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po -21.59 1.27 $EndPAD $PAD Sh "13" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 22 "xled5" Po -8.89 -1.27 $EndPAD $PAD Sh "6" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 2 "GND" Po -19.05 1.27 $EndPAD $PAD Sh "15" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 23 "xled6" Po -6.35 -1.27 $EndPAD $PAD Sh "8" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 7 "N-0000031" Po -16.51 1.27 $EndPAD $PAD Sh "17" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po -3.81 -1.27 $EndPAD $PAD Sh "10" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 8 "N-0000032" Po -13.97 1.27 $EndPAD $PAD Sh "19" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 24 "xled7" Po -1.27 -1.27 $EndPAD $PAD Sh "12" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 9 "N-0000033" Po -11.43 1.27 $EndPAD $PAD Sh "21" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 25 "xled8" Po 1.27 -1.27 $EndPAD $PAD Sh "14" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 2 "GND" Po -8.89 1.27 $EndPAD $PAD Sh "23" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 17 "N-0000092" Po 3.81 -1.27 $EndPAD $PAD Sh "16" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 10 "N-0000034" Po -6.35 1.27 $EndPAD $PAD Sh "25" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 2 "GND" Po 6.35 -1.27 $EndPAD $PAD Sh "18" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 3 "N-0000027" Po -3.81 1.27 $EndPAD $PAD Sh "27" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 8.89 -1.27 $EndPAD $PAD Sh "20" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 2 "GND" Po -1.27 1.27 $EndPAD $PAD Sh "29" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 15 "N-0000090" Po 11.43 -1.27 $EndPAD $PAD Sh "22" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 11 "N-0000035" Po 1.27 1.27 $EndPAD $PAD Sh "31" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 16 "N-0000091" Po 13.97 -1.27 $EndPAD $PAD Sh "24" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 12 "N-0000036" Po 3.81 1.27 $EndPAD $PAD Sh "26" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 13 "N-0000037" Po 6.35 1.27 $EndPAD $PAD Sh "33" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 4 "N-0000028" Po 16.51 -1.27 $EndPAD $PAD Sh "28" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 8.89 1.27 $EndPAD $PAD Sh "32" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 14 "N-0000038" Po 13.97 1.27 $EndPAD $PAD Sh "34" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 16.51 1.27 $EndPAD $PAD Sh "36" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 19.05 1.27 $EndPAD $PAD Sh "38" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 21.59 1.27 $EndPAD $PAD Sh "35" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 5 "N-0000029" Po 19.05 -1.27 $EndPAD $PAD Sh "37" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 6 "N-0000030" Po 21.59 -1.27 $EndPAD $PAD Sh "3" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 18 "xled1" Po -21.59 -1.27 $EndPAD $PAD Sh "5" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 19 "xled2" Po -19.05 -1.27 $EndPAD $PAD Sh "7" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 20 "xled3" Po -16.51 -1.27 $EndPAD $PAD Sh "9" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 2 "GND" Po -13.97 -1.27 $EndPAD $PAD Sh "39" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 2 "GND" Po 24.13 -1.27 $EndPAD $PAD Sh "40" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 0 "" Po 24.13 1.27 $EndPAD $PAD Sh "30" C 1.524 1.524 0 0 0 Dr 1.016 0 0 At STD N 00E0FFFF Ne 2 "GND" Po 11.43 1.27 $EndPAD $PAD Sh "H2" C 5.7 5.7 0 0 0 Dr 2.75 0 0 At STD N 00E0FFFF Ne 0 "" Po -29 0 $EndPAD $PAD Sh "H3" C 5.7 5.7 0 0 0 Dr 2.75 0 0 At STD N 00E0FFFF Ne 0 "" Po 29 0 $EndPAD $PAD Sh "H4" C 5.7 5.7 0 0 0 Dr 2.75 0 0 At STD N 00E0FFFF Ne 0 "" Po 29 -49 $EndPAD $PAD Sh "H1" C 5.7 5.7 0 0 0 Dr 2.75 0 0 At STD N 00E0FFFF Ne 0 "" Po -29 -49 $EndPAD $SHAPE3D Na "pin_array/pins_array_20x2.wrl" Sc 1 1 1 Of 0 0 0 Ro 0 0 0 $EndSHAPE3D $EndMODULE RASPI_BPLUS_MIRRORED $MODULE SIL-3PDP Po 0 0 0 15 54BD2D6F 00000000 ~~ Li SIL-3PDP Cd Connecteur 3 pins Kw CONN DEV Sc 0 AR /54BD28E4 Op 0 0 0 T0 3.175 -2.54 0.5 0.5 0 0.125 N V 21 N "P3" T1 -2.286 -2.54 0.5 0.5 0 0.125 N I 21 N "SERIAL3V" T2 2.54 -1.778 0.5 0.5 0 0.1 N V 21 N "TX" T2 0 -1.778 0.5 0.5 0 0.1 N V 21 N "RX" T2 -2.54 -1.778 0.5 0.5 0 0.1 N V 21 N "GND" DS -3.81 1.27 -3.81 -1.27 0.3048 21 DS -3.81 -1.27 3.81 -1.27 0.3048 21 DS 3.81 -1.27 3.81 1.27 0.3048 21 DS 3.81 1.27 -3.81 1.27 0.3048 21 DS -1.27 -1.27 -1.27 1.27 0.3048 21 $PAD Sh "1" R 1.397 1.397 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 1 "GND" Po -2.54 0 $EndPAD $PAD Sh "2" C 1.397 1.397 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 2 "RX" Po 0 0 $EndPAD $PAD Sh "3" C 1.397 1.397 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 3 "TX" Po 2.54 0 $EndPAD $EndMODULE SIL-3PDP $MODULE SIL-5PDP Po 0 0 0 15 54BD2E53 00000000 ~~ Li SIL-5PDP Cd Connecteur 5 pins Kw CONN DEV Sc 0 AR /54BD2904 Op 0 0 0 T0 4.699 -2.54 0.5 0.5 0 0.125 N V 21 N "P4" T1 -5.715 -2.54 0.5 0.5 0 0.125 N I 21 N "EXPANSION" T2 3.81 -1.778 0.5 0.5 0 0.1 N V 21 N "GPIO" T2 1.27 -1.778 0.5 0.5 0 0.1 N V 21 N "GND" T2 -1.27 -1.778 0.5 0.5 0 0.1 N V 21 N "5V" T2 -3.81 -1.778 0.5 0.5 0 0.1 N V 21 N "N/C" T2 -6.223 -1.778 0.5 0.5 0 0.1 N V 21 N "3.3V" DS -7.62 1.27 -7.62 -1.27 0.3048 21 DS -7.62 -1.27 5.08 -1.27 0.3048 21 DS 5.08 -1.27 5.08 1.27 0.3048 21 DS 5.08 1.27 -7.62 1.27 0.3048 21 DS -5.08 1.27 -5.08 -1.27 0.3048 21 $PAD Sh "1" R 1.397 1.397 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 1 "+3.3V" Po -6.35 0 $EndPAD $PAD Sh "2" C 1.397 1.397 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 0 "" Po -3.81 0 $EndPAD $PAD Sh "3" C 1.397 1.397 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 2 "+5V" Po -1.27 0 $EndPAD $PAD Sh "4" C 1.397 1.397 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 3 "GND" Po 1.27 0 $EndPAD $PAD Sh "5" C 1.397 1.397 0 0 0 Dr 0.8128 0 0 At STD N 00E0FFFF Ne 4 "SPARE_IO" Po 3.81 0 $EndPAD $EndMODULE SIL-5PDP $MODULE SW_KND2 Po 0 0 0 15 548F15A7 00000000 ~~ Li SW_KND2 Cd Switch inverseur Kw SWITCH DEV Sc 0 AR Op 0 0 0 T0 3.5 7.9 1.016 1.016 900 0.2032 N V 21 N "SW_KND2_1x2" T1 -0.05 -20.3 1.016 1.016 0 0.2032 N V 21 N "SW*" DS -4.75 -18.9 -4.75 18.9 0.15 21 DS -4.75 18.9 4.75 18.9 0.15 21 DS 4.75 18.9 4.75 -18.9 0.15 21 DS 4.75 -18.9 -4.75 -18.9 0.15 21 DS -4.75 -10.3 -4.75 10.3 0.15 21 DS -4.75 10.3 4.75 10.3 0.15 21 DS 4.75 10.3 4.75 -10.3 0.15 21 DS 4.75 -10.3 -4.75 -10.3 0.15 21 $PAD Sh "2" O 3.81 2.54 0 0 0 Dr 2.5 0 0 O 2.5 0.8 At STD N 00E0FFFF Ne 0 "" Po 0 0 $EndPAD $PAD Sh "1" O 3.81 2.54 0 0 0 Dr 2.5 0 0 O 2.5 0.8 At STD N 00E0FFFF Ne 0 "" Po 0 -5.58 $EndPAD $PAD Sh "3" O 3.81 2.54 0 0 0 Dr 2.5 0 0 O 2.5 0.8 At STD N 00E0FFFF Ne 0 "" Po 0 5.58 $EndPAD $PAD Sh "H1" C 4 4 0 0 0 Dr 3 0 0 At STD N 00E0FFFF Ne 0 "" Po 0 -15 $EndPAD $PAD Sh "H2" C 4 4 0 0 0 Dr 3 0 0 At STD N 00E0FFFF Ne 0 "" Po 0 15 $EndPAD $EndMODULE SW_KND2 $MODULE SW_KND2_PDP Po 0 0 0 15 54B2AA91 00000000 ~~ Li SW_KND2_PDP Cd Switch inverseur Kw SWITCH DEV Sc 0 AR Op 0 0 0 T0 4 0 0.3 0.3 900 0.05 N I 21 N "SW_KND2_1x2_PDP" T1 -0.05 -20.3 1.2 1.2 0 0.2032 N V 21 N "SW*" DS -4.75 7.8 -4.75 -10.3 0.15 21 DS -4.75 7.8 4.75 7.8 0.15 21 DS 4.75 7.8 4.75 -10.3 0.15 21 DS -4.75 -10.3 -4.75 -18.9 0.15 21 DS 4.75 -10.3 4.75 -18.9 0.15 21 DS 4.75 -18.9 -4.75 -18.9 0.15 21 DS 4.75 -10.3 -4.75 -10.3 0.15 21 $PAD Sh "1" O 3.81 2.54 0 0 0 Dr 2.5 0 0 O 2.5 0.8 At STD N 00E0FFFF Ne 0 "" Po 0 0 $EndPAD $PAD Sh "2" O 3.81 2.54 0 0 0 Dr 2.5 0 0 O 2.5 0.8 At STD N 00E0FFFF Ne 0 "" Po 0 -5.58 $EndPAD $PAD Sh "3" O 3.81 2.54 0 0 0 Dr 2.5 0 0 O 2.5 0.8 At STD N 00E0FFFF Ne 0 "" Po 0 5.58 $EndPAD $PAD Sh "H1" C 4 4 0 0 0 Dr 3 0 0 At STD N 00E0FFFF Ne 0 "" Po 0 -15 $EndPAD $EndMODULE SW_KND2_PDP $MODULE SW_KND2_PDP2 Po 0 0 0 15 554E2AD7 00000000 ~~ Li SW_KND2_PDP2 Cd Switch inverseur Kw SWITCH DEV Sc 0 AR Op 0 0 0 T0 3.429 -3.683 0.3 0.3 900 0.05 N I 21 N "SW_KND2_1x2_PDP" T1 -0.05 -20.3 1.2 1.2 0 0.2032 N V 21 N "SW*" DS -4.75 1.95 -4.75 -10.35 0.15 21 DS 4.75 -10.3 4.75 1.95 0.15 21 DS -4.75 1.958 4.75 1.958 0.15 21 DS -4.75 -10.3 -4.75 -18.9 0.15 21 DS 4.75 -10.3 4.75 -18.9 0.15 21 DS 4.75 -18.9 -4.75 -18.9 0.15 21 DS 4.75 -10.3 -4.75 -10.3 0.15 21 $PAD Sh "1" O 5.08 2.54 0 0 0 Dr 3.45 0 0 O 3.45 1.18 At STD N 00E0FFFF Ne 0 "" Po 0 0 $EndPAD $PAD Sh "2" O 5.08 2.54 0 0 0 Dr 3.45 0 0 O 3.45 1.15 At STD N 00E0FFFF Ne 0 "" Po 0 -5.58 $EndPAD $PAD Sh "3" C 4 4 0 0 0 Dr 3 0 0 At STD N 00E0FFFF Ne 0 "" Po 0 -15 $EndPAD $EndMODULE SW_KND2_PDP2 $EndLIBRARY |
cannot compute difference between binary files
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | v 20130925 2 C 39600 60100 1 0 0 5V-plus-1.sym { T 39600 60100 5 10 1 1 0 0 1 pinnumber=1 } C 39700 58200 1 0 0 gnd-1.sym { T 39600 58400 5 10 1 1 0 0 1 pinnumber=7 } C 40100 58200 1 0 0 gnd-1.sym { T 40000 58400 5 10 1 1 0 0 1 pinnumber=8 } C 40000 60100 1 0 0 5V-plus-1.sym { T 40000 60100 5 10 1 1 0 0 1 pinnumber=2 } C 38500 60600 1 270 0 switch-spst-1.sym { T 39200 60200 5 10 0 0 270 0 1 device=SPST T 38800 60400 5 10 1 1 270 0 1 refdes=Switch } N 40200 59300 40200 60100 4 N 39800 58500 39800 58700 4 N 40200 58500 40200 59000 4 C 37900 60300 1 0 0 BNC-1.sym { T 38250 60950 5 10 0 0 0 0 1 device=BNC T 37900 61000 5 10 1 1 0 0 1 refdes=DC Jack } B 39400 57800 1200 3000 3 0 0 0 -1 -1 0 -1 -1 -1 -1 -1 { T 40700 60100 5 10 1 1 270 0 1 name=Expansion Port Pins } N 38000 60300 38000 58700 4 N 38000 58700 39800 58700 4 N 38000 59000 40200 59000 4 N 39800 60100 39800 59600 4 N 38500 59600 39800 59600 4 N 38500 59300 38500 59800 4 N 40200 59300 38500 59300 4 N 38400 60800 38500 60800 4 N 38500 60800 38500 60600 4 T 37800 56300 9 10 1 0 0 0 5 Copyright © 2016 by Warren Young This file is licensed under the terms of the SIMH license, a copy of which is in ../SIMH-LICENSE.md. |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | # USB Stick Labels ## What It Is This directory contains an Inkscape document (`*.svg`) containing the DECtape logo and USB stick labels with graphics based on that label. There are three example labels in the document: * **BIN Loader** for `media/copytoUSBsticks/binloader.pt` * **FOCAL-69** for `media/copytoUSBsticks/focal.pt` * **ADD.PA** for `examples/add.pt` These labels use the "DECtape" graphics even though they're paper tapes, primarily because it's a nice graphic and I haven't bothered to draw something appropriate to paper tapes yet. The labels print out at approximately 30×16mm each, which fits the USB sticks I have here, but you may need to scale the printout for your particular USB sticks. ## Affixing the Labels This document is not designed with any particular self-adhesive label stock in mind. Instead, I simply use rubber cement as a contact adhesive to affix these labels to the USB stick. Simply cut the label(s) you want to use out with scissors, paint both the back of the label and the top of the USB stick with rubber cement, and let it dry for a minute or so. When the glue is dry-looking, carefully place the label where you want it on the USB stick. You won't have much of a chance to move the label around after the two dried glue patches touch, so be careful with your placement. Press the label firmly against the stick, pressing repeatedly to cover the entire surface, then rub around the label gently to brush away any excess cement. Protip: Use the part of the page you cut the labels out of as a protective mat to work on. It will let you apply cement to the label fully edge-to-edge without messing up your work surface. The labels will be much more durable if there is no unglued bit near the edge for fingernails and such to snag on. You were going to throw this excess material away, so you might as well get one final use out of it, yes? ## Fonts This SVG file uses a non-free font called [Dottie][font] for the faux dot matrix text. There are [free alternatives][alt], but none of the ones I liked allow redistribution, so I couldn't include one of them in this repository. [font]: https://www.fonts.com/font/ingrimayne-type/dottie/regular [alt]: http://www.1001fonts.com/digital+dot-matrix-fonts.html ## PDF Version If you don't want to use one of those alternative fonts or simply like the look of Dottie and don't need custom labels, this directory also includes a PDF of the same design with the necessary subset of Dottie embedded, so that you can print it out. |
cannot compute difference between binary files
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg2" version="1.1" inkscape:version="0.91 r13725" xml:space="preserve" width="765" height="990" viewBox="0 0 765 990" sodipodi:docname="dectape-usb-key.svg"><title id="title4244">PiDP-8/I USB key labels</title><metadata id="metadata8"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title>PiDP-8/I USB key labels</dc:title><dc:date>December 2016</dc:date><dc:creator><cc:Agent><dc:title>Warren Young</dc:title></cc:Agent></dc:creator><dc:rights><cc:Agent><dc:title>see license</dc:title></cc:Agent></dc:rights><dc:language>English</dc:language><dc:subject><rdf:Bag><rdf:li>label</rdf:li><rdf:li>USB</rdf:li><rdf:li>DEC</rdf:li><rdf:li>PDP-8</rdf:li><rdf:li>dot matrix</rdf:li><rdf:li>DECtape</rdf:li></rdf:Bag></dc:subject><dc:description>Graphical labels for use on USB sticks containing binary media images suitable for use with the PiDP-8/I's USB stick auto-attaching feature.</dc:description><cc:license rdf:resource="https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md" /></cc:Work></rdf:RDF></metadata><defs id="defs6"><clipPath clipPathUnits="userSpaceOnUse" id="clipPath18"><path d="M 0,0 612,0 612,792 0,792 0,0 Z" id="path20" inkscape:connector-curvature="0" /></clipPath><filter inkscape:label="Opacity" style="color-interpolation-filters:sRGB;" id="filter3471"><feColorMatrix values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 -0 " result="colormatrix" id="feColorMatrix3473" /><feComposite in2="colormatrix" operator="arithmetic" k2="0.343085" result="composite" id="feComposite3475" /></filter></defs><sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="2560" inkscape:window-height="1391" id="namedview4" showgrid="false" inkscape:zoom="3.17" inkscape:cx="117.85871" inkscape:cy="792.26542" inkscape:window-x="0" inkscape:window-y="1" inkscape:window-maximized="1" inkscape:current-layer="layer2" showguides="true" inkscape:guide-bbox="true"><sodipodi:guide position="278.68734,454.12002" orientation="0,1" id="guide3550" /><sodipodi:guide position="294.28136,404.66471" orientation="0,1" id="guide3552" /></sodipodi:namedview><g id="g10" inkscape:groupmode="layer" inkscape:label="reference" transform="matrix(1.25,0,0,-1.25,0,990)" style="display:inline"><g id="g12" /></g><g inkscape:groupmode="layer" id="layer1" inkscape:label="inner elements" style="display:inline" /><g inkscape:groupmode="layer" id="layer2" inkscape:label="ring" style="display:inline"><g id="g4253" transform="translate(-3.4700316,-242.58675)"><ellipse ry="37.22398" rx="39.077209" style="display:inline;fill:none;fill-opacity:1;stroke:none;stroke-width:0.99528235;stroke-opacity:1" id="circle4384" cx="88.770988" cy="306.1496" /><g inkscape:label="#g3477" style="display:inline;fill:#1e97ec;fill-opacity:1;stroke:none" id="digital-logo" transform="matrix(0.05536257,0,0,-0.05536257,75.852793,325.57701)"><g style="fill:#1e97ec;fill-opacity:1;stroke:none" id="g3479" clip-path="url(#clipPath18)"><path d="m 101.3,107.13 c 0.02,-2.96 -3.43,-7.55 -7.63,-7.56 -4.48,0.02 -8.87,4.08 -8.87,12.2 0,8.24 4.38,12.48 8.73,12.5 4.34,-0.02 7.79,-4.67 7.77,-8.2 l 0,-8.94 z m 0.23,22.74 0,18.13 8.9,0 0,-56.4 -9.2,0 0,2.6 c -0.75,-0.76 -3.92,-4.07 -9.33,-4.07 -5.64,-0.01 -15.73,4.69 -15.73,21.64 0,14.37 7.54,21.8 16.5,21.8 3.32,0 6.58,-1.18 8.86,-3.7 z M 72,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m 7,0 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,40.4 9,0 0,-40.4 z m -9,0 z m 9,45.9 -9,0 0,10 9,0 0,-10 z m -9,0 z m 61.18,-20.72 c 0,3.59 -4.04,7.3 -7.78,7.3 -3.22,0 -8.2,-2.05 -8.2,-11.24 0,-9.79 6.12,-11.22 8.15,-11.22 4.03,0 7.83,2.77 7.83,7.05 l 0,8.11 z M 171,172 l 42.5,0 0,-100 -42.5,0 0,100 z m 28.52,-43.91 c -0.93,1.33 -3.98,4.35 -8.34,4.35 -6.77,-0.01 -16.21,-3.92 -16.21,-20.89 0.01,-13.38 10.7,-17.87 15.09,-17.87 4.74,-0.01 8.26,2.75 9.22,3.79 l 0,-4.21 c 0,-3.11 -3.19,-6.15 -8.53,-6.15 -4.6,0.01 -5.08,2.96 -5.08,4.42 l -9.4,0 c 0,-4.67 3.01,-11.49 13.91,-11.5 9.76,0 12.98,3.73 14.37,5.13 1.17,1.18 2.92,4.42 2.92,7.01 l 0,39.83 -7.94,0 -0.01,-3.91 z M 220.5,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,40.4 9,0 0,-40.4 z m -9,0 z m 9,45.9 -9,0 0,10 9,0 0,-10 z m -9,0 z m 56.03,9.75 -8.23,0 0,-14.54 -4.31,0 0,-6.75 4.31,0 0,-25.44 c 0,-4.85 2.49,-8.66 9.43,-8.65 3.25,0 3.12,-0.02 5.94,0.47 l 0,8.4 c -1.84,-0.32 -2.41,-0.45 -3.31,-0.42 -1.73,0.05 -3.83,0.66 -3.83,3.74 l 0,21.89 6.52,0 0,6.76 -6.52,0 0,14.54 z M 312.5,72 270,72 l 0,100 42.5,0 0,-100 z m 49.5,0 -42.5,0 0,100 42.5,0 0,-100 z m -42.5,0 z m 6.99,47.28 7.71,0 c 0,4.1 2.12,6.25 6.16,6.25 6.44,0.01 6.23,-2.86 6.22,-6.45 -3.98,-1.55 -3.61,-1.51 -9.68,-2.89 -7.71,-1.78 -12.43,-5.08 -12.44,-13.07 0.01,-7.81 5.57,-11.98 11.84,-11.97 6.28,-0.01 7.58,2.02 10.18,3.75 l 0,-3.12 9.84,0 c -2.32,3.74 -1.71,4.47 -1.73,7.28 0.01,2.2 0,23.74 0,23.74 0.01,4.27 -2.21,6.88 -3.66,7.75 -3.62,2.16 -8.09,2.42 -10.57,2.43 -8.81,-0.02 -13.88,-4.45 -13.87,-13.7 z m 20.09,-7.82 0,-5.45 c 0,-2.49 -3.03,-7.31 -8.98,-7.32 -2.9,-0.01 -4.52,2.14 -4.53,4.93 0.01,2.8 2.38,4.95 4.39,5.35 2.09,0.42 6.9,1.65 9.12,2.49 z M 369,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,56.9 9,0 0,-56.9 z" style="fill:#1e97ec;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path3481" inkscape:connector-curvature="0" /></g></g><g transform="matrix(0.140057,0,0,0.140057,28.143932,232.97391)" inkscape:label="#g4177" id="text" style="display:inline"><text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:32px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#1e97ec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="234.70551" y="-270.57205" id="text3511" sodipodi:linespacing="125%" transform="matrix(1.25,0,0,1.25,0,990)"><tspan sodipodi:role="line" id="tspan3513" x="234.70551" y="-270.57205" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:13px;font-family:'Helvetica Neue';-inkscape-font-specification:'Helvetica Neue Bold';fill:#1e97ec;fill-opacity:1;stroke:none">DIGITAL EQUIPMENT CORPORATION</tspan></text> <text transform="matrix(1.25,0,0,1.25,0,990)" sodipodi:linespacing="125%" id="text3515" y="-258.09683" x="252.52724" style="font-style:normal;font-weight:normal;font-size:32px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#1e97ec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" xml:space="preserve"><tspan style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:11px;font-family:'Helvetica Neue';-inkscape-font-specification:'Helvetica Neue Bold';fill:#1e97ec;fill-opacity:1;stroke:none" y="-258.09683" x="252.52724" id="tspan3517" sodipodi:role="line">MAYNARD, MASSACHUSETTS, 01754</tspan></text> <text transform="matrix(1.25,0,0,1.25,0,990)" sodipodi:linespacing="125%" id="text3519" y="-237.42363" x="236.84412" style="font-style:normal;font-weight:normal;font-size:32px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#1e97ec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" xml:space="preserve"><tspan style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:15px;font-family:'Helvetica Neue';-inkscape-font-specification:'Helvetica Neue Bold';letter-spacing:0.80000001px;fill:#1e97ec;fill-opacity:1;stroke:none" y="-237.42363" x="236.84412" id="tspan3521" sodipodi:role="line">REEL NO.</tspan></text> <text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:32px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#1e97ec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="422.72479" y="-237.42363" id="text3523" sodipodi:linespacing="125%" transform="matrix(1.25,0,0,1.25,0,990)"><tspan sodipodi:role="line" id="tspan3525" x="422.72479" y="-237.42363" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:15px;font-family:'Helvetica Neue';-inkscape-font-specification:'Helvetica Neue Bold';letter-spacing:0.80000001px;fill:#1e97ec;fill-opacity:1;stroke:none">DATE</tspan></text> </g><path inkscape:connector-curvature="0" d="m 72.199362,308.19926 0,6.84856 1.404033,-0.0156 c 0,0 4.448809,0.2496 4.461705,-3.60369 0.01175,-3.51016 -4.430504,-3.27607 -4.430504,-3.27607 z m 1.326032,1.31043 0,4.1965 0.686416,0 c 0,0 2.523387,0.12492 2.542859,-2.30886 0.0156,-1.95004 -2.402456,-1.91884 -2.402456,-1.91884 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path3539" /><path inkscape:connector-curvature="0" id="path3554" d="m 78.252303,308.02765 0,6.92656 3.588086,0 0,-1.29483 -2.106051,0 0,-1.54443 2.028048,0 0,-1.31043 -2.074848,0 0,-1.41964 2.059249,0 0,-1.35723 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path3556" d="m 87.48772,310.0089 1.450835,0 c 0,0 -0.702017,-2.23085 -3.416481,-2.23085 -2.714464,0 -3.572483,2.38685 -3.572483,3.74408 0,1.35724 1.294829,3.43208 3.775287,3.43208 2.480459,0 3.229277,-2.04364 3.229277,-2.04364 l -1.466435,0 c 0,0 -0.358807,0.71761 -1.747241,0.71761 -1.388432,0 -2.402456,-0.99842 -2.402456,-2.23085 0,-1.23243 0.951623,-2.16845 2.230851,-2.16845 1.279232,0 1.918846,0.78002 1.918846,0.78002 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path3558" d="m 89.219362,308.02765 0,6.92656 1.669238,0 0,-5.46012 -1.201229,0 0,-1.46644 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path3560" d="m 92.152229,314.95421 0,-5.47572 1.29483,0 0.0312,-1.45084 3.697286,0 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path3562" d="m 93.868269,314.95421 1.357232,-1.90324 1.560036,0 0,1.90324 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path sodipodi:nodetypes="cccc" inkscape:connector-curvature="0" id="path3564" d="m 96.052321,311.84974 0.748816,-1.06082 0,1.04522 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path3566" d="m 98.080369,308.02765 0,6.92656 0.530412,0 0,-6.92656 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path3568" d="m 99.87441,309.32248 0,1.79404 0.67082,0.0156 c 0,0 0.99842,-0.1248 0.99842,-0.92042 0,-0.79562 -1.02962,-0.85802 -1.02962,-0.85802 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path3570" d="m 99.936811,312.28655 0,2.66766 3.057669,0 0,-6.92656 -1.84084,0 c 0,0 1.56004,0.35881 1.56004,2.32446 0,1.96564 -1.90325,1.95004 -1.90325,1.95004 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><g transform="matrix(0.140057,0,0,0.140057,28.143932,232.97391)" inkscape:label="#g4171" id="dectape-graphics" style="display:inline"><path transform="matrix(1.25,0,0,-1.25,0,990)" style="fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 139.98514,433.20896 410.6593,-5.07131 c 0,0 -5.97508,23.16953 -13.43181,38.13146 -167.11395,1.42458 -326.54993,2.93466 -382.95298,3.28558 -9.80882,-18.26995 -14.27451,-36.34573 -14.27451,-36.34573 z" id="path3574" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc" /><path transform="matrix(1.25,0,0,-1.25,0,990)" style="fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 163.42461,486.64088 c 0,0 17.16387,25.4632 30.545,37.27097 14.36613,-10e-6 304.87219,-2.95063 304.87219,-2.95063 0,0 18.39873,-19.40688 28.73226,-37.55356 -41.33413,-0.25205 -364.14945,3.23322 -364.14945,3.23322 z" id="path3576" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc" /><path transform="matrix(1.25,0,0,-1.25,0,990)" style="fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 208.21343,538.27798 277.34946,-3.48528 c 0,0 -34.54921,30.89095 -64.85267,39.09636 -20.66706,0.50408 -148.33167,1.15579 -148.33167,1.15579 0,0 -35.4761,-11.99339 -64.16512,-36.76687 z" id="path3578" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc" /><path transform="matrix(1.25,0,0,-1.25,0,990)" style="fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 446.79083,363.29602 0,-7.57424 -11.58413,0 0,-9.53463 11.49503,0 0,-6.23761 -11.76235,0 0,-9.62373 11.85145,0 0,-6.59404 56.4949,0 c 0,0 38.49493,6.86137 38.49493,45.35631 0,38.49494 -42.59393,44.82166 -42.59393,44.82166 l -363.02869,3.74256 c 0,0 -5.43563,-22.45538 -5.43563,-40.00979 15.77223,0 363.1178,-2.67326 363.1178,-2.67326 0,0 6.86137,0.35644 6.86137,-6.1485 0,-6.50493 -6.23761,-5.52473 -6.23761,-5.52473 z" id="path3572" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccccsccccscc" /></g><path inkscape:label="#circle4400" inkscape:connector-curvature="0" id="ring" d="M 88.506113,265.74856 A 40.577442,40.577442 0 0 0 47.928702,306.32597 40.577442,40.577442 0 0 0 88.506113,346.90365 40.577442,40.577442 0 0 0 129.0838,306.32597 40.577442,40.577442 0 0 0 88.506113,265.74856 Z m 0,2.02535 A 38.375756,38.552254 0 0 1 126.88201,306.32597 38.375756,38.552254 0 0 1 88.506113,344.8783 38.375756,38.552254 0 0 1 50.130497,306.32597 38.375756,38.552254 0 0 1 88.506113,267.77391 Z" style="display:inline;fill:#53a6c2;fill-opacity:1;stroke:none;stroke-width:1.16711712;stroke-opacity:1" /></g><text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:5.5970993px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="3.6412585" y="379.60495" id="text4175" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4177" x="3.6412585" y="379.60495" /></text> <text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:10.07446671px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="48.558857" y="344.43402" id="text4177" sodipodi:linespacing="125%"><tspan sodipodi:role="line" x="48.558857" y="344.43402" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.29654121px;font-family:Dottie;-inkscape-font-specification:Dottie" id="tspan4185" /></text> <text sodipodi:linespacing="125%" id="text4251" y="445.44971" x="3.6412585" style="font-style:normal;font-weight:normal;font-size:5.5970993px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" xml:space="preserve"><tspan y="445.44971" x="3.6412585" id="tspan4253" sodipodi:role="line" /></text> <ellipse ry="37.22398" rx="39.077209" style="display:inline;fill:none;fill-opacity:1;stroke:none;stroke-width:0.99528235;stroke-opacity:1" id="ellipse4269" cx="188.95584" cy="309.14252" /><g id="g4403" transform="translate(-3.4700316,-242.58675)"><rect style="fill:none;fill-opacity:1;stroke:#dcdcdc;stroke-width:0.33938482;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect4249" width="98.517426" height="51.003555" x="42.359982" y="431.91147" /><text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:12.70192051px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="46.723854" y="443.1936" id="text4255" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4257" x="46.723854" y="443.1936" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.93869972px;font-family:Dottie;-inkscape-font-specification:Dottie">BIN LOADER</tspan><tspan id="tspan4425" sodipodi:role="line" x="46.723854" y="453.11697" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.93869972px;font-family:Dottie;-inkscape-font-specification:Dottie">DEC-08-LBAA-PM</tspan><tspan sodipodi:role="line" x="46.723854" y="463.04034" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.93869972px;font-family:Dottie;-inkscape-font-specification:Dottie" id="tspan4261">5/10/67 SA:7777</tspan><tspan sodipodi:role="line" x="46.723854" y="472.96371" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.93869972px;font-family:Dottie;-inkscape-font-specification:Dottie" id="tspan4263" /></text> <g id="g4393" transform="translate(-0.5513317,64.832146)"><g transform="matrix(0.03699838,0,0,-0.03699838,88.960048,419.11479)" id="g4395" style="display:inline;fill:#1e97ec;fill-opacity:1;stroke:none" inkscape:label="#g3477"><g clip-path="url(#clipPath18)" id="g4397" style="fill:#1e97ec;fill-opacity:1;stroke:none"><path inkscape:connector-curvature="0" id="path4399" style="fill:#1e97ec;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 101.3,107.13 c 0.02,-2.96 -3.43,-7.55 -7.63,-7.56 -4.48,0.02 -8.87,4.08 -8.87,12.2 0,8.24 4.38,12.48 8.73,12.5 4.34,-0.02 7.79,-4.67 7.77,-8.2 l 0,-8.94 z m 0.23,22.74 0,18.13 8.9,0 0,-56.4 -9.2,0 0,2.6 c -0.75,-0.76 -3.92,-4.07 -9.33,-4.07 -5.64,-0.01 -15.73,4.69 -15.73,21.64 0,14.37 7.54,21.8 16.5,21.8 3.32,0 6.58,-1.18 8.86,-3.7 z M 72,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m 7,0 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,40.4 9,0 0,-40.4 z m -9,0 z m 9,45.9 -9,0 0,10 9,0 0,-10 z m -9,0 z m 61.18,-20.72 c 0,3.59 -4.04,7.3 -7.78,7.3 -3.22,0 -8.2,-2.05 -8.2,-11.24 0,-9.79 6.12,-11.22 8.15,-11.22 4.03,0 7.83,2.77 7.83,7.05 l 0,8.11 z M 171,172 l 42.5,0 0,-100 -42.5,0 0,100 z m 28.52,-43.91 c -0.93,1.33 -3.98,4.35 -8.34,4.35 -6.77,-0.01 -16.21,-3.92 -16.21,-20.89 0.01,-13.38 10.7,-17.87 15.09,-17.87 4.74,-0.01 8.26,2.75 9.22,3.79 l 0,-4.21 c 0,-3.11 -3.19,-6.15 -8.53,-6.15 -4.6,0.01 -5.08,2.96 -5.08,4.42 l -9.4,0 c 0,-4.67 3.01,-11.49 13.91,-11.5 9.76,0 12.98,3.73 14.37,5.13 1.17,1.18 2.92,4.42 2.92,7.01 l 0,39.83 -7.94,0 -0.01,-3.91 z M 220.5,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,40.4 9,0 0,-40.4 z m -9,0 z m 9,45.9 -9,0 0,10 9,0 0,-10 z m -9,0 z m 56.03,9.75 -8.23,0 0,-14.54 -4.31,0 0,-6.75 4.31,0 0,-25.44 c 0,-4.85 2.49,-8.66 9.43,-8.65 3.25,0 3.12,-0.02 5.94,0.47 l 0,8.4 c -1.84,-0.32 -2.41,-0.45 -3.31,-0.42 -1.73,0.05 -3.83,0.66 -3.83,3.74 l 0,21.89 6.52,0 0,6.76 -6.52,0 0,14.54 z M 312.5,72 270,72 l 0,100 42.5,0 0,-100 z m 49.5,0 -42.5,0 0,100 42.5,0 0,-100 z m -42.5,0 z m 6.99,47.28 7.71,0 c 0,4.1 2.12,6.25 6.16,6.25 6.44,0.01 6.23,-2.86 6.22,-6.45 -3.98,-1.55 -3.61,-1.51 -9.68,-2.89 -7.71,-1.78 -12.43,-5.08 -12.44,-13.07 0.01,-7.81 5.57,-11.98 11.84,-11.97 6.28,-0.01 7.58,2.02 10.18,3.75 l 0,-3.12 9.84,0 c -2.32,3.74 -1.71,4.47 -1.73,7.28 0.01,2.2 0,23.74 0,23.74 0.01,4.27 -2.21,6.88 -3.66,7.75 -3.62,2.16 -8.09,2.42 -10.57,2.43 -8.81,-0.02 -13.88,-4.45 -13.87,-13.7 z m 20.09,-7.82 0,-5.45 c 0,-2.49 -3.03,-7.31 -8.98,-7.32 -2.9,-0.01 -4.52,2.14 -4.53,4.93 0.01,2.8 2.38,4.95 4.39,5.35 2.09,0.42 6.9,1.65 9.12,2.49 z M 369,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,56.9 9,0 0,-56.9 z" /></g></g><path id="path4401" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 106.30956,411.81751 0,4.57684 0.9383,-0.0104 c 0,0 2.97311,0.1668 2.98173,-2.40832 0.008,-2.34582 -2.96088,-2.18938 -2.96088,-2.18938 z m 0.88618,0.87575 0,2.80449 0.45873,0 c 0,0 1.68636,0.0835 1.69937,-1.54299 0.0104,-1.3032 -1.60555,-1.28235 -1.60555,-1.28235 z" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 110.35469,411.70282 0,4.62897 2.3979,0 0,-0.86532 -1.40746,0 0,-1.03213 1.35532,0 0,-0.87575 -1.3866,0 0,-0.94874 1.37618,0 0,-0.90703 z" id="path4403" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 116.52666,413.02688 0.96958,0 c 0,0 -0.46915,-1.49086 -2.28321,-1.49086 -1.81406,0 -2.38747,1.59511 -2.38747,2.50214 0,0.90703 0.86533,2.29363 2.523,2.29363 1.65767,0 2.1581,-1.36575 2.1581,-1.36575 l -0.98,0 c 0,0 -0.23979,0.47958 -1.16767,0.47958 -0.92789,0 -1.60555,-0.66724 -1.60555,-1.49086 0,-0.82363 0.63596,-1.44916 1.49086,-1.44916 0.8549,0 1.28236,0.52128 1.28236,0.52128 z" id="path4405" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 117.6839,411.70282 0,4.62897 1.11554,0 0,-3.64895 -0.80277,0 0,-0.98002 z" id="path4407" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 119.64391,416.33179 0,-3.65938 0.86533,0 0.0208,-0.96959 2.47087,0 z" id="path4409" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 120.79073,416.33179 0.90703,-1.27192 1.04255,0 0,1.27192 z" id="path4411" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 122.25032,414.2571 0.50043,-0.70894 0,0.69851 z" id="path4413" inkscape:connector-curvature="0" sodipodi:nodetypes="cccc" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 123.60565,411.70282 0,4.62897 0.35447,0 0,-4.62897 z" id="path4415" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 124.80459,412.56815 0,1.19894 0.4483,0.0104 c 0,0 0.66724,-0.0834 0.66724,-0.61511 0,-0.53171 -0.68809,-0.57341 -0.68809,-0.57341 z" id="path4417" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 124.84629,414.54901 0,1.78278 2.04342,0 0,-4.62897 -1.23022,0 c 0,0 1.04256,0.23979 1.04256,1.55342 0,1.31363 -1.27192,1.3032 -1.27192,1.3032 z" id="path4419" inkscape:connector-curvature="0" /><path style="fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 129.14164,411.70282 0,0.88618 -1.35533,0 0,1.11554 1.34491,0 0,0.7298 -1.37619,0 0,1.12596 1.38661,0 0,0.77149 6.60983,0 c 0,0 4.50387,-0.80276 4.50387,-5.30663 0,-4.50386 -4.98345,-5.24408 -4.98345,-5.24408 l -90.87296,-0.43787 c 0,0 -0.04525,2.62725 -0.04525,4.68109 1.845329,0 90.29268,0.31277 90.29268,0.31277 0,0 0.80277,-0.0417 0.80277,0.71937 0,0.76107 -0.72979,0.64638 -0.72979,0.64638 z" id="path4421" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccccsccccscc" /></g></g><g id="g4381" transform="translate(-3.4700316,-242.58675)"><rect y="366.06671" x="42.359982" height="51.003555" width="98.517426" id="rect4187" style="fill:none;fill-opacity:1;stroke:#dcdcdc;stroke-width:0.33938482;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /><g transform="translate(-0.5513317,-0.5513317)" id="g4377"><g inkscape:label="#g3477" style="display:inline;fill:#1e97ec;fill-opacity:1;stroke:none" id="g4271" transform="matrix(0.03699838,0,0,-0.03699838,88.960048,419.11479)"><g style="fill:#1e97ec;fill-opacity:1;stroke:none" id="g4273" clip-path="url(#clipPath18)"><path d="m 101.3,107.13 c 0.02,-2.96 -3.43,-7.55 -7.63,-7.56 -4.48,0.02 -8.87,4.08 -8.87,12.2 0,8.24 4.38,12.48 8.73,12.5 4.34,-0.02 7.79,-4.67 7.77,-8.2 l 0,-8.94 z m 0.23,22.74 0,18.13 8.9,0 0,-56.4 -9.2,0 0,2.6 c -0.75,-0.76 -3.92,-4.07 -9.33,-4.07 -5.64,-0.01 -15.73,4.69 -15.73,21.64 0,14.37 7.54,21.8 16.5,21.8 3.32,0 6.58,-1.18 8.86,-3.7 z M 72,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m 7,0 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,40.4 9,0 0,-40.4 z m -9,0 z m 9,45.9 -9,0 0,10 9,0 0,-10 z m -9,0 z m 61.18,-20.72 c 0,3.59 -4.04,7.3 -7.78,7.3 -3.22,0 -8.2,-2.05 -8.2,-11.24 0,-9.79 6.12,-11.22 8.15,-11.22 4.03,0 7.83,2.77 7.83,7.05 l 0,8.11 z M 171,172 l 42.5,0 0,-100 -42.5,0 0,100 z m 28.52,-43.91 c -0.93,1.33 -3.98,4.35 -8.34,4.35 -6.77,-0.01 -16.21,-3.92 -16.21,-20.89 0.01,-13.38 10.7,-17.87 15.09,-17.87 4.74,-0.01 8.26,2.75 9.22,3.79 l 0,-4.21 c 0,-3.11 -3.19,-6.15 -8.53,-6.15 -4.6,0.01 -5.08,2.96 -5.08,4.42 l -9.4,0 c 0,-4.67 3.01,-11.49 13.91,-11.5 9.76,0 12.98,3.73 14.37,5.13 1.17,1.18 2.92,4.42 2.92,7.01 l 0,39.83 -7.94,0 -0.01,-3.91 z M 220.5,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,40.4 9,0 0,-40.4 z m -9,0 z m 9,45.9 -9,0 0,10 9,0 0,-10 z m -9,0 z m 56.03,9.75 -8.23,0 0,-14.54 -4.31,0 0,-6.75 4.31,0 0,-25.44 c 0,-4.85 2.49,-8.66 9.43,-8.65 3.25,0 3.12,-0.02 5.94,0.47 l 0,8.4 c -1.84,-0.32 -2.41,-0.45 -3.31,-0.42 -1.73,0.05 -3.83,0.66 -3.83,3.74 l 0,21.89 6.52,0 0,6.76 -6.52,0 0,14.54 z M 312.5,72 270,72 l 0,100 42.5,0 0,-100 z m 49.5,0 -42.5,0 0,100 42.5,0 0,-100 z m -42.5,0 z m 6.99,47.28 7.71,0 c 0,4.1 2.12,6.25 6.16,6.25 6.44,0.01 6.23,-2.86 6.22,-6.45 -3.98,-1.55 -3.61,-1.51 -9.68,-2.89 -7.71,-1.78 -12.43,-5.08 -12.44,-13.07 0.01,-7.81 5.57,-11.98 11.84,-11.97 6.28,-0.01 7.58,2.02 10.18,3.75 l 0,-3.12 9.84,0 c -2.32,3.74 -1.71,4.47 -1.73,7.28 0.01,2.2 0,23.74 0,23.74 0.01,4.27 -2.21,6.88 -3.66,7.75 -3.62,2.16 -8.09,2.42 -10.57,2.43 -8.81,-0.02 -13.88,-4.45 -13.87,-13.7 z m 20.09,-7.82 0,-5.45 c 0,-2.49 -3.03,-7.31 -8.98,-7.32 -2.9,-0.01 -4.52,2.14 -4.53,4.93 0.01,2.8 2.38,4.95 4.39,5.35 2.09,0.42 6.9,1.65 9.12,2.49 z M 369,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,56.9 9,0 0,-56.9 z" style="fill:#1e97ec;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path4275" inkscape:connector-curvature="0" /></g></g><path inkscape:connector-curvature="0" d="m 106.30956,411.81751 0,4.57684 0.9383,-0.0104 c 0,0 2.97311,0.1668 2.98173,-2.40832 0.008,-2.34582 -2.96088,-2.18938 -2.96088,-2.18938 z m 0.88618,0.87575 0,2.80449 0.45873,0 c 0,0 1.68636,0.0835 1.69937,-1.54299 0.0104,-1.3032 -1.60555,-1.28235 -1.60555,-1.28235 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path4295" /><path inkscape:connector-curvature="0" id="path4297" d="m 110.35469,411.70282 0,4.62897 2.3979,0 0,-0.86532 -1.40746,0 0,-1.03213 1.35532,0 0,-0.87575 -1.3866,0 0,-0.94874 1.37618,0 0,-0.90703 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path4299" d="m 116.52666,413.02688 0.96958,0 c 0,0 -0.46915,-1.49086 -2.28321,-1.49086 -1.81406,0 -2.38747,1.59511 -2.38747,2.50214 0,0.90703 0.86533,2.29363 2.523,2.29363 1.65767,0 2.1581,-1.36575 2.1581,-1.36575 l -0.98,0 c 0,0 -0.23979,0.47958 -1.16767,0.47958 -0.92789,0 -1.60555,-0.66724 -1.60555,-1.49086 0,-0.82363 0.63596,-1.44916 1.49086,-1.44916 0.8549,0 1.28236,0.52128 1.28236,0.52128 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path4301" d="m 117.6839,411.70282 0,4.62897 1.11554,0 0,-3.64895 -0.80277,0 0,-0.98002 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path4303" d="m 119.64391,416.33179 0,-3.65938 0.86533,0 0.0208,-0.96959 2.47087,0 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path4305" d="m 120.79073,416.33179 0.90703,-1.27192 1.04255,0 0,1.27192 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path sodipodi:nodetypes="cccc" inkscape:connector-curvature="0" id="path4307" d="m 122.25032,414.2571 0.50043,-0.70894 0,0.69851 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path4309" d="m 123.60565,411.70282 0,4.62897 0.35447,0 0,-4.62897 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path4311" d="m 124.80459,412.56815 0,1.19894 0.4483,0.0104 c 0,0 0.66724,-0.0834 0.66724,-0.61511 0,-0.53171 -0.68809,-0.57341 -0.68809,-0.57341 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path inkscape:connector-curvature="0" id="path4313" d="m 124.84629,414.54901 0,1.78278 2.04342,0 0,-4.62897 -1.23022,0 c 0,0 1.04256,0.23979 1.04256,1.55342 0,1.31363 -1.27192,1.3032 -1.27192,1.3032 z" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /><path sodipodi:nodetypes="cccccccccccsccccscc" inkscape:connector-curvature="0" id="path4323" d="m 129.14164,411.70282 0,0.88618 -1.35533,0 0,1.11554 1.34491,0 0,0.7298 -1.37619,0 0,1.12596 1.38661,0 0,0.77149 6.60983,0 c 0,0 4.50387,-0.80276 4.50387,-5.30663 0,-4.50386 -4.98345,-5.24408 -4.98345,-5.24408 l -90.87296,-0.43787 c 0,0 -0.04525,2.62725 -0.04525,4.68109 1.845329,0 90.29268,0.31277 90.29268,0.31277 0,0 0.80277,-0.0417 0.80277,0.71937 0,0.76107 -0.72979,0.64638 -0.72979,0.64638 z" style="fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /></g><text sodipodi:linespacing="125%" id="text4427" y="378.7012" x="46.723854" style="font-style:normal;font-weight:normal;font-size:12.70192051px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" xml:space="preserve"><tspan id="tspan4455" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.93869972px;font-family:Dottie;-inkscape-font-specification:Dottie" y="378.7012" x="46.723854" sodipodi:role="line">FOCAL-69</tspan><tspan id="tspan4459" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.93869972px;font-family:Dottie;-inkscape-font-specification:Dottie" y="388.62457" x="46.723854" sodipodi:role="line">DEC-08-AJAB-PB</tspan><tspan id="tspan4465" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.93869972px;font-family:Dottie;-inkscape-font-specification:Dottie" y="398.54794" x="46.723854" sodipodi:role="line">4/29/68 SA:0200</tspan></text> </g><rect style="fill:none;fill-opacity:1;stroke:#dcdcdc;stroke-width:0.33938482;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect4428" width="98.517426" height="51.003555" x="38.88995" y="254.30894" /><text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:12.70192051px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="43.253822" y="265.59109" id="text4430" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4432" x="43.253822" y="265.59109" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.93869972px;font-family:Dottie;-inkscape-font-specification:Dottie">ADD.PA</tspan><tspan id="tspan4434" sodipodi:role="line" x="43.253822" y="275.51447" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.93869972px;font-family:Dottie;-inkscape-font-specification:Dottie">PIDP-8/I Example</tspan><tspan sodipodi:role="line" x="43.253822" y="285.43784" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.93869972px;font-family:Dottie;-inkscape-font-specification:Dottie" id="tspan4436">11/27/16 SA:0200</tspan><tspan sodipodi:role="line" x="43.253822" y="295.36121" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.93869972px;font-family:Dottie;-inkscape-font-specification:Dottie" id="tspan4438" /></text> <g id="g4440" transform="translate(-4.0213633,-112.77037)"><g transform="matrix(0.03699838,0,0,-0.03699838,88.960048,419.11479)" id="g4442" style="display:inline;fill:#1e97ec;fill-opacity:1;stroke:none" inkscape:label="#g3477"><g clip-path="url(#clipPath18)" id="g4444" style="fill:#1e97ec;fill-opacity:1;stroke:none"><path inkscape:connector-curvature="0" id="path4446" style="fill:#1e97ec;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 101.3,107.13 c 0.02,-2.96 -3.43,-7.55 -7.63,-7.56 -4.48,0.02 -8.87,4.08 -8.87,12.2 0,8.24 4.38,12.48 8.73,12.5 4.34,-0.02 7.79,-4.67 7.77,-8.2 l 0,-8.94 z m 0.23,22.74 0,18.13 8.9,0 0,-56.4 -9.2,0 0,2.6 c -0.75,-0.76 -3.92,-4.07 -9.33,-4.07 -5.64,-0.01 -15.73,4.69 -15.73,21.64 0,14.37 7.54,21.8 16.5,21.8 3.32,0 6.58,-1.18 8.86,-3.7 z M 72,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m 7,0 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,40.4 9,0 0,-40.4 z m -9,0 z m 9,45.9 -9,0 0,10 9,0 0,-10 z m -9,0 z m 61.18,-20.72 c 0,3.59 -4.04,7.3 -7.78,7.3 -3.22,0 -8.2,-2.05 -8.2,-11.24 0,-9.79 6.12,-11.22 8.15,-11.22 4.03,0 7.83,2.77 7.83,7.05 l 0,8.11 z M 171,172 l 42.5,0 0,-100 -42.5,0 0,100 z m 28.52,-43.91 c -0.93,1.33 -3.98,4.35 -8.34,4.35 -6.77,-0.01 -16.21,-3.92 -16.21,-20.89 0.01,-13.38 10.7,-17.87 15.09,-17.87 4.74,-0.01 8.26,2.75 9.22,3.79 l 0,-4.21 c 0,-3.11 -3.19,-6.15 -8.53,-6.15 -4.6,0.01 -5.08,2.96 -5.08,4.42 l -9.4,0 c 0,-4.67 3.01,-11.49 13.91,-11.5 9.76,0 12.98,3.73 14.37,5.13 1.17,1.18 2.92,4.42 2.92,7.01 l 0,39.83 -7.94,0 -0.01,-3.91 z M 220.5,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,40.4 9,0 0,-40.4 z m -9,0 z m 9,45.9 -9,0 0,10 9,0 0,-10 z m -9,0 z m 56.03,9.75 -8.23,0 0,-14.54 -4.31,0 0,-6.75 4.31,0 0,-25.44 c 0,-4.85 2.49,-8.66 9.43,-8.65 3.25,0 3.12,-0.02 5.94,0.47 l 0,8.4 c -1.84,-0.32 -2.41,-0.45 -3.31,-0.42 -1.73,0.05 -3.83,0.66 -3.83,3.74 l 0,21.89 6.52,0 0,6.76 -6.52,0 0,14.54 z M 312.5,72 270,72 l 0,100 42.5,0 0,-100 z m 49.5,0 -42.5,0 0,100 42.5,0 0,-100 z m -42.5,0 z m 6.99,47.28 7.71,0 c 0,4.1 2.12,6.25 6.16,6.25 6.44,0.01 6.23,-2.86 6.22,-6.45 -3.98,-1.55 -3.61,-1.51 -9.68,-2.89 -7.71,-1.78 -12.43,-5.08 -12.44,-13.07 0.01,-7.81 5.57,-11.98 11.84,-11.97 6.28,-0.01 7.58,2.02 10.18,3.75 l 0,-3.12 9.84,0 c -2.32,3.74 -1.71,4.47 -1.73,7.28 0.01,2.2 0,23.74 0,23.74 0.01,4.27 -2.21,6.88 -3.66,7.75 -3.62,2.16 -8.09,2.42 -10.57,2.43 -8.81,-0.02 -13.88,-4.45 -13.87,-13.7 z m 20.09,-7.82 0,-5.45 c 0,-2.49 -3.03,-7.31 -8.98,-7.32 -2.9,-0.01 -4.52,2.14 -4.53,4.93 0.01,2.8 2.38,4.95 4.39,5.35 2.09,0.42 6.9,1.65 9.12,2.49 z M 369,72 l 42.5,0 0,100 -42.5,0 0,-100 z m 42.5,0 z m -16.75,19.6 -9,0 0,56.9 9,0 0,-56.9 z" /></g></g><path id="path4448" style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 106.30956,411.81751 0,4.57684 0.9383,-0.0104 c 0,0 2.97311,0.1668 2.98173,-2.40832 0.008,-2.34582 -2.96088,-2.18938 -2.96088,-2.18938 z m 0.88618,0.87575 0,2.80449 0.45873,0 c 0,0 1.68636,0.0835 1.69937,-1.54299 0.0104,-1.3032 -1.60555,-1.28235 -1.60555,-1.28235 z" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 110.35469,411.70282 0,4.62897 2.3979,0 0,-0.86532 -1.40746,0 0,-1.03213 1.35532,0 0,-0.87575 -1.3866,0 0,-0.94874 1.37618,0 0,-0.90703 z" id="path4450" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 116.52666,413.02688 0.96958,0 c 0,0 -0.46915,-1.49086 -2.28321,-1.49086 -1.81406,0 -2.38747,1.59511 -2.38747,2.50214 0,0.90703 0.86533,2.29363 2.523,2.29363 1.65767,0 2.1581,-1.36575 2.1581,-1.36575 l -0.98,0 c 0,0 -0.23979,0.47958 -1.16767,0.47958 -0.92789,0 -1.60555,-0.66724 -1.60555,-1.49086 0,-0.82363 0.63596,-1.44916 1.49086,-1.44916 0.8549,0 1.28236,0.52128 1.28236,0.52128 z" id="path4452" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 117.6839,411.70282 0,4.62897 1.11554,0 0,-3.64895 -0.80277,0 0,-0.98002 z" id="path4454" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 119.64391,416.33179 0,-3.65938 0.86533,0 0.0208,-0.96959 2.47087,0 z" id="path4456" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 120.79073,416.33179 0.90703,-1.27192 1.04255,0 0,1.27192 z" id="path4458" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 122.25032,414.2571 0.50043,-0.70894 0,0.69851 z" id="path4460" inkscape:connector-curvature="0" sodipodi:nodetypes="cccc" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 123.60565,411.70282 0,4.62897 0.35447,0 0,-4.62897 z" id="path4462" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 124.80459,412.56815 0,1.19894 0.4483,0.0104 c 0,0 0.66724,-0.0834 0.66724,-0.61511 0,-0.53171 -0.68809,-0.57341 -0.68809,-0.57341 z" id="path4464" inkscape:connector-curvature="0" /><path style="display:inline;fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 124.84629,414.54901 0,1.78278 2.04342,0 0,-4.62897 -1.23022,0 c 0,0 1.04256,0.23979 1.04256,1.55342 0,1.31363 -1.27192,1.3032 -1.27192,1.3032 z" id="path4466" inkscape:connector-curvature="0" /><path style="fill:#1e97ec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 129.14164,411.70282 0,0.88618 -1.35533,0 0,1.11554 1.34491,0 0,0.7298 -1.37619,0 0,1.12596 1.38661,0 0,0.77149 6.60983,0 c 0,0 4.50387,-0.80276 4.50387,-5.30663 0,-4.50386 -4.98345,-5.24408 -4.98345,-5.24408 l -90.87296,-0.43787 c 0,0 -0.04525,2.62725 -0.04525,4.68109 1.845329,0 90.29268,0.31277 90.29268,0.31277 0,0 0.80277,-0.0417 0.80277,0.71937 0,0.76107 -0.72979,0.64638 -0.72979,0.64638 z" id="path4468" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccccsccccscc" /></g></g></svg> |
cannot compute difference between binary files
cannot compute difference between binary files
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | The PiDP is typically used with a USB hub as its 'PiDP Universal Storage Device'. Image files (disk images, paper tape images, DECtape images) are then stored on a USB stick, and when inserted to the USB hub the first image file can be mounted into the emulated device. The image files in this directory are typical candidates to put on USB sticks. Mounting works as follows: 1. Select the device you want to mount on by setting the Data Field switches Switch Settings File Extension -------------------------------------------------------------------------------- 000 - mount USB paper tape on the high-speed paper tape reader .pt 001 - mount USB paper tape on the paper tape punch .pt 010 - mount DECtape on DT0 (TU55) .dt 011 - mount DECtape on DT1 (TU55) .dt 100 - mount 8" floppy disk on RX0 (RX01/02) .rx 101 - mount 8" floppy disk on RX1 (RX01/02) .rx 110 - mount 10MB removable disk cartridge on RL0 (RL8A) .rl 111 - mount 10MB removable disk cartridge on RL1 (RL8A) .rl 2. Toggle Sing_Step and Sing_Inst switches together 3. The PiDP will scan all inserted USB sticks and mount the first unmounted image file for that device. Scanning requires the image file to have the extension as per the above table. This is equivalent to using the attach command from the simh command line. Notes: - Multiple image files can reside on one USB stick, as long as they do not have the same extension (and your USB stick is large enough). - You can put any other files on the sticks too, the PiDP will just ignore them. - You can, of course, also just use the simh attach command to mount any image files on the SD card, and ignore the "PiDP Universal USB Storage Device" altogether. |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | At main console: ---------------- To run ETOS: R ETOS to start the operating system. Hit return at the option prompt. To login enter LOGIN and then hit return which should then give the login prompt. No prompt will be displayed for entering the login command. At the prompt enter account number such as 0,3 and hit return. Then enter the password at the password prompt. On the distribution ETOS pack the following users exist: At terminal (telnet localhost 4000): ----------- LOGIN;0,4 USER1 <CTRL-M> Users: ------ Account Password 0,4 USER1 0,5 USER2 Shutdown: --------- You can To shutdown enter . ^VS (^V is control-V) !PRIV 4040 !SHUTUP See: ---- http://www.pdp8.net/os/etos/ (introduction) http://highgate.comm.sfu.ca/pdp8/index.html (manuals, search page for ETOS) ftp://ftp.pdp8online.com/images/etos/ (disk images) |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | # Digital License Agreement This document is your Proof of License and the legal agreement governing your use of the OS/8 software. ## 1 DEFINITION SOFTWARE TECHNOLOGY shall mean the sources and binaries to the OS/8, an operating system that runs on PDP-8 computers. DIGITAL’S INTELLECTUAL PROPERTY RIGHTS shall mean DIGITAL’s patent, copyright and trade secret rights in its SOFTWARE TECHNOLOGY. ## 2 LICENSE GRANT Digital grants to Customer a worldwide, non-exclusive, royalty-free license under DIGITAL’s INTELLECTUAL PROPERTY RIGHTS to reproduce, modify, use and distribute the SOFTWARE TECHNOLOGY solely for non-commercial uses. ## 3 TECHNOLOGY TRANSFER AND ACCEPTANCE 3.1 CUSTOMER acknowledges that it accepts the SOFTWARE TECHNOLOGY "AS IS". 3.2 DIGITAL is under no obligation to supply error corrections or updates to the SOFTWARE TECHNOLOGY as they become available, or to provide training, support or consulting for the SOFTWARE TECHNOLOGY. ## 4 WARRANTY DISCLAIMER/LIMITATION OF LIABILITY DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO ANY SOFTWARE TECHNOLOGY LICENSED TO CUSTOMER HEREUNDER, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE, INTELLECTUAL PROPERTY INFRINGEMENT OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF ANY SOFTWARE TECHNOLOGY LICENSE HEREUNDER. ## 5 INDEMNITY CUSTOMER will hold DIGITAL harmless against all liabilities, demands, damages, expenses, or losses arising out of use by CUSTOMER of SOFTWARE TECHNOLOGY or information furnished under this Agreement. ## 6 TERM AND TERMINATION 6.1 This Agreement shall be effective until otherwise terminated. Either party may terminate this Agreement at any time upon 30 days written notice. 6.2 If CUSTOMER shall fail to perform or observe any of the terms and conditions to be performed or observed by it under this Agreement, DIGITAL may in its sole discretion thereafter elect to terminate this Agreement, and this Agreement and all the obligations owed and rights granted herein to CUSTOMER shall immediately terminate. 6.3 The parties agree that the termination of this Agreement shall not release either party from any other liability which shall have accrued to the other party at the time such termination becomes effective, nor affect in any manner the survival of any right, duty or obligation of either party. 6.4 In the event of any termination of this Agreement for any reason, CUSTOMER shall delete all original and all whole or partial copies and derivatives of the SOFTWARE TECHNOLOGY provided to CUSTOMER under this Agreement. CUSTOMER further shall cease to use and distribute the SOFTWARE TECHNOLOGY in all forms immediately upon the date of termination. ## 7 GENERAL TERMS 7.1 This Agreement shall be governed by the laws of the Commonwealth of Massachusetts. 7.2 This Agreement imposes personal obligations on CUSTOMER. CUSTOMER shall not assign any rights under this Agreement not specifically transferable by its terms without the written consent of DIGITAL. 7.3 The SOFTWARE TECHNOLOGY obtained under this Agreement may be subject to US and other government export control regulations. CUSTOMER assures that it will comply with these regulations whenever it exports or re-exports a controlled product or technical data obtained from DIGITAL or any product produced directly from the SOFTWARE TECHNOLOGY. 7.4 The waiver of a breach hereunder may be effected only by a writing signed by the waiving party and shall not constitute a waiver of any other breach. 7.5 CUSTOMER acknowledges that he has read this Agreement, understands it and agrees to be bound by its term and further agrees that it is the complete and exclusive statement of the Agreement between the parties which supersedes all communications and understanding between the parties relating to the subject matter of this Agreement. |
cannot compute difference between binary files
cannot compute difference between binary files
cannot compute difference between binary files
cannot compute difference between binary files
cannot compute difference between binary files
> > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # palbart License The following was extracted from the top of [`palbart.c`][1] in this directory: --------- This is free software. There is no fee for using it. You may make any changes that you wish and also give it away. If you can make commercial product out of it, fine, but do not put any limits on the purchaser's right to do the same. If you improve it or fix any bugs, it would be nice if you told me and offered me a copy of the new version. --------- [1]: https://tangentsoft.com/pidp8i/doc/trunk/palbart/palbart.c |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | .\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH PALBART 1 "January 16, 2000" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp <n> insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME palbart \- BART enhanced PDP8 crossassembler .SH SYNOPSIS .B palbart .RI [options] inputfile .br .SH DESCRIPTION This manual page documents briefly the .B palbart command. It is a cross-assembler to for PDP/8 assembly language programs. It will produce an output file in bin format, rim format, and using the appropriate pseudo-ops, a combination of rim and bin formats. A listing file is always produced and with an optional symbol table and/or a symbol cross-reference (concordance). The permanent symbol table can be output in a form that may be read back in so a customized permanent symbol table can be produced. Any detected errors are output to a separate file giving the filename in which they were detected along with the line number, column number and error message as well as marking the error in the listing file. .PP The following file name extensions are used: .PP .pal source code (input) .PP .lst assembly listing (output) .PP .bin assembly output in DEC's bin format (output) .PP .rim assembly output in DEC's rim format (output) .PP .err assembly errors detected (if any) (output) .PP .prm permanent symbol table in form suitable for reading after the EXPUNGE pseudo-op. .PP .SH OPTIONS A summary of options is included below. .TP .B \-d Show symbol table at end of assembly .TP .B \-h Display help. .TP .B \-l Allow generation of literals (default is no literal generation) Show version of program. .TP .B \-p Generate a file with the permanent symbols in it. (To get the current symbol table, assemble a file than has only a $ in it.) .TP .B \-r Produce output in rim format (default is bin format) .TP .B \-v Display version information. .TP .B \-x Generate a cross-reference (concordance) of user symbols. .SH DIAGNOSTICS Assembler error diagnostics are output to an error file and inserted in the listing file. Each line in the error file has the form .PP <filename>(<line>:<col>) : error: <message> at Loc = <loc> .PP An example error message is: .br bintst.pal(17:9) : error: undefined symbol "UNDEF" at Loc = 07616 .PP The error diagnostics put in the listing start with a two character error code (if appropriate) and a short message. A carat '^' is placed under the item in error if appropriate. An example error message is: .PP 17 07616 3000 DCA UNDEF .br UD undefined ^ .br 18 07617 1777 TAD I DUMMY .PP When an indirect is generated, an at character '@' is placed after the the instruction value in the listing as an indicator as follows: .PP 14 03716 1777@ TAD OFFPAG .PP Undefined symbols are marked in the symbol table listing by prepending a '?' to the symbol. Redefined symbols are marked in the symbol table listing by prepending a '#' to the symbol. Examples are: .PP #REDEF 04567 .br SWITCH 07612 .br ?UNDEF 00000 .PP Refer to the code for the diagnostic messages generated. .SH BUGS Only a minimal effort has been made to keep the listing format anything like the PAL-8 listing format. The operation of the conditional assembly pseudo-ops may not function exactly as the DEC versions. I did not have any examples of these so the implementation is my interpretation of how they should work. .PP The RIMPUNch and BINPUNch pseudo-ops do not change the binary output file type that was specified on startup. This was intentional and and allows rim formatted data to be output prior to the actual binary formatted data. On UN*X style systems, the same effect can be achieved ing the "cat" command, but on DOS/Windows systems, doing this was a major chore. .PP The floating point input does not generate values exactly as the DEC compiler does. I worked out several examples by hand and believe that this implementation is slightly more accurate. If I am mistaken, let me know and, if possible, a better method of generating the values. .br .SH HISTORICAL NOTE This assembler was written to support the fleet of PDP-8 systems used by the Bay Area Rapid Transit System. As of early 1997, this includes about 40 PDP-8/E systems driving the train destination signs in passenger stations. .SH REFERENCES This assembler is based on the pal assember by: .br Douglas Jones <jones@cs.uiowa.edu> and .br Rich Coon <coon@convexw.convex.com> .SH DISCLAIMER See the symbol table for the set of pseudo-ops supported. .PP See the code for pseudo-ops that are not standard for PDP/8 assembly. .PP Refer to DEC's "Programming Languages (for the PDP/8)" for complete documentation of pseudo-ops. .PP Refer to DEC's "Introduction to Programming (for the PDP/8)" or a lower level introduction to the assembly language. .SH WARRANTY If you don't like it the way it works or if it doesn't work, that's tough. You're welcome to fix it yourself. That's what you get for using free software. .SH COPYRIGHT NOTICE This is free software. There is no fee for using it. You may make any changes that you wish and also give it away. If you can make a commercial product out of it, fine, but do not put any limits on the purchaser's right to do the same. If you improve it or fix any bugs, it would be nice if you told me and offered me a copy of the new version. Gary Messenbrink <gam@rahul.net> .SH VERSIONS Version Date by Comments .br v1.0 12Apr96 GAM Original .br v1.1 18Nov96 GAM Permanent symbol table initialization error. .br v1.2 20Nov96 GAM Added BINPUNch and RIMPUNch pseudo-operators. .br v1.3 24Nov96 GAM Added DUBL pseudo-op (24 bit integer constants). .br v1.4 29Nov96 GAM Fixed bug in checksum generation. .br v2.1 08Dec96 GAM Added concordance processing (cross reference). .br v2.2 10Dec96 GAM Added FLTG psuedo-op (floating point constants). .br v2.3 2Feb97 GAM Fixed paging problem in cross reference output. .br v2.4 11Apr97 GAM Fixed problem with some labels being put in cross reference multiple times. .SH AUTHOR This manual page was written by Vince Mulhollon <vlm@execpc.com>, for the Debian GNU/Linux system (but may be used by others). |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 | /******************************************************************************/ /* */ /* Program: PAL (BART version) */ /* File: pal.c */ /* Author: Gary A. Messenbrink */ /* gam@rahul.net */ /* */ /* Purpose: A 2 pass PDP-8 pal-like assembler. */ /* */ /* PAL(1) */ /* */ /* NAME */ /* pal - a PDP/8 pal-like assembler. */ /* */ /* SYNOPSIS: */ /* pal [ -$ -d -h -e -l -p -r -t -v -x ] inputfile */ /* */ /* DESCRIPTION */ /* This is a cross-assembler to for PDP/8 assembly language programs. */ /* It will produce an output file in bin format, rim format, and using the */ /* appropriate pseudo-ops, a combination of rim and bin formats. */ /* A listing file is always produced and with an optional symbol table */ /* and/or a symbol cross-reference (concordance). The permanent symbol */ /* table can be output in a form that may be read back in so a customized */ /* permanent symbol table can be produced. Any detected errors are output */ /* to a separate file giving the filename in which they were detected */ /* along with the line number, column number and error message as well as */ /* marking the error in the listing file. */ /* The following file name extensions are used: */ /* .pal source code (input) */ /* .lst assembly listing (output) */ /* .bin assembly output in DEC's bin format (output) */ /* .rim assembly output in DEC's rim format (output) */ /* .err assembly errors detected (if any) (output) */ /* .prm permanent symbol table in form suitable for reading after */ /* the EXPUNGE pseudo-op. */ /* */ /* OPTIONS */ /* -$ Allow files to not end with $ */ /* -d Dump the symbol table at end of assembly */ /* -h Show help */ /* -e Don't allow generation of links */ /* -l Allow generation of links (default is link generation) */ /* -n No redefinition of permanent symbols with labels */ /* -p Generate a file with the permanent symbols in it. */ /* (To get the current symbol table, assemble a file than has only */ /* a $ in it.) */ /* -r Produce output in rim format (default is bin format) */ /* -tN Set tab stops to N spaces (default is 8) */ /* -v Display program version. */ /* -x Generate a cross-reference (concordance) of user symbols. */ /* */ /* DIAGNOSTICS */ /* Assembler error diagnostics are output to an error file and inserted */ /* in the listing file. Each line in the error file has the form */ /* */ /* <filename>(<line>:<col>) : error: <message> at Loc = <loc> */ /* */ /* An example error message is: */ /* */ /* bintst.pal(17:9) : error: undefined symbol "UNDEF" at Loc = 07616 */ /* */ /* The error diagnostics put in the listing start with a two character */ /* error code (if appropriate) and a short message. A carat '^' is */ /* placed under the item in error if appropriate. */ /* An example error message is: */ /* */ /* 17 07616 3000 DCA UNDEF */ /* UD undefined ^ */ /* 18 07617 1777 TAD I DUMMY */ /* */ /* When an indirect is generated, an at character '@' is placed after the */ /* the instruction value in the listing as an indicator as follows: */ /* */ /* 14 03716 1777@ TAD OFFPAG */ /* */ /* Undefined symbols are marked in the symbol table listing by prepending */ /* a '?' to the symbol. Redefined symbols are marked in the symbol table */ /* listing by prepending a '#' to the symbol. Examples are: */ /* */ /* #REDEF 04567 */ /* SWITCH 07612 */ /* ?UNDEF 00000 */ /* */ /* Refer to the code for the diagnostic messages generated. */ /* */ /* BUGS */ /* This program will accept source that real PAL will not. To ensure */ /* valid source assemble on real or simulated PDP-8. */ /* Different PAL versions have different permanent symbols defined. This */ /* program define more than and PAL version. By default redefining them */ /* as a label is not an error. It is for normal PAL. The -n flag will */ /* make redefining an error. */ /* */ /* Only a minimal effort has been made to keep the listing format */ /* anything like the PAL-8 listing format. */ /* The operation of the conditional assembly pseudo-ops may not function */ /* exactly as the DEC versions. I did not have any examples of these so */ /* the implementation is my interpretation of how they should work. */ /* */ /* The RIMPUNch and BINPUNch pseudo-ops do not change the binary output */ /* file type that was specified on startup. This was intentional and */ /* and allows rim formatted data to be output prior to the actual binary */ /* formatted data. On UN*X style systems, the same effect can be achieved */ /* by using the "cat" command, but on DOS/Windows systems, doing this was */ /* a major chore. */ /* */ /* The floating point input does not generate values exactly as the DEC */ /* compiler does. I worked out several examples by hand and believe that */ /* this implementation is slightly more accurate. If I am mistaken, */ /* let me know and, if possible, a better method of generating the values. */ /* */ /* CDF .-. */ /* Generates 2201 when assembled at 5000. This looks like a bug in OS/8 */ /* PAL */ /* */ /* BUILD and INSTALLATION */ /* The current version has only been built under Linux. */ /* Earlier versions have been built and successfully executed on: */ /* a. Linux (80486 CPU)using gcc */ /* b. RS/6000 (AIX 3.2.5) */ /* c. Borland C++ version 3.1 (large memory model) */ /* d. Borland C++ version 4.52 (large memory model) */ /* with no modifications to the source code. */ /* */ /* On UNIX type systems, store the the program as the pal command */ /* and on PC type systems, store it as pal.exe */ /* */ /* HISTORICAL NOTE: */ /* This assembler was written to support the fleet of PDP-8 systems */ /* used by the Bay Area Rapid Transit System. As of early 1997, */ /* this includes about 40 PDP-8/E systems driving the train destination */ /* signs in passenger stations. */ /* */ /* REFERENCES: */ /* This assembler is based on the pal assembler by: */ /* Douglas Jones <jones@cs.uiowa.edu> and */ /* Rich Coon <coon@convexw.convex.com> */ /* */ /* DISCLAIMER: */ /* See the symbol table for the set of pseudo-ops supported. */ /* See the code for pseudo-ops that are not standard for PDP/8 assembly. */ /* Refer to DEC's "Programming Languages (for the PDP/8)" for complete */ /* documentation of pseudo-ops. */ /* Refer to DEC's "Introduction to Programming (for the PDP/8)" or a */ /* lower level introduction to the assembly language. */ /* */ /* WARRANTY: */ /* If you don't like it the way it works or if it doesn't work, that's */ /* tough. You're welcome to fix it yourself. That's what you get for */ /* using free software. */ /* */ /* COPYRIGHT NOTICE: */ /* This is free software. There is no fee for using it. You may make */ /* any changes that you wish and also give it away. If you can make */ /* a commercial product out of it, fine, but do not put any limits on */ /* the purchaser's right to do the same. If you improve it or fix any */ /* bugs, it would be nice if you told me and offered me a copy of the */ /* new version. */ /* */ /* */ /* Amendments Record: */ /* Version Date by Comments */ /* ------- ------- --- --------------------------------------------------- */ /* v1.0 12Apr96 GAM Original */ /* v1.1 18Nov96 GAM Permanent symbol table initialization error. */ /* v1.2 20Nov96 GAM Added BINPUNch and RIMPUNch pseudo-operators. */ /* v1.3 24Nov96 GAM Added DUBL pseudo-op (24 bit integer constants). */ /* v1.4 29Nov96 GAM Fixed bug in checksum generation. */ /* v2.1 08Dec96 GAM Added concordance processing (cross reference). */ /* v2.2 10Dec96 GAM Added FLTG psuedo-op (floating point constants). */ /* v2.3 2Feb97 GAM Fixed paging problem in cross reference output. */ /* DJG: I started with the 2.5 RK version but found when looking on the net */ /* later that multiple diverging version existed. I have tried to combine */ /* the fixed into one version. I took the version info below from the versions*/ /* I pulled from. */ /* http://dustyoldcomputers.com/pdp-common/reference/host/index.html */ /* http://www.dunnington.u-net.com/public/PDP-8/palbart.c */ /* http://sourcecodebrowser.com/palbart/2.4/palbart-2_84_8c_source.html */ /* http://packages.qa.debian.org/p/palbart.html */ /* v2.4 11Apr97 GAM Fixed problem with some labels being put in cross */ /* reference multiple times. */ /* Started with RK version, Attempted to merge */ /* GAM V2.4 and PNT change DJG */ /* v2.4 29Oct07 RK Added 4 character tabstop; IOTs for TA8/E. */ /* v2.4 19Jan03 PNT Added ASCII pseudo-op, like TEXT but not packed. */ /* v2.5 03Nov07 RK Fixed buffer overflow problem in readLine and */ /* increased symbol table size */ /* v2.6 14Jul03 PNT Added missing TTY symbols, and "1st TTY" symbols. */ /* v2.7 14Jun13 DJG David Gesswein djg@pdp8online.com */ /* Merged other changes found online giving duplicate */ /* Versions in the history */ /* Didn't copy over deleting -l literal flag */ /* All fixes to make it match OS/8 PAL8 better */ /* Fixed handling of IFDEF type conditionals */ /* Fixed excessive redefined symbol errors */ /* PAL8 uses 12 bit symbols and this program label */ /* symbols are 15 bit. */ /* Added FILENAME and DEVNAME psuedo ops */ /* Added OPR and KCF instructions. Fixed RMF */ /* Allowed space after = */ /* Prevented I and D from being deleted by EXPUNGE */ /* Allowed permanent symbols to be redefined with error*/ /* PAL8 updates without message. Error is just warning*/ /* Fixed certain cases of memory reference generation */ /* Allowed unary + */ /* Fixed " character literal at end of line */ /* Fixed errors in reloc handling */ /* Fixed [CDF CIF type expressions */ /* Made title default to first line */ /* Fixed checksum when nopunch used */ /* Fixed FIXTAB */ /* Probably added more subtle bugs */ /* v2.8 15Jun13 DJG Merged versions found on net. See above */ /* Added * to RELOC addresses in listing */ /* Changed default to literal/links on. Added -e to */ /* turn off */ /* Fixed PAGE when RELOC used */ /* Changed SPF to TFL and SPI to TSK */ /* Make error when changing permanent symbol to label */ /* if -e flag is used */ /* Allow space oring in IFZERO etc */ /* Fixed handling of page zero overflow */ /* v2.9 23Jun13 DJG Fixed properly all pages literal handling */ /* changing page doesn't cause loss of last literal */ /* location used. */ /* Fixed bin generation if no origin set */ /* v2.9a 01Jul13 DJG Fixed Comment. Binaries not updated */ /* v2.10 08Feb14 DJG Changed trailer to 8 bytes since pip didn't like */ /* trailer of one 0x80 */ /* v2.11 19Apr15 DPI Fixed incorrect link generation with impled 0200 */ /* starting address. Patch from Doug Ingrams */ /* v2.12 28Apr15 DJG Fixed incorrect handling of reloc, expressions with */ /* undefined symbols. Fixed conditional assembly with */ /* undefined symbols. Added new flag to allow file to */ /* not end with $ */ /* v2.13 02May15 DPI Fixed bug in readLine when removing \r from a blank */ /* line. Changed -s to -$ in -h display. Corrected */ /* version comment. */ /* v2.13 03May15 DJG Moved TITLE, BANK to new additional option. */ /* Change release variable below when you update. Send changes back to */ /* David Gesswein, djg@pdp8online.com. */ /******************************************************************************/ #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> char *release = "pal-2.13, 03 May 2015"; /* Set to 1 and use -e flag to make ( and [ literals errors */ #define LITERAL_ERROR 0 #define LINELEN 132 #define LIST_LINES_PER_PAGE 55 /* Includes 5 line page header. */ #define NAMELEN 128 #define SYMBOL_COLUMNS 5 #define SYMLEN 7 #define SYMBOL_TABLE_SIZE 4096 #define TITLELEN 63 #define XREF_COLUMNS 8 #define ADDRESS_FIELD 00177 #define FIELD_FIELD 070000 #define INDIRECT_BIT 00400 #define LAST_PAGE_LOC 00177 #define OP_CODE 07000 #define PAGE_BIT 00200 #ifdef PAGE_SIZE #undef PAGE_SIZE #endif #define PAGE_SIZE 00200 #define PAGE_FIELD 07600 #define PAGE_ZERO_END 00200 /* Macro to get the number of elements in an array. */ #define DIM(a) (sizeof(a)/sizeof(a[0])) /* Macro to get the address plus one of the end of an array. */ #define BEYOND(a) ((a) + DIM(A)) #define is_blank(c) ((c==' ') || (c=='\t') || (c=='\f') || (c=='>')) #define isend(c) ((c=='\0')|| (c=='\n')) #define isdone(c) ((c=='/') || (isend(c)) || (c==';')) /* Macros for testing symbol attributes. Each macro evaluates to non-zero */ /* (true) if the stated condition is met. */ /* Use these to test attributes. The proper bits are extracted and then */ /* tested. */ #define M_CONDITIONAL(s) ((s & CONDITION) == CONDITION) #define M_DEFINED(s) ((s & DEFINED) == DEFINED) #define M_DUPLICATE(s) ((s & DUPLICATE) == DUPLICATE) #define M_FIXED(s) ((s & FIXED) == FIXED) #define M_LABEL(s) ((s & LABEL) == LABEL) #define M_MRI(s) ((s & MRI) == MRI) #define M_MRIFIX(s) ((s & MRIFIX) == MRIFIX) #define M_PSEUDO(s) ((s & PSEUDO) == PSEUDO) #define M_REDEFINED(s) ((s & REDEFINED) == REDEFINED) #define M_UNDEFINED(s) (!M_DEFINED(s)) #define M_PERM_REDEFINED(s) ((s & PERM_REDEFINED) == PERM_REDEFINED) /* This macro is used to test symbols by the conditional assembly pseudo-ops. */ #define M_DEF(s) (M_DEFINED(s)) #define M_COND(s) (M_CONDITIONAL(s)) #define M_DEFINED_CONDITIONALLY(t) (M_DEF(t) && ((pass==1) ||!M_COND(t))) typedef unsigned char BOOL; typedef unsigned char BYTE; typedef short int WORD16; typedef long int WORD32; #ifndef FALSE #define FALSE 0 #define TRUE (!FALSE) #endif /* Line listing styles. Used to control listing of lines. */ enum linestyle_t { LINE, LINE_VAL, LINE_LOC_VAL, LOC_VAL }; typedef enum linestyle_t LINESTYLE_T; /* Symbol Types. */ /* Note that the names that have FIX as the suffix contain the FIXED bit */ /* included in the value. */ /* */ /* The CONDITION bit is used when processing the conditional assembly PSEUDO- */ /* OPs (e.g., IFDEF). During pass 1 of the assembly, the symbol is either */ /* defined or undefined. The condition bit is set when the symbol is defined */ /* during pass 1 and reset on pass 2 at the location the symbol was defined */ /* during pass 1. When processing conditionals during pass 2, if the symbol */ /* is defined and the condition bit is set, the symbol is treated as if it */ /* were undefined. This gives consistent behavior of the conditional */ /* pseudo-ops during both pass 1 and pass 2. */ enum symtyp { UNDEFINED = 0000, DEFINED = 0001, FIXED = 0002, MRI = 0004 | DEFINED, LABEL = 0010 | DEFINED, REDEFINED = 0020 | DEFINED, DUPLICATE = 0040 | DEFINED, PSEUDO = 0100 | FIXED | DEFINED, CONDITION = 0200 | DEFINED, PERM_REDEFINED = 0400, MRIFIX = MRI | FIXED | DEFINED, DEFFIX = DEFINED | FIXED }; typedef enum symtyp SYMTYP; enum pseudo_t { BANK, BINPUNCH, DECIMAL, DUBL, EJECT, ENPUNCH, EXPUNGE, FIELD, FIXMRI, FIXTAB, FLTG, IFDEF, IFNDEF, IFNZERO, IFZERO, NOPUNCH, OCTAL, PAGE, PAUSE, RELOC, RIMPUNCH, SEGMNT, TEXT, TITLE, XLIST, ZBLOCK, FILENAME, DEVICE, ASCII }; typedef enum pseudo_t PSEUDO_T; struct sym_t { SYMTYP type; char name[SYMLEN]; WORD16 val; int xref_index; int xref_count; }; typedef struct sym_t SYM_T; struct lpool_t { WORD16 loc; WORD16 last_punched; WORD16 pool[PAGE_SIZE]; }; typedef struct lpool_t LPOOL_T; struct emsg_t { char *list; char *file; }; typedef struct emsg_t EMSG_T; struct errsave_t { char *mesg; int col; }; typedef struct errsave_t ERRSAVE_T; struct fltg_ { WORD16 exponent; WORD32 mantissa; }; typedef struct fltg_ FLTG_T; /*----------------------------------------------------------------------------*/ /* Function Prototypes */ int binarySearch( char *name, int start, int symbol_count ); int compareSymbols( const void *a, const void *b ); void conditionFalse( void ); void conditionTrue( void ); SYM_T *defineLexeme( int start, int term, WORD16 val, SYMTYP type ); SYM_T *defineSymbol( char *name, WORD16 val, SYMTYP type, WORD16 start); void endOfBinary( void ); void errorLexeme( EMSG_T *mesg, int col ); void errorMessage( EMSG_T *mesg, int col ); void errorSymbol( EMSG_T *mesg, char *name, int col ); SYM_T *eval( void ); WORD32 evalDubl( WORD32 initial_value ); FLTG_T *evalFltg( void ); SYM_T *evalSymbol( void ); void getArgs( int argc, char *argv[] ); WORD32 getDublExpr( void ); WORD32 getDublExprs( void ); FLTG_T *getFltgExpr( void ); FLTG_T *getFltgExprs( void ); SYM_T *getExpr( void ); WORD16 getExprs( void ); WORD16 incrementClc( void ); void inputDubl( void ); void inputFltg( void ); WORD16 insertLiteral( LPOOL_T *pool, WORD16 value, int fieldpage_index ); char *lexemeToName( char *name, int from, int term ); void listLine( void ); SYM_T *lookup( char *name ); void moveToEndOfLine( void ); void nextLexBlank( void ); void nextLexeme( void ); void normalizeFltg( FLTG_T *fltg ); void onePass( void ); void printCrossReference( void ); void printErrorMessages( void ); void printLine(char *line, WORD16 loc, WORD16 val, LINESTYLE_T linestyle); void printPageBreak( void ); void printPermanentSymbolTable( void ); void printSymbolTable( void ); BOOL pseudoOperators( PSEUDO_T val ); void punchChecksum( void ); void punchLocObject( WORD16 loc, WORD16 val ); void punchLiteralPool( LPOOL_T *p, BOOL punch_page0 ); void punchOutObject( WORD16 loc, WORD16 val ); void punchLeader( int count ); void punchObject( WORD16 val ); void punchOrigin( WORD16 loc ); void readLine( void ); void saveError( char *mesg, int cc ); BOOL testForLiteralCollision( WORD16 loc ); void topOfForm( char *title, char *sub_title ); /*----------------------------------------------------------------------------*/ /* Table of pseudo-ops (directives) which are used to setup the symbol */ /* table on startup and when the EXPUNGE pseudo-op is executed. */ SYM_T pseudo[] = { { PSEUDO, "ASCII", ASCII }, /* Put 8-bit ASCII into memory (see TEXT) */ { PSEUDO, "BINPUN", BINPUNCH }, /* Output in Binary Loader format. */ { PSEUDO, "DECIMA", DECIMAL }, /* Read literal constants in base 10. */ { PSEUDO, "DEVICE", DEVICE }, /* Pack 6 bit device name into memory */ { PSEUDO, "DUBL", DUBL }, /* Ignored (unsupported). */ { PSEUDO, "EJECT", EJECT }, /* Eject a page in the listing. */ { PSEUDO, "ENPUNC", ENPUNCH }, /* Turn on object code generation. */ { PSEUDO, "EXPUNG", EXPUNGE }, /* Remove all symbols from symbol table. */ { PSEUDO, "FIELD", FIELD }, /* Set origin to memory field. */ { PSEUDO, "FILENA", FILENAME }, /* Pack 6 bit filename into memory. */ { PSEUDO, "FIXMRI", FIXMRI }, /* Like =, but creates mem ref instruction*/ { PSEUDO, "FIXTAB", FIXTAB }, /* Mark current symbols as permanent. */ { PSEUDO, "FLTG", FLTG }, /* Ignored (unsupported). */ { PSEUDO, "IFDEF", IFDEF }, /* Assemble if symbol is defined. */ { PSEUDO, "IFNDEF", IFNDEF }, /* Assemble if symbol is not defined. */ { PSEUDO, "IFNZER", IFNZERO }, /* Assemble if symbol value is not 0. */ { PSEUDO, "IFNZRO", IFNZERO }, /* Assemble if symbol value is not 0. */ { PSEUDO, "IFZERO", IFZERO }, /* Assemble if symbol value is 0. */ { PSEUDO, "NOPUNC", NOPUNCH }, /* Turn off object code generation. */ { PSEUDO, "OCTAL", OCTAL }, /* Read literal constants in base 8. */ { PSEUDO, "PAGE", PAGE }, /* Set orign to page +1 or page n (0..37).*/ { PSEUDO, "PAUSE", PAUSE }, /* Ignored */ { PSEUDO, "RELOC", RELOC }, /* Assemble to run at a different address.*/ { PSEUDO, "RIMPUN", RIMPUNCH }, /* Output in Read In Mode format. */ { PSEUDO, "SEGMNT", SEGMNT }, /* Like page, but with page size=1K words.*/ { PSEUDO, "TEXT", TEXT }, /* Pack 6 bit trimmed ASCII into memory. */ { PSEUDO, "XLIST", XLIST }, /* Toggle listing generation. */ { PSEUDO, "ZBLOCK", ZBLOCK }, /* Zero a block of memory. */ { PSEUDO, "TITLE", TITLE }, /* Use the text string as a listing title.*/ { PSEUDO, "BANK", BANK } /* Like field, select some 32K out of 128K*/ }; /* Number o extended pseudo operators to ignore unless command option specified * to enable */ #define NUMBER_ADDITIONAL_PSEUDO 2 /* Symbol Table */ /* The table is put in lexical order on startup, so symbols can be */ /* inserted as desired into the initial table. */ /* really_permanent_symbols aren't removed by EXPUNGE */ SYM_T really_permanent_symbols[] = { { MRIFIX, "I", 00400 }, /* INDIRECT ADDRESSING */ { MRIFIX, "Z", 00000 } /* PAGE ZERO ADDRESS */ }; SYM_T permanent_symbols[] = { /* Memory Reference Instructions */ { MRIFIX, "AND", 00000 }, /* LOGICAL AND */ { MRIFIX, "TAD", 01000 }, /* TWO'S COMPLEMENT ADD */ { MRIFIX, "ISZ", 02000 }, /* INCREMENT AND SKIP IF ZERO */ { MRIFIX, "DCA", 03000 }, /* DEPOSIT AND CLEAR ACC */ { MRIFIX, "JMP", 05000 }, /* JUMP */ { MRIFIX, "JMS", 04000 }, /* JUMP TO SUBROUTINE */ /* Floating Point Interpreter Instructions */ { MRIFIX, "FEXT", 00000 }, /* FLOATING EXIT */ { MRIFIX, "FADD", 01000 }, /* FLOATING ADD */ { MRIFIX, "FSUB", 02000 }, /* FLOATING SUBTRACT */ { MRIFIX, "FMPY", 03000 }, /* FLOATING MULTIPLY */ { MRIFIX, "FDIV", 04000 }, /* FLOATING DIVIDE */ { MRIFIX, "FGET", 05000 }, /* FLOATING GET */ { MRIFIX, "FPUT", 06000 }, /* FLOATING PUT */ { FIXED, "FNOR", 07000 }, /* FLOATING NORMALIZE */ { FIXED, "FEXT", 00000 }, /* EXIT FROM FLOATING POINT INTERPRETER */ { FIXED, "SQUARE", 00001 }, /* SQUARE C(FAC) */ { FIXED, "SQROOT", 00002 }, /* TAKE SQUARE ROOT OF C(FAC) */ /* Group 1 Operate Microinstrcutions */ { FIXED, "OPR", 07000 }, /* NO OPERATION */ { FIXED, "NOP", 07000 }, /* NO OPERATION */ { FIXED, "IAC", 07001 }, /* INCREMENT AC */ { FIXED, "RAL", 07004 }, /* ROTATE AC AND LINK LEFT ONE */ { FIXED, "RTL", 07006 }, /* ROTATE AC AND LINK LEFT TWO */ { FIXED, "RAR", 07010 }, /* ROTATE AC AND LINK RIGHT ONE */ { FIXED, "RTR", 07012 }, /* ROTATE AC AND LINK RIGHT TWO */ { FIXED, "CML", 07020 }, /* COMPLEMENT LINK */ { FIXED, "CMA", 07040 }, /* COMPLEMEMNT AC */ { FIXED, "CLL", 07100 }, /* CLEAR LINK */ { FIXED, "CLA", 07200 }, /* CLEAR AC */ /* Group 2 Operate Microinstructions */ { FIXED, "BSW", 07002 }, /* Swap bytes in AC (PDP/8e) */ { FIXED, "HLT", 07402 }, /* HALT THE COMPUTER */ { FIXED, "OSR", 07404 }, /* INCLUSIVE OR SR WITH AC */ { FIXED, "SKP", 07410 }, /* SKIP UNCONDITIONALLY */ { FIXED, "SNL", 07420 }, /* SKIP ON NON-ZERO LINK */ { FIXED, "SZL", 07430 }, /* SKIP ON ZERO LINK */ { FIXED, "SZA", 07440 }, /* SKIP ON ZERO AC */ { FIXED, "SNA", 07450 }, /* SKIP ON NON=ZERO AC */ { FIXED, "SMA", 07500 }, /* SKIP MINUS AC */ { FIXED, "SPA", 07510 }, /* SKIP ON POSITIVE AC (ZERO IS POSITIVE) */ /* Combined Operate Microinstructions */ { FIXED, "CIA", 07041 }, /* COMPLEMENT AND INCREMENT AC */ { FIXED, "STL", 07120 }, /* SET LINK TO 1 */ { FIXED, "GLK", 07204 }, /* GET LINK (PUT LINK IN AC BIT 11) */ { FIXED, "STA", 07240 }, /* SET AC TO -1 */ { FIXED, "LAS", 07604 }, /* LOAD ACC WITH SR */ /* MQ Instructions (PDP/8e) */ { FIXED, "MQL", 07421 }, /* Load MQ from AC, then clear AC. */ { FIXED, "MQA", 07501 }, /* Inclusive OR MQ with AC */ { FIXED, "SWP", 07521 }, /* Swap AC and MQ */ { FIXED, "ACL", 07701 }, /* Load MQ into AC */ /* Program Interrupt */ { FIXED, "IOT", 06000 }, { FIXED, "ION", 06001 }, /* TURN INTERRUPT PROCESSOR ON */ { FIXED, "IOF", 06002 }, /* TURN INTERRUPT PROCESSOR OFF */ /* Program Interrupt, PDP-8/e */ { FIXED, "SKON", 06000 }, /* Skip if interrupt on and turn int off. */ { FIXED, "SRQ", 06003 }, /* Skip on interrupt request. */ { FIXED, "GTF", 06004 }, /* Get interrupt flags. */ { FIXED, "RTF", 06005 }, /* Restore interrupt flags. */ { FIXED, "SGT", 06006 }, /* Skip on greater than flag. */ { FIXED, "CAF", 06007 }, /* Clear all flags. */ /* Keyboard/Reader */ { FIXED, "KCF", 06030 }, /* CLEAR KEYBOAR FLAG */ { FIXED, "KSF", 06031 }, /* SKIP ON KEYBOARD FLAG */ { FIXED, "KCC", 06032 }, /* CLEAR KEYBOARD FLAG & READ CHAR */ { FIXED, "KRS", 06034 }, /* READ KEYBOARD BUFFER (STATIC) */ { FIXED, "KIE", 06035 }, /* AC11 TO KEYBD/RDR INT ENABLE F/F */ { FIXED, "KRB", 06036 }, /* READ KEYBOARD BUFFER & CLEAR FLAG */ /* Teleprinter/Punch */ { FIXED, "TFL", 06040 }, /* SET TELEPRINTER/PUNCH FLAG */ { FIXED, "TSF", 06041 }, /* SKIP ON TELEPRINTER FLAG */ { FIXED, "TCF", 06042 }, /* CLEAR TELEPRINTER FLAG */ { FIXED, "TPC", 06044 }, /* LOAD TELEPRINTER & PRINT */ { FIXED, "TSK", 06045 }, /* SKIP IF TELETYPE INTERRUPT */ { FIXED, "TLS", 06046 }, /* LOAD TELPRINTER & CLEAR FLAG */ /* High Speed Paper Tape Reader */ { FIXED, "RSF", 06011 }, /* SKIP ON READER FLAG */ { FIXED, "RRB", 06012 }, /* READ READER BUFFER AND CLEAR FLAG */ { FIXED, "RFC", 06014 }, /* READER FETCH CHARACTER */ /* PC8-E High Speed Paper Tape Reader & Punch */ { FIXED, "RPE", 06010 }, /* Set interrupt enable for reader/punch */ { FIXED, "PCE", 06020 }, /* Clear interrupt enable for rdr/punch */ { FIXED, "RCC", 06016 }, /* Read reader buffer, clear flags & buf, */ /* and fetch character. */ /* High Speed Paper Tape Punch */ { FIXED, "PSF", 06021 }, /* SKIP ON PUNCH FLAG */ { FIXED, "PCF", 06022 }, /* CLEAR ON PUNCH FLAG */ { FIXED, "PPC", 06024 }, /* LOAD PUNCH BUFFER AND PUNCH CHARACTER* */ { FIXED, "PLS", 06026 }, /* LOAD PUNCH BUFFER AND CLEAR FLAG */ /* DECassette TU60 (RK 20071008) */ { FIXED, "KCLR", 06700 }, /* Clear all (clear A and B) */ { FIXED, "KSDR", 06701 }, /* Skip if data flag set */ { FIXED, "KSEN", 06702 }, /* Skip if EOT/BOT, not ready, or empty */ { FIXED, "KSBF", 06703 }, /* Skip if ready flag set */ { FIXED, "KLSA", 06704 }, /* AC4-11 -> A, clear A, -(AC4-11) -> A */ { FIXED, "KSAF", 06705 }, /* Skip on any flag or error */ { FIXED, "KGOA", 06706 }, /* Assert status A and transfer data to AC*/ { FIXED, "KRSB", 06707 }, /* Transfer B -> AC4-11 */ /* DECtape Transport Type TU55 and DECtape Control Type TC01 */ { FIXED, "DTRA", 06761 }, /* Contents of status register is ORed */ /* into AC bits 0-9 */ { FIXED, "DTCA", 06762 }, /* Clear status register A, all flags */ /* undisturbed */ { FIXED, "DTXA", 06764 }, /* Status register A loaded by exclusive */ /* OR from AC. If AC bit 10=0, clear */ /* error flags; if AC bit 11=0, DECtape */ /* control flag is cleared. */ { FIXED, "DTLA", 06766 }, /* Combination of DTCA and DTXA */ { FIXED, "DTSF", 06771 }, /* Skip if error flag is 1 or if DECtape */ /* control flag is 1 */ { FIXED, "DTRB", 06772 }, /* Contents of status register B is */ /* ORed into AC */ { FIXED, "DTLB", 06774 }, /* Memory field portion of status */ /* register B loaded from AC bits 6-8 */ /* Disk File and Control, Type DF32 */ { FIXED, "DCMA", 06601 }, /* CLEAR DISK MEMORY REQUEST AND */ /* INTERRUPT FLAGS */ { FIXED, "DMAR", 06603 }, /* LOAD DISK FROM AC, CLEAR AC READ */ /* INTO CORE, CLEAR INTERRUPT FLAG */ { FIXED, "DMAW", 06605 }, /* LOAD DISK FROM AC, WRITE ONTO DISK */ /* FROM CORE, CLEAR INTERRUPT FLAG */ { FIXED, "DCEA", 06611 }, /* CLEAR DISK EXTENDED ADDRESS AND */ { FIXED, "DSAC", 06612 }, /* SKIP IF ADDRESS CONFIRMED FLAG = 1 */ /* MEMORY ADDRESS EXTENSION REGISTER */ { FIXED, "DEAL", 06615 }, /* CLEAR DISK EXTENDED ADDRESS AND */ /* MEMORY ADDRESS EXTENSION REGISTER */ /* AND LOAD SAME FROM AC */ { FIXED, "DEAC", 06616 }, /* CLEAR AC, LOAD AC FROM DISK EXTENDED */ /* ADDRESS REGISTER, SKIP IF ADDRESS */ /* CONFIRMED FLAG = 1 */ { FIXED, "DFSE", 06621 }, /* SKIP IF PARITY ERROR, DATA REQUEST */ /* LATE, OR WRITE LOCK SWITCH FLAG = 0 */ /* (NO ERROR) */ { FIXED, "DFSC", 06622 }, /* SKIP IF COMPLETION FLAG = 1 (DATA */ /* TRANSFER COMPLETE) */ { FIXED, "DMAC", 06626 }, /* CLEAR AC, LOAD AC FROM DISK MEMORY */ /* ADDRESS REGISTER */ /* Disk File and Control, Type RF08 */ { FIXED, "DCIM", 06611 }, { FIXED, "DIML", 06615 }, { FIXED, "DIMA", 06616 }, { FIXED, "DISK", 06623 }, { FIXED, "DCXA", 06641 }, { FIXED, "DXAL", 06643 }, { FIXED, "DXAC", 06645 }, { FIXED, "DMMT", 06646 }, /* Memory Extension Control, Type 183 */ { FIXED, "CDF", 06201 }, /* CHANGE DATA FIELD */ { FIXED, "CIF", 06202 }, /* CHANGE INSTRUCTION FIELD */ { FIXED, "CDI", 06203 }, /* Change data & instrution field. */ { FIXED, "RDF", 06214 }, /* READ DATA FIELD */ { FIXED, "RIF", 06224 }, /* READ INSTRUCTION FIELD */ { FIXED, "RIB", 06234 }, /* READ INTERRUPT BUFFER */ { FIXED, "RMF", 06244 }, /* RESTORE MEMORY FIELD */ /* Memory Parity, Type MP8/I (MP8/L) */ { FIXED, "SMP", 06101 }, /* SKIP IF MEMORY PARITY FLAG = 0 */ { FIXED, "CMP", 06104 }, /* CLEAR MEMORY PAIRTY FLAG */ /* Memory Parity, Type MP8-E (PDP8/e) */ { FIXED, "DPI", 06100 }, /* Disable parity interrupt. */ { FIXED, "SNP", 06101 }, /* Skip if no parity error. */ { FIXED, "EPI", 06103 }, /* Enable parity interrupt. */ { FIXED, "CNP", 06104 }, /* Clear parity error flag. */ { FIXED, "CEP", 06106 }, /* Check for even parity. */ { FIXED, "SPO", 06107 }, /* Skip on parity option. */ /* Data Communications Systems, Type 680I */ { FIXED, "TTINCR", 06401 }, /* The content of the line select */ /* register is incremented by one. */ { FIXED, "TTI", 06402 }, /* The line status word is read and */ /* sampled. If the line is active for */ /* the fourth time, the line bit is */ /* shifted into the character assembly */ /* word. If the line bit is active for */ /* a number of times less than four, */ /* the count is incremented. If the */ /* line is not active, the active/inac- */ /* tive status of the line is recorded */ { FIXED, "TTO", 06404 }, /* The character in the AC is shifted */ /* right one position, zeros are shifted */ /* into vacated positions, and the orig- */ /* inal content of AC11 is transferred */ /* out of the computer on the TTY line. */ { FIXED, "TTCL", 06411 }, /* The line select register is cleared. */ { FIXED, "TTSL", 06412 }, /* The line select register is loaded by */ /* an OR transfer from the content of */ /* of AC5-11, the the AC is cleared. */ { FIXED, "TTRL", 06414 }, /* The content of the line select regis- */ /* ter is read into AC5-11 by an OR */ /* transfer. */ { FIXED, "TTSKP", 06421 }, /* Skip if clock flag is a 1. */ { FIXED, "TTXON", 06424 }, /* Clock 1 is enabled to request a prog- */ /* ram interrupt and clock 1 flag is */ /* cleared. */ { FIXED, "TTXOF", 06422 }, /* Clock 1 is disabled from causing a */ /* program interrupt and clock 1 flag */ /* is cleared. */ }; /* End-of-Symbols for Permanent Symbol Table */ /* Global variables */ SYM_T *symtab; /* Symbol Table */ int symbol_top; /* Number of entries in symbol table. */ SYM_T *fixed_symbols; /* Start of the fixed symbol table entries. */ int number_of_fixed_symbols; /*----------------------------------------------------------------------------*/ WORD16 *xreftab; /* Start of the concordance table. */ ERRSAVE_T error_list[20]; int save_error_count; #define GET_PAGE_INDEX(x) (((x) & 07600) >> 7) #define MAX_PAGES 32 LPOOL_T cp[MAX_PAGES]; /* Storage for page constants. */ int max_page_used[MAX_PAGES]; char s_detected[] = "detected"; char s_error[] = "error"; char s_errors[] = "errors"; char s_no[] = "No"; char s_page[] = "Page"; char s_symtable[] = "Symbol Table"; char s_xref[] = "Cross Reference"; char s_generated[] = "generated"; char s_link[] = "link"; char s_links[] = "links"; /* Assembler diagnostic messages. */ /* Some attempt has been made to keep continuity with the PAL-III and */ /* MACRO-8 diagnostic messages. If a diagnostic indicator, (e.g., IC) */ /* exists, then the indicator is put in the listing as the first two */ /* characters of the diagnostic message. The PAL-III indicators where used */ /* when there was a choice between using MACRO-8 and PAL-III indicators. */ /* The character pairs and their meanings are: */ /* DT Duplicate Tag (symbol) */ /* IC Illegal Character */ /* ID Illegal Redefinition of a symbol. An attempt was made to give */ /* a symbol a new value not via =. */ /* IE Illegal Equals An equal sign was used in the wrong context, */ /* (e.g., A+B=C, or TAD A+=B) */ /* II Illegal Indirect An off page reference was made, but a literal */ /* could not be generated because the indirect bit was already set. */ /* IR Illegal Reference (address is not on current page or page zero) */ /* ND No $ (the program terminator) at end of file. */ /* PE Current, Non-Zero Page Exceeded (literal table flowed into code) */ /* RD ReDefintion of a symbol */ /* ST Symbol Table full */ /* UA Undefined Address (undefined symbol) */ /* ZE Zero Page Exceeded (see above, or out of space) */ EMSG_T duplicate_label = { "DT duplicate", "duplicate label" }; EMSG_T illegal_blank = { "IC illegal blank", "illegal blank" }; EMSG_T illegal_character = { "IC illegal char", "illegal character" }; EMSG_T illegal_expression = { "IC in expression", "illegal expression" }; EMSG_T label_syntax = { "IC label syntax", "label syntax" }; EMSG_T not_a_number = { "IC numeric syntax", "numeric syntax of" }; EMSG_T number_not_radix = { "IC radix", "number not in current radix"}; EMSG_T symbol_syntax = { "IC symbol syntax", "symbol syntax" }; EMSG_T illegal_equals = { "IE illegal =", "illegal equals" }; EMSG_T illegal_indirect = { "II off page", "illegal indirect" }; EMSG_T illegal_reference = { "IR off page", "illegal reference" }; EMSG_T undefined_symbol = { "UD undefined", "undefined symbol" }; EMSG_T redefined_symbol = { "RD redefined", "redefined symbol" }; EMSG_T illegal_redefine = { "ID redefined", "Illegal redefine of symbol" }; EMSG_T literal_overflow = { "PE page exceeded", "current page literal capacity exceeded" }; EMSG_T pz_literal_overflow = { "ZE page exceeded", "page zero capacity exceeded" }; EMSG_T dubl_overflow = { "dubl overflow", "DUBL value overflow" }; EMSG_T fltg_overflow = { "fltg overflow", "FLTG value overflow" }; EMSG_T zblock_too_small = { "expr too small", "ZBLOCK value too small" }; EMSG_T zblock_too_large = { "expr too large", "ZBLOCK value too large" }; EMSG_T end_of_file = { "ND no $ at EOF", "No $ at End-of-File" }; EMSG_T no_pseudo_op = { "not implemented", "not implemented pseudo-op" }; EMSG_T illegal_field_value = { "expr out of range", "field value not in range of 0 through 7" }; EMSG_T literal_gen_off = { "literals off", "literal generation is off" }; EMSG_T no_literal_value = { "no value", "no literal value" }; EMSG_T text_string = { "no delimiter", "text string delimiters not matched" }; EMSG_T in_rim_mode = { "not OK in rim mode" "FIELD pseudo-op not valid in RIM mode" }; EMSG_T lt_expected = { "'<' expected", "'<' expected" }; EMSG_T symbol_table_full = { "ST Symbol Tbl Full", "Symbol Table Full" }; /*----------------------------------------------------------------------------*/ FILE *errorfile; FILE *infile; FILE *listfile; FILE *listsave; FILE *objectfile; FILE *objectsave; char errorpathname[NAMELEN]; char filename[NAMELEN]; char listpathname[NAMELEN]; char objectpathname[NAMELEN]; char *pathname; char permpathname[NAMELEN]; int tabstops; /* number of characters to expand a tab to */ int list_lineno; int list_pageno; char list_title[LINELEN]; BOOL list_title_set; /* Set if TITLE pseudo-op used. */ char line[LINELEN]; /* Input line. */ int lineno; /* Current line number. */ int page_lineno; /* print line number on current page. */ BOOL listed; /* Listed flag. */ BOOL listedsave; int cc; /* Column Counter (char position in line). */ WORD16 checksum; /* Generated checksum */ BOOL binary_data_output; /* Set true when data has been output. */ WORD16 clc; /* Location counter */ WORD16 cplc; /* Current page literal counter. */ char delimiter; /* Character immediately after eval'd term. */ int errors; /* Number of errors found so far. */ int links; /* Number of links generated so far. */ BOOL error_in_line; /* TRUE if error on current line. */ int errors_pass_1; /* Number of errors on pass 1. */ WORD16 field; /* Current field */ WORD16 fieldlc; /* location counter without field portion. */ BOOL fltg_input; /* TRUE when doing floating point input. */ BOOL indirect_generated; /* TRUE if an off page address generated. */ int last_xref_lexstart; /* Column where last xref symbol was located. */ int last_xref_lineno; /* Line where last xref symbol was located. */ int lexstartprev; /* Where previous lexeme started. */ int lextermprev; /* Where previous lexeme ended. */ int lexstart; /* Index of current lexeme on line. */ int lexterm; /* Index of character after current lexeme. */ BOOL literals_ok; /* Generate literals, ignore ID redefine err */ BOOL perm_redef_error; /* Make redefining perm sym with labels error */ int maxcc; /* Current line length. */ BOOL overflow; /* Overflow flag for math routines. */ int pass; /* Number of current pass. */ BOOL print_permanent_symbols; WORD16 pzlc; /* Page Zero literal counter. */ WORD16 radix; /* Default number radix. */ WORD16 reloc; /* The relocation distance. */ BOOL rim_mode; /* Generate rim format, defaults to bin */ BOOL dollar_not_required; /* $ not required at end of file */ BOOL additional_enabled; /* True if extended functions over PAL8 */ /* enabled */ BOOL symtab_print; /* Print symbol table flag */ BOOL xref; FLTG_T fltg_ac; /* Value holder for evalFltg() */ SYM_T sym_eval = { DEFINED, "", 0 }; /* Value holder for eval() */ SYM_T sym_getexpr = { DEFINED, "", 0 }; /* Value holder for getexpr() */ SYM_T sym_undefined = { UNDEFINED, "", 0 };/* Symbol Table Terminator */ /******************************************************************************/ /* */ /* Function: main */ /* */ /* Synopsis: Starting point. Controls order of assembly. */ /* */ /******************************************************************************/ int main( int argc, char *argv[] ) { int ix; int space; /* Set the default values for global symbols. */ binary_data_output = FALSE; fltg_input = FALSE; literals_ok = TRUE; perm_redef_error = FALSE; print_permanent_symbols = FALSE; rim_mode = FALSE; dollar_not_required = FALSE; additional_enabled = FALSE; symtab_print = FALSE; xref = FALSE; pathname = NULL; /* Get the options and pathnames */ getArgs( argc, argv ); /* Setup the error file in case symbol table overflows while installing the */ /* permanent symbols. */ errorfile = fopen( errorpathname, "w" ); if (errorfile == NULL) { fprintf( stderr, "Could not open error file %s: %s\n", errorpathname, strerror(errno)); exit( -1 ); } errors = 0; save_error_count = 0; pass = 0; /* This is required for symbol table initialization. */ symtab = (SYM_T *) malloc( sizeof( SYM_T ) * SYMBOL_TABLE_SIZE ); if( symtab == NULL ) { fprintf( stderr, "Could not allocate memory for symbol table.\n"); exit( -1 ); } /* Place end marker in symbol table. */ symtab[0] = sym_undefined; symbol_top = 0; number_of_fixed_symbols = symbol_top; fixed_symbols = &symtab[symbol_top - 1]; /* Enter the pseudo-ops into the symbol table */ for( ix = 0; ix < DIM( pseudo ) - (additional_enabled ? 0 : NUMBER_ADDITIONAL_PSEUDO) ; ix++ ) { defineSymbol( pseudo[ix].name, pseudo[ix].val, pseudo[ix].type, 0 ); } /* Enter the predefined symbols into the table. */ /* Also make them part of the permanent symbol table. */ for( ix = 0; ix < DIM( really_permanent_symbols ); ix++ ) { defineSymbol( really_permanent_symbols[ix].name, really_permanent_symbols[ix].val, really_permanent_symbols[ix].type | DEFFIX , 0 ); } /* Enter the predefined symbols into the table. */ /* Also make them part of the permanent symbol table. */ for( ix = 0; ix < DIM( permanent_symbols ); ix++ ) { defineSymbol( permanent_symbols[ix].name, permanent_symbols[ix].val, permanent_symbols[ix].type | DEFFIX , 0 ); } number_of_fixed_symbols = symbol_top; fixed_symbols = &symtab[symbol_top - 1]; /* Do pass one of the assembly */ checksum = 0; pass = 1; page_lineno = LIST_LINES_PER_PAGE; onePass(); errors_pass_1 = errors; /* Set up for pass two */ rewind( infile ); /*Opened in main errorfile = fopen( errorpathname, "w" );*/ objectfile = fopen( objectpathname, "wb" ); if (objectfile == NULL) { fprintf( stderr, "Could not open object file %s: %s\n", objectpathname, strerror(errno)); exit( -1 ); } objectsave = objectfile; listfile = fopen( listpathname, "w" ); if (listfile == NULL) { fprintf( stderr, "Could not open list file %s: %s\n", listpathname, strerror(errno)); exit( -1 ); } listsave = NULL; punchLeader( 0 ); checksum = 0; /* Do pass two of the assembly */ errors = 0; save_error_count = 0; page_lineno = LIST_LINES_PER_PAGE; if( xref ) { /* Get the amount of space that will be required for the concordance. */ for( space = 0, ix = 0; ix < symbol_top; ix++ ) { symtab[ix].xref_index = space; /* Index into concordance table. */ space += symtab[ix].xref_count + 1; symtab[ix].xref_count = 0; /* Clear the count for pass 2. */ } /* Allocate the necessary space. */ xreftab = (WORD16 *) malloc( sizeof( WORD16 ) * space ); /* Clear the cross reference space. */ for( ix = 0; ix < space; ix++ ) { xreftab[ix] = 0; } } pass = 2; onePass(); /* Undo effects of NOPUNCH for any following checksum */ objectfile = objectsave; punchChecksum(); /* Works great for trailer. */ punchLeader( 8 ); /* undo effects of XLIST for any following output to listing file. */ if( listfile == NULL ) { listfile = listsave; } /* Display value of error counter. */ if( errors == 0 ) { fprintf( listfile, "\n %s %s %s\n", s_no, s_detected, s_errors ); } else { fprintf( errorfile, "\n %d %s %s\n", errors, s_detected, ( errors == 1 ? s_error : s_errors )); fprintf( listfile, "\n %d %s %s\n", errors, s_detected, ( errors == 1 ? s_error : s_errors )); fprintf( stderr, " %d %s %s\n", errors, s_detected, ( errors == 1 ? s_error : s_errors )); } /* Display value of link counter. */ if( links == 0 ) { fprintf( listfile, " %s %s %s\n", s_no, s_links, s_generated ); } else { fprintf( errorfile, " %d %s %s\n", links, ( links == 1 ? s_link : s_links ), s_generated); fprintf( listfile, " %d %s %s\n", links, ( links == 1 ? s_link : s_links ), s_generated); fprintf( stderr, " %d %s %s\n", links, ( links == 1 ? s_link : s_links ), s_generated); } if( symtab_print ) { printSymbolTable(); } if( print_permanent_symbols ) { printPermanentSymbolTable(); } if( xref ) { printCrossReference(); } fclose( objectfile ); fclose( listfile ); fclose( errorfile ); if( errors == 0 && errors_pass_1 == 0 ) { remove( errorpathname ); } return( errors != 0 ); } /* main() */ /******************************************************************************/ /* */ /* Function: getArgs */ /* */ /* Synopsis: Parse command line, set flags accordingly and setup input and */ /* output files. */ /* */ /******************************************************************************/ void getArgs( int argc, char *argv[] ) { int len; int ix, jx; /* Set the defaults */ errorfile = NULL; infile = NULL; listfile = NULL; listsave = NULL; objectfile = NULL; objectsave = NULL; tabstops = 8; for( ix = 1; ix < argc; ix++ ) { if( argv[ix][0] == '-' ) { for( jx = 1; argv[ix][jx] != 0; jx++ ) { switch( argv[ix][jx] ) { case '$': dollar_not_required = TRUE; break; case 'd': symtab_print = TRUE; break; case 'a': additional_enabled = TRUE; break; case 'r': rim_mode = TRUE; break; case 'e': literals_ok = FALSE; break; case 'l': literals_ok = TRUE; break; case 'n': perm_redef_error = TRUE; break; case 'p': print_permanent_symbols = TRUE; break; /* Added -tN; RK 20071029 */ /* Damn, this is ugly, we should use getopt() */ case 't': if (argv [ix][jx + 1]) { tabstops = atoi (argv [ix] + (jx + 1)); /* advance past numbers */ for (jx++; argv [ix][jx]; jx++) ; jx--; } else { ix++; if (ix >= argc) { fprintf( stderr, "%s: missing argument for -t, expected number of tabsopts\n", argv[0] ); exit( -1 ); } for (jx = 0; argv [ix][jx]; jx++) ; jx--; tabstops = atoi (argv [ix]); } break; case 'x': xref = TRUE; break; case 'v': fprintf( stderr, "%s\n", release ); fflush( stderr ); exit( -1 ); break; default: fprintf( stderr, "%s: unknown flag: %s\n", argv[0], argv[ix] ); case 'h': fprintf( stderr, " -$ -- allow file to not end with $\n" ); fprintf( stderr, " -a -- enable additional function not in PAL8\n" ); fprintf( stderr, " -d -- dump symbol table\n" ); fprintf( stderr, " -e -- error if link generated\n" ); fprintf( stderr, " -h -- show this help\n" ); fprintf( stderr, " -l -- generate literal/link (default)\n" ); fprintf( stderr, " -n -- no redefining with label permanent symbols\n" ); fprintf( stderr, " -p -- output permanent symbols to file\n" ); fprintf( stderr, " -r -- output rim format file\n" ); fprintf( stderr, " -t N -- set tab stops to N\n" ); fprintf( stderr, " -v -- display version\n" ); fprintf( stderr, " -x -- output cross reference to file\n" ); fflush( stderr ); exit( -1 ); } /* end switch */ } /* end for */ } else { if( pathname != NULL ) { fprintf( stderr, "%s: too many input files\n", argv[0] ); exit( -1 ); } pathname = &argv[ix][0]; } } /* end for */ if( pathname == NULL ) { fprintf( stderr, "%s: no input file specified\n", argv[0] ); exit( -1 ); } len = strlen( pathname ); if( len > NAMELEN - 5 ) { fprintf( stderr, "%s: pathname \"%s\" too long\n", argv[0], pathname ); exit( -1 ); } /* Now open the input file. */ if(( infile = fopen( pathname, "r" )) == NULL ) { fprintf( stderr, "%s: cannot open \"%s\": %s\n", argv[0], pathname, strerror(errno) ); exit( -1 ); } /* Now make the pathnames */ /* Find last '.', if it exists. */ jx = len - 1; while( pathname[jx] != '.' && pathname[jx] != '/' && pathname[jx] != '\\' && jx >= 0 ) { jx--; } switch( pathname[jx] ) { case '.': break; case '/': case '\\': jx = len; break; default: break; } /* Add the pathname extensions. */ strncpy( objectpathname, pathname, jx ); objectpathname[jx] = '\0'; strcat( objectpathname, rim_mode ? ".rim" : ".bin" ); strncpy( listpathname, pathname, jx ); listpathname[jx] = '\0'; strcat( listpathname, ".lst" ); strncpy( errorpathname, pathname, jx ); errorpathname[jx] = '\0'; strcat( errorpathname, ".err" ); strncpy( permpathname, pathname, jx ); permpathname[jx] = '\0'; strcat( permpathname, ".prm" ); /* Extract the filename from the path. */ if( isalpha( pathname[0] ) && pathname[1] == ':' && pathname[2] != '\\' ) { pathname[1] = '\\'; /* MS-DOS style pathname */ } jx = len - 1; while( pathname[jx] != '/' && pathname[jx] != '\\' && jx >= 0 ) { jx--; } strcpy( filename, &pathname[jx + 1] ); } /* getArgs() */ /******************************************************************************/ /* */ /* Function: clearLiteralTable */ /* */ /* Synopsis: Clear the cp and max_page_used data storing literal */ /* information. */ /* */ /******************************************************************************/ void clearLiteralTable() { int i; for (i = 0; i < DIM(cp); i++) { cp[i].loc = 0200; /* Points to end of page for [] operands. */ cp[i].last_punched = 0200; /* Points to end of page for [] operands. */ } memset(max_page_used, 0, sizeof(max_page_used)); } /******************************************************************************/ /* */ /* Function: onePass */ /* */ /* Synopsis: Do one assembly pass. */ /* */ /******************************************************************************/ void onePass() { char name[SYMLEN]; WORD16 newclc; BOOL scanning_line; int start; SYM_T *sym; int term; WORD16 val; clc = 0200; /* Default starting address is 200 octal. */ field = 0; fieldlc = clc & 07777; reloc = 0; clearLiteralTable(); listed = TRUE; lineno = 0; list_pageno = 0; list_lineno = 0; last_xref_lexstart = 0; last_xref_lineno = 0; list_title_set = FALSE; radix = 8; /* Initial radix is octal (base 8). */ if( !rim_mode ) { /* Put out initial origin if not in rim mode. */ punchOrigin( clc ); } while( TRUE ) { readLine(); nextLexeme(); scanning_line = TRUE; while( scanning_line ) { if( isend( line[lexstart] )) { scanning_line = FALSE; } else { switch( line[lexstart] ) { case '/': scanning_line = FALSE; break; case ';': nextLexeme(); break; case '$': endOfBinary(); return; case '*': nextLexeme(); /* Skip '*', (set origin symbol) */ newclc = ((getExpr())->val & 07777 ) | field; /* Do not change Current Location Counter if an error occurred. */ if( !error_in_line ) { if(( newclc & 07600 ) != ( clc & 07600 ) ) { /* Current page has changed. */ punchLiteralPool( cp, 0 ); } clc = newclc - reloc; fieldlc = clc & 07777; if( !rim_mode ) { /* Not rim mode, put out origin. */ punchOrigin( clc ); } printLine( line, 0, fieldlc, LINE_VAL ); } break; default: switch( line[lexterm] ) { case ',': if( isalpha( line[lexstart] )) { /* Use lookup so symbol will not be counted as reference. */ sym = lookup( lexemeToName( name, lexstart, lexterm )); if( M_DEFINED( sym->type )) { if( (sym->val & 07777) != ( ( clc+reloc ) & 07777) && pass == 2 ) { errorSymbol( &duplicate_label, sym->name, lexstart ); } sym->type = sym->type | DUPLICATE; } /* Must call define on pass 2 to generate concordance. */ defineLexeme( lexstart, lexterm, ( clc + reloc ), LABEL ); } else { errorLexeme( &label_syntax, lexstart ); } nextLexeme(); /* skip label */ nextLexeme(); /* skip comma */ break; case '=': if( isalpha( line[lexstart] )) { start = lexstart; term = lexterm; delimiter = line[lexterm]; nextLexBlank(); /* skip symbol */ nextLexeme(); /* skip trailing =, allow blank */ delimiter = line[lexterm]; val = getExprs(); defineLexeme( start, term, val, DEFINED ); printLine( line, 0, val, LINE_VAL ); } else { errorLexeme( &symbol_syntax, lexstartprev ); nextLexeme(); /* skip symbol */ nextLexeme(); /* skip trailing = */ getExprs(); /* skip expression */ } break; default: if( isalpha( line[lexstart] )) { sym = evalSymbol(); val = sym->val; if( M_PSEUDO( sym->type )) { nextLexeme(); /* Skip symbol */ scanning_line = pseudoOperators( (PSEUDO_T)val & 07777 ); } else { /* Identifier is not a pseudo-op, interpret as load value */ punchOutObject( clc, getExprs() & 07777 ); incrementClc(); } } else { /* Identifier is a value, interpret as load value */ punchOutObject( clc, getExprs() & 07777 ); incrementClc(); } break; } /* end switch */ break; } /* end switch */ } /* end if */ } /* end while( scanning_line ) */ } /* end while( TRUE ) */ } /* onePass() */ /******************************************************************************/ /* */ /* Function: fixMRIInstruction */ /* */ /* Synopsis: Now that we have the final value figure out if page 0, current */ /* page, or indirect needed and max final instruction */ /* */ /******************************************************************************/ WORD16 fixMRIInstruction(WORD16 instruction, WORD16 value) { /* Now have the address part of the MRI instruction. */ if( value < 00200 ) { instruction |= value; /* Page zero MRI. */ } else if( (( fieldlc + reloc ) & 07600 ) <= value && value <= ((( fieldlc + reloc ) & 07600) | 0177 )) { instruction |= ( PAGE_BIT | (value & ADDRESS_FIELD )); /* Current page MRI */ } else { if(( instruction & INDIRECT_BIT ) == INDIRECT_BIT ) { /* Already indirect, can't generate */ errorSymbol( &illegal_indirect, NULL, lexstartprev ); } else { if( literals_ok ) { /* Now fix off page reference. */ /* Search current page literal pool for needed instruction. */ /* Set Indirect Current Page */ instruction |= ( 00600 | insertLiteral( cp, value, GET_PAGE_INDEX(clc) )); indirect_generated = TRUE; if (pass == 2) { links++; } } else { errorSymbol( &illegal_reference, NULL, lexstartprev ); instruction |= ( value & 0177 ); } } } return instruction; } /******************************************************************************/ /* */ /* Function: getExprs */ /* */ /* Synopsis: Or together a list of blank separated expressions, from the */ /* current lexeme onward. Leave the current lexeme as */ /* the last one in the list. */ /* */ /******************************************************************************/ WORD16 getExprs() { SYM_T *symv; SYM_T *symt; WORD16 temp; SYMTYP temp_type; WORD16 value; SYMTYP value_type; BOOL MRI_held = FALSE; WORD16 held_value = 0; symv = getExpr(); value = symv->val; value_type = symv->type; while( TRUE ) { if( isdone( line[lexstart] )) { if (MRI_held) { value = fixMRIInstruction(value, held_value); } return( value ); } switch( line[lexstart] ) { case ')': case ']': case '<': if (MRI_held) { value = fixMRIInstruction(value, held_value); } return( value ); default: break; } /* Interpret space as logical or */ symt = getExpr(); temp = symt->val & 07777; temp_type = symt->type; switch( value_type & (MRI | MRIFIX)) { case MRI: case MRIFIX: /* Previous symbol was a Memory Reference Instruction. */ switch( temp_type & (MRI | MRIFIX) ) { case MRI: case MRIFIX: /* If we have held value don't or in more MRI's to instuction, they */ /* are now instuction value */ if (MRI_held) { held_value |= temp; } else { /* Current symbol is also a Memory Reference Instruction. */ value |= temp; /* Just OR the MRI instructions. */ } break; default: held_value |= temp; MRI_held = TRUE; break; } break; default: if (value_type == UNDEFINED || temp_type == UNDEFINED) { value = 0; } else { value |= temp; /* Normal 12 bit value. */ } break; } } /* end while */ } /* getExprs() */ /******************************************************************************/ /* */ /* Function: getExpr */ /* */ /* Synopsis: Get an expression, from the current lexeme onward, leave the */ /* current lexeme as the one after the expression. Expressions */ /* contain terminal symbols (identifiers) separated by operators. */ /* */ /******************************************************************************/ SYM_T *getExpr() { SYM_T *sym; delimiter = line[lexterm]; if( line[lexstart] == '-' ) { nextLexBlank(); sym_getexpr = *(eval()); sym_getexpr.val = ( - sym_getexpr.val ) & 07777; } else { if( line[lexstart] == '+' ) { nextLexBlank(); } sym_getexpr = *(eval()); sym_getexpr.val = sym_getexpr.val & 07777; } if( is_blank( delimiter )) { return( &sym_getexpr ); } /* Here we assume the current lexeme is the operator separating the */ /* previous operator from the next, if any. */ while( TRUE ) { /* assert line[lexstart] == delimiter */ if( is_blank( delimiter )) { return( &sym_getexpr ); } switch( line[lexstart] ) { case '+': /* add */ nextLexBlank(); /* skip over the operator */ sym = eval(); sym_getexpr.val += sym->val; if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) { sym_getexpr.val = 0; sym_getexpr.type = UNDEFINED; } break; case '-': /* subtract */ nextLexBlank(); /* skip over the operator */ sym = eval(); sym_getexpr.val -= sym->val; if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) { sym_getexpr.val = 0; sym_getexpr.type = UNDEFINED; } break; case '^': /* multiply */ nextLexBlank(); /* skip over the operator */ sym = eval(); sym_getexpr.val *= sym->val; if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) { sym_getexpr.val = 0; sym_getexpr.type = UNDEFINED; } break; case '%': /* divide */ nextLexBlank(); /* skip over the operator */ sym = eval(); sym_getexpr.val /= sym->val; if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) { sym_getexpr.val = 0; sym_getexpr.type = UNDEFINED; } break; case '&': /* and */ nextLexBlank(); /* skip over the operator */ sym = eval(); sym_getexpr.val &= sym->val; if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) { sym_getexpr.val = 0; sym_getexpr.type = UNDEFINED; } break; case '!': /* or */ nextLexBlank(); /* skip over the operator */ sym = eval(); sym_getexpr.val |= sym->val; if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) { sym_getexpr.val = 0; sym_getexpr.type = UNDEFINED; } break; default: if( isend( line[lexstart] )) { return( &sym_getexpr ); } switch( line[lexstart] ) { case '/': case ';': case ')': case ']': case '<': break; case '=': errorMessage( &illegal_equals, lexstart ); moveToEndOfLine(); sym_getexpr.val = 0; break; default: errorMessage( &illegal_expression, lexstart ); moveToEndOfLine(); sym_getexpr.val = 0; break; } return( &sym_getexpr ); } } /* end while */ } /* getExpr() */ /******************************************************************************/ /* */ /* Function: eval */ /* */ /* Synopsis: Get the value of the current lexeme, set delimiter and advance.*/ /* */ /******************************************************************************/ SYM_T *eval() { WORD16 digit; int from; WORD16 loc; SYM_T *sym; WORD16 val; val = 0; delimiter = line[lexterm]; if( isalpha( line[lexstart] )) { sym = evalSymbol(); if( M_UNDEFINED( sym->type ) && pass == 2 ) { errorSymbol( &undefined_symbol, sym->name, lexstart ); nextLexeme(); return( sym ); } else { nextLexeme(); return( sym ); } } else if( isdigit( line[lexstart] )) { from = lexstart; val = 0; while( from < lexterm ) { if( isdigit( line[from] )) { digit = (WORD16) line[from++] - (WORD16) '0'; if( digit < radix ) { val = val * radix + digit; } else { errorLexeme( &number_not_radix, from - 1 ); val = 0; from = lexterm; } } else { errorLexeme( ¬_a_number, lexstart ); val = 0; from = lexterm; } } nextLexeme(); sym_eval.val = val; return( &sym_eval ); } else { switch( line[lexstart] ) { case '"': /* Character literal */ if( cc + 1 <= maxcc ) { val = line[lexstart + 1] | 0200; delimiter = line[lexstart + 2]; cc = lexstart + 2; } else { errorMessage( &no_literal_value, lexstart ); } nextLexeme(); break; case '.': /* Value of Current Location Counter */ val = (clc & 07777) + reloc; nextLexeme(); break; case '[': /* Generate literal on page zero. */ if( !literals_ok && LITERAL_ERROR) { errorMessage( &literal_gen_off, lexstart ); } nextLexBlank(); /* Skip bracket */ val = getExprs() & 07777; if( line[lexstart] == ']' ) { nextLexBlank(); /* Skip end bracket */ } sym_eval.val = (literals_ok || !LITERAL_ERROR) ? insertLiteral( cp , val, GET_PAGE_INDEX(field)) : 0; return( &sym_eval ); case '(': /* Generate literal on current page. */ if( !literals_ok && LITERAL_ERROR) { errorMessage( &literal_gen_off, lexstart ); } nextLexBlank(); /* Skip paren */ val = getExprs() & 07777; if( line[lexstart] == ')' ) { nextLexBlank(); /* Skip end paren */ } loc = (literals_ok || !LITERAL_ERROR) ? insertLiteral( cp, val, GET_PAGE_INDEX(clc) ) : 0; sym_eval.val = loc + (( clc + reloc ) & 077600 ); return( &sym_eval ); default: switch( line[lexstart] ) { case '=': errorMessage( &illegal_equals, lexstart ); moveToEndOfLine(); break; default: errorMessage( &illegal_character, lexstart ); break; } val = 0; /* On error, set value to zero. */ nextLexBlank(); /* Go past illegal character. */ } } sym_eval.val = val; return( &sym_eval ); } /* eval() */ /******************************************************************************/ /* */ /* Function: inputDubl */ /* */ /* Synopsis: Get the value of the current lexeme as a double word. */ /* */ /******************************************************************************/ void inputDubl() { WORD32 dublvalue; BOOL scanning_line; scanning_line = TRUE; do { while( scanning_line ) { if( isend( line[lexstart] )) { scanning_line = FALSE; } else { switch( line[lexstart] ) { case '/': scanning_line = FALSE; break; case ';': nextLexeme(); break; case '+': delimiter = line[lexterm]; nextLexBlank(); case '-': default: if( isdigit( line[lexstart] ) || line[lexstart] == '-' ) { dublvalue = getDublExprs(); punchOutObject( clc, (WORD16)(( dublvalue >> 12 ) & 07777 )); incrementClc(); punchOutObject( clc, (WORD16)( dublvalue & 07777 )); incrementClc(); } else { return; /* Non-numeric input, back to assembly. */ } break; } /* end switch */ } /* end if */ if( error_in_line ) { return; /* Error occurred, exit DUBL input mode. */ } } /* end while( scanning_line ) */ readLine(); nextLexeme(); scanning_line = TRUE; } while( TRUE ); } /* inputDubl() */ /******************************************************************************/ /* */ /* Function: getDublExprs */ /* */ /* Synopsis: Get a DUBL expression. */ /* */ /******************************************************************************/ WORD32 getDublExprs() { WORD32 dublvalue; dublvalue = getDublExpr(); while( TRUE ) { if( isdone( line[lexstart] )) { return( dublvalue ); } else { errorMessage( &illegal_expression, lexstart - 1 ); return( 0 ); } } /* end while */ } /* getDublExprs() */ /******************************************************************************/ /* */ /* Function: getDublExpr */ /* */ /* Synopsis: Get the value of the current lexeme as a double word. The */ /* number is always considered to have a decimal radix. */ /* */ /******************************************************************************/ WORD32 getDublExpr() { WORD32 dublvalue; delimiter = line[lexterm]; if( line[lexstart] == '-' ) { nextLexBlank(); dublvalue = evalDubl( 0 ); nextLexeme(); /* Test for any value greater than 23 bits in length. */ if( (unsigned long int)dublvalue > 040000000L ) { errorMessage( &dubl_overflow, lexstart ); dublvalue = 0; } dublvalue = -dublvalue; } else { dublvalue = evalDubl( 0 ); nextLexeme(); /* Test for any value greater than 23 bits in length. */ if( (unsigned long int)dublvalue > 037777777L ) { errorMessage( &dubl_overflow, lexstart ); dublvalue = 0; } } if( is_blank( delimiter )) { return( dublvalue ); } /* Here we assume the current lexeme is the operator separating the */ /* previous operator from the next, if any. */ while( TRUE ) { /* assert line[lexstart] == delimiter */ if( is_blank( delimiter )) { errorMessage( &illegal_expression, lexstart ); moveToEndOfLine(); dublvalue = 0; return( dublvalue ); } switch( line[lexstart] ) { case '+': /* add */ case '-': /* subtract */ case '^': /* multiply */ case '%': /* divide */ case '&': /* and */ case '!': /* or */ errorMessage( &illegal_expression, lexstart ); moveToEndOfLine(); dublvalue = 0; break; default: if( isend( line[lexstart] )) { return( dublvalue ); } switch( line[lexstart] ) { case '/': case ';': break; default: errorMessage( &illegal_expression, lexstart ); moveToEndOfLine(); dublvalue = 0; break; } return( dublvalue ); } } /* end while */ } /* getDublExpr() */ /******************************************************************************/ /* */ /* Function: evalDubl */ /* */ /* Synopsis: Get the value of the current lexeme as a double word. The */ /* number is always considered to have a decimal radix. */ /* */ /******************************************************************************/ WORD32 evalDubl( WORD32 initial_value ) { WORD32 digit; int from; WORD32 dublvalue; WORD32 olddublvalue; overflow = FALSE; delimiter = line[lexterm]; from = lexstart; dublvalue = initial_value; while( from < lexterm ) { if( isdigit( line[from] )) { olddublvalue = dublvalue; digit = (WORD32)( line[from++] - '0' ); dublvalue = dublvalue * 10 + digit; if( dublvalue < olddublvalue ) { overflow = TRUE; } } else { errorLexeme( ¬_a_number, from ); dublvalue = 0; from = lexterm; } } return( dublvalue ); } /* evalDubl() */ /******************************************************************************/ /* */ /* Function: inputFltg */ /* */ /* Synopsis: Get the value of the current lexeme as a Floating Point const. */ /* */ /******************************************************************************/ void inputFltg() { FLTG_T *fltg; BOOL scanning_line; fltg_input = TRUE; /* Set lexeme scanner for floating point. */ scanning_line = TRUE; while( TRUE ) { while( scanning_line ) { if( isend( line[lexstart] )) { scanning_line = FALSE; } else { switch( line[lexstart] ) { case '/': scanning_line = FALSE; break; case ';': nextLexeme(); break; case '+': delimiter = line[lexterm]; nextLexBlank(); case '-': default: if( isdigit( line[lexstart] ) || line[lexstart] == '-' ) { fltg = getFltgExprs(); punchOutObject( clc, ( fltg->exponent & 07777 )); incrementClc(); punchOutObject( clc, (WORD16)(( fltg->mantissa >> 12 ) & 07777 )); incrementClc(); punchOutObject( clc, (WORD16)( fltg->mantissa & 07777 )); incrementClc(); } else { fltg_input = FALSE; /* Reset lexeme scanner. */ return; /* Non-numeric input, back to assembly. */ } break; } /* end switch */ } /* end if */ if( error_in_line ) { fltg_input = FALSE; /* Reset lexeme scanner. */ return; /* Error occurred, exit FLTG input mode. */ } } /* end while( scanning_line ) */ readLine(); nextLexeme(); scanning_line = TRUE; } } /* inputFltg() */ /******************************************************************************/ /* */ /* Function: getFltgExprs */ /* */ /* Synopsis: Get a FLTG expression. */ /* */ /******************************************************************************/ FLTG_T *getFltgExprs() { FLTG_T *fltg; fltg = getFltgExpr(); while( TRUE ) { if( isdone( line[lexstart] )) { return( fltg ); } else { errorMessage( &illegal_expression, lexstart - 1 ); return( 0 ); } } /* end while */ } /* getFltgExprs() */ /******************************************************************************/ /* */ /* Function: getFltgExpr */ /* */ /* Synopsis: Get the value of the current lexeme as a double word. The */ /* number is always considered to have a decimal radix. */ /* */ /******************************************************************************/ FLTG_T *getFltgExpr() { FLTG_T *fltg; delimiter = line[lexterm]; fltg = evalFltg(); /* Test for any value greater than 23 bits in length. */ if( (unsigned long int)fltg->mantissa> 077777777L ) { errorMessage( &fltg_overflow, lexstart ); } if( is_blank( delimiter )) { return( fltg ); } /* Here we assume the current lexeme is the operator separating the */ /* previous operator from the next, if any. */ while( TRUE ) { /* assert line[lexstart] == delimiter */ if( is_blank( delimiter )) { errorMessage( &illegal_expression, lexstart ); moveToEndOfLine(); fltg = 0; return( fltg ); } switch( line[lexstart] ) { case '+': /* add */ case '-': /* subtract */ case '^': /* multiply */ case '%': /* divide */ case '&': /* and */ case '!': /* or */ errorMessage( &illegal_expression, lexstart ); moveToEndOfLine(); fltg = NULL; break; default: if( isend( line[lexstart] )) { return( fltg ); } switch( line[lexstart] ) { case '/': case ';': break; default: errorMessage( &illegal_expression, lexstart ); moveToEndOfLine(); fltg = NULL; break; } return( fltg ); } } /* end while */ } /* getFltgExpr() */ /******************************************************************************/ /* */ /* Function: evalFltg */ /* */ /* Synopsis: Get the value of the current lexeme as a floating point value. */ /* Floating point input is alwasy considered decimal. */ /* The general format of a floating point number is: */ /* +-ddd.dddE+-dd where each d is a decimal digit. */ /* */ /******************************************************************************/ FLTG_T *evalFltg() { int current_state; int current_col; WORD16 exponent; FLTG_T *fltg; WORD32 input_value; BOOL negate; BOOL negate_exponent; int next_state; int right_digits; /* This uses a lexical analyzer to parse the floating point format. */ static BYTE state_table[][10] = { /* 0 1 2 3 4 5 6 Oolumn index */ /* + - d . E sp p State Comment */ { 2, 1, 3, 4, 10, 10, 10 }, /* 0 Initial state. */ { 11, 11, 3, 4, 11, 11, 11 }, /* 1 - */ { 11, 11, 3, 4, 11, 11, 11 }, /* 2 + */ { 10, 10, 10, 4, 6, 10, 10 }, /* 3 # (+-ddd) */ { 11, 11, 5, 11, 11, 10, 10 }, /* 4 . (+-ddd.) */ { 11, 11, 11, 11, 6, 10, 11 }, /* 5 # (+-ddd.ddd) */ { 8, 7, 9, 11, 11, 11, 11 }, /* 6 E (+-ddd.dddE) */ { 11, 11, 9, 11, 11, 11, 11 }, /* 7 - (+-ddd.dddE- */ { 11, 11, 9, 11, 11, 11, 11 }, /* 8 + (+-ddd.dddE+ */ { 11, 11, 11, 11, 11, 10, 11 } /* 9 # (+-ddd.dddE+-dd */ /* 10 Completion state */ /* 11 Error state. */ }; delimiter = line[lexterm]; fltg = &fltg_ac; fltg->exponent = 0; fltg->mantissa = 0; input_value = 0; negate = FALSE; negate_exponent = FALSE; next_state = 0; exponent = 0; right_digits = 0; current_state = 0; while( TRUE ) { /* Classify character. This is the column index. */ switch( line[lexstart] ) { case '+': current_col = 0; break; case '-': current_col = 1; break; case '.': current_col = 3; break; case 'E': case 'e': current_col = 4; break; default: if( isdigit( line[lexstart] )) { current_col = 2; } else if( isdone( line[lexstart] )) { current_col = 5; } else { current_col = 6; } break; } next_state = state_table[current_state][current_col]; switch( next_state ) { case 1: /* - */ negate = TRUE; case 2: /* + */ delimiter = line[lexterm]; /* Move past the + or - character. */ nextLexBlank(); break; case 3: /* Number (+-ddd) */ input_value = evalDubl( 0 ); /* Integer part of the number. */ nextLexeme(); /* Move past previous lexeme. */ break; case 4: delimiter = line[lexterm]; nextLexBlank(); /* Move past the . character. */ break; case 5: /* . (+-ddd.ddd) */ /* Fractional part of the number. */ input_value = evalDubl( input_value ); right_digits = lexterm - lexstart;/* Digit count to right of decimal. */ nextLexeme(); /* Move past previous lexeme. */ break; case 6: /* E (+-ddd.dddE) */ delimiter = line[lexterm]; /* Move past the E. */ nextLexBlank(); break; case 7: /* - (+-ddd.dddE-) */ negate_exponent = TRUE; case 8: /* + (+-ddd.dddE+) */ delimiter = line[lexterm]; /* Move past the + or - character. */ nextLexBlank(); break; case 9: /* # (+-ddd.dddE+-dd) */ exponent = (int)evalDubl( 0 ); /* Exponent of floating point number. */ if( negate_exponent ) { exponent = - exponent; } nextLexeme(); /* Move past previous lexeme. */ break; case 10: /* Floating number parsed, convert */ /* the number. */ /* Get the exponent for the number as input. */ exponent -= right_digits; /* Remove trailing zeros and adjust the exponent accordingly. */ while(( input_value % 10 ) == 0 ) { input_value /= 10; exponent++; } /* Convert the number to floating point. The number is calculated with */ /* a 27 bit mantissa to improve precision. The extra 3 bits are */ /* discarded after the result has been calculated. */ fltg->exponent = 26; fltg->mantissa = input_value << 3; normalizeFltg( fltg ); while( exponent != 0 ) { if( exponent < 0 ) { /* Decimal point is to the left. */ fltg->mantissa /= 10; normalizeFltg( fltg ); exponent++; } else if( exponent > 0 ) { /* Decimal point is to the right. */ fltg->mantissa *= 10; normalizeFltg( fltg ); exponent--; } } /* Discard the extra precsion used for calculating the number. */ fltg->mantissa >>= 3; fltg->exponent -= 3; if( negate ) { fltg->mantissa = (- fltg->mantissa ) & 077777777L; } return( fltg ); case 11: /* Error in format. */ /* Not a properly constructued floating point number. */ return( fltg ); default: break; } /* Set state for next pass through the loop. */ current_state = next_state; } } /* evalFltg() */ /******************************************************************************/ /* */ /* Function: normalizeFltg */ /* */ /* Synopsis: Normalize a PDP-8 double precision floating point number. */ /* */ /******************************************************************************/ void normalizeFltg( FLTG_T *fltg ) { /* Normalize the floating point number. */ if( fltg->mantissa != 0 ) { if(( fltg->mantissa & ~0x3FFFFFFL ) == 0 ) { while(( fltg->mantissa & ~0x1FFFFFFL ) == 0 ) { fltg->mantissa <<= 1; fltg->exponent--; } } else { while(( fltg->mantissa & ~0x3FFFFFFL ) != 0 ) { fltg->mantissa >>= 1; fltg->exponent++; } } } else { fltg->exponent = 0; } return; } /******************************************************************************/ /* */ /* Function: incrementClc */ /* */ /* Synopsis: Set the next assembly location. Test for collision with */ /* the literal tables. */ /* */ /******************************************************************************/ WORD16 incrementClc() { testForLiteralCollision( clc ); /* Incrementing the location counter is not to change field setting. */ clc = ( clc & 070000 ) + (( clc + 1 ) & 07777 ); fieldlc = clc & 07777; return( clc ); } /* incrementClc() */ /******************************************************************************/ /* */ /* Function: testForLiteralCollision */ /* */ /* Synopsis: Test the given location for collision with the literal tables. */ /* */ /******************************************************************************/ BOOL testForLiteralCollision( WORD16 loc ) { WORD16 pagelc; BOOL result = FALSE; WORD16 tmppage; int tmpfield; tmpfield = GET_PAGE_INDEX(loc); tmppage = loc & 07600; pagelc = loc & 00177; if ( pagelc > max_page_used[tmpfield] ) { max_page_used[tmpfield] = pagelc; } if ( pagelc >= cp[tmpfield].loc ) { if ( tmppage == 0 ) { errorMessage( &pz_literal_overflow, -1 ); } else { errorMessage( &literal_overflow, -1 ); } result = TRUE; } return( result ); } /* testForLiteralCollision() */ /******************************************************************************/ /* */ /* Function: readLine */ /* */ /* Synopsis: Get next line of input. Print previous line if needed. */ /* */ /******************************************************************************/ void readLine() { WORD16 ix; WORD16 iy; char inpline[LINELEN]; listLine(); /* List previous line if needed. */ lineno++; /* Count lines read. */ indirect_generated = FALSE; /* Mark no indirect address generated. */ listed = FALSE; /* Mark as not listed. */ cc = 0; /* Initialize column counter. */ lexstartprev = 0; error_in_line = FALSE; if(( fgets( inpline, LINELEN - 1, infile )) == NULL ) { inpline[0] = '$'; inpline[1] = '\n'; inpline[2] = '\0'; if (!dollar_not_required) { error_in_line = TRUE; } } /* Remove any tabs from the input line by inserting the required number */ /* of spaces to simulate N character tab stops, where N defaults to 8 and */ /* is set by the command line option -t. (RK 20071029) */ /* Ignore \r if there is one. (DPI 20150501) */ for( ix = 0, iy = 0; inpline[ix] != '\0' && iy < (LINELEN - 2); ix++ ) { switch( inpline[ix] ) { case '\t': do { line[iy] = ' '; iy++; } while(( iy % tabstops ) != 0 && iy < (LINELEN - 2)); break; case '\r': /* dont copy the carriage return */ break; default: line[iy] = inpline[ix]; iy++; break; } } if (iy >= (LINELEN - 2)) { line [iy] = '\n'; iy++; } line[iy] = '\0'; maxcc = iy; /* Save the current line length. */ /* Save the first line for possible use as the listing title. */ if( lineno == 1 ) { strcpy( list_title, line ); } } /* readLine() */ /******************************************************************************/ /* */ /* Function: listLine */ /* */ /* Synopsis: Output a line to the listing file. */ /* */ /******************************************************************************/ void listLine() /* generate a line of listing if not already done! */ { if( listfile != NULL && listed == FALSE ) { printLine( line, 0, 0, LINE ); } } /* listLine() */ /******************************************************************************/ /* */ /* Function: printPageBreak */ /* */ /* Synopsis: Output a Top of Form and listing header if new page necessary. */ /* */ /******************************************************************************/ void printPageBreak() { if( page_lineno >= LIST_LINES_PER_PAGE ) /* ( list_lineno % LIST_LINES_PER_PAGE ) == 0 ) */ { if( !list_title_set ) { /* strcpy( list_title, line ); */ if( list_title[strlen(list_title) - 1] == '\n' ) { list_title[strlen(list_title) - 1] = '\0'; } if( strlen( list_title ) > TITLELEN ) { list_title[TITLELEN] = '\0'; } list_title_set = TRUE; } topOfForm( list_title, NULL ); } } /* printPageBreak() */ /******************************************************************************/ /* */ /* Function: printLine */ /* */ /* Synopsis: Output a line to the listing file with new page if necessary. */ /* */ /******************************************************************************/ void printLine( char *line, WORD16 loc, WORD16 val, LINESTYLE_T linestyle ) { char rlc; if( listfile == NULL ) { save_error_count = 0; return; } printPageBreak(); list_lineno++; page_lineno++; if (reloc == 0) { rlc = ' '; } else { rlc = '*'; } switch( linestyle ) { default: case LINE: fprintf(listfile, "%5d ", lineno ); fputs( line, listfile ); listed = TRUE; break; case LINE_VAL: fprintf(listfile, "%5d %4.4o ", lineno, val ); fputs( line, listfile ); listed = TRUE; break; case LINE_LOC_VAL: if( !listed ) { if( indirect_generated ) { fprintf( listfile, "%5d %5.5o%c %4.4o@ ", lineno, loc, rlc, val ); } else { fprintf( listfile, "%5d %5.5o%c %4.4o ", lineno, loc, rlc, val ); } fputs( line, listfile ); listed = TRUE; } else { fprintf( listfile, " %5.5o%c %4.4o\n", loc, rlc, val ); } break; case LOC_VAL: fprintf( listfile, " %5.5o%c %4.4o\n", loc, rlc, val ); break; } printErrorMessages(); } /* printLine() */ /******************************************************************************/ /* */ /* Function: printErrorMessages */ /* */ /* Synopsis: Output any error messages from the current list of errors. */ /* */ /******************************************************************************/ void printErrorMessages() { WORD16 ix; WORD16 iy; if( listfile != NULL ) { /* If any errors, display them now. */ for( iy = 0; iy < save_error_count; iy++ ) { printPageBreak(); fprintf( listfile, "%-18.18s", error_list[iy].mesg ); if( error_list[iy].col >= 0 ) { for( ix = 0; ix < error_list[iy].col; ix++ ) { if( line[ix] == '\t' ) { putc( '\t', listfile ); } else { putc( ' ', listfile ); } } fputs( "^", listfile ); list_lineno++; page_lineno++; } fputs( "\n", listfile ); } } save_error_count = 0; } /* printErrorMessages() */ /******************************************************************************/ /* */ /* Function: endOfBinary */ /* */ /* Synopsis: Outputs both literal tables at the end of a binary segment. */ /* */ /******************************************************************************/ void endOfBinary() { /* Punch page 0 also. */ punchLiteralPool( cp, 1 ); if( error_in_line ) { listed = TRUE; clc = ( clc & 070000 ) + (( clc - 1 ) & 07777 ); errorMessage( &end_of_file, -1 ); clc = ( clc & 070000 ) + (( clc + 1 ) & 07777 ); } else { listLine(); /* List line if not done yet. */ } return; } /* endOfBinary() */ /******************************************************************************/ /* */ /* Function: punchChecksum */ /* */ /* Synopsis: Output a checksum if the current mode requires it and an */ /* object file exists. */ /* */ /******************************************************************************/ void punchChecksum() { /* If the assembler has output any BIN data output the checksum. */ if( binary_data_output && !rim_mode ) { punchLocObject( 0, checksum ); } binary_data_output = FALSE; checksum = 0; } /* punchChecksum() */ /******************************************************************************/ /* */ /* Function: punchLeader */ /* */ /* Synopsis: Generate 2 feet of leader on object file, as per DEC */ /* documentation. Paper tape has 10 punches per inch. */ /* */ /******************************************************************************/ void punchLeader( int count ) { int ix; /* If value is zero, set to the default of 2 feet of leader. */ count = ( count == 0 ) ? 240 : count; if( objectfile != NULL ) { for( ix = 0; ix < count; ix++ ) { fputc( 0200, objectfile ); } } } /* punchLeader() */ /******************************************************************************/ /* */ /* Function: punchOrigin */ /* */ /* Synopsis: Output an origin to the object file. */ /* */ /******************************************************************************/ void punchOrigin( WORD16 loc ) { punchObject((( loc >> 6 ) & 0077 ) | 0100 ); punchObject( loc & 0077 ); } /* punchOrigin() */ /******************************************************************************/ /* */ /* Function: punchObject */ /* */ /* Synopsis: Put one character to object file and include it in checksum. */ /* */ /******************************************************************************/ void punchObject( WORD16 val ) { val &= 0377; if( objectfile != NULL ) { fputc( val, objectfile ); checksum += val; } binary_data_output = TRUE; } /* punchObject() */ /******************************************************************************/ /* */ /* Function: punchOutObject */ /* */ /* Synopsis: Output the current line and then then punch value to the */ /* object file. */ /* */ /******************************************************************************/ void punchOutObject( WORD16 loc, WORD16 val ) { /* Adding reloc makes printout agree with PAL8 where is prints the */ /* relocated address, not the address in the BIN file */ printLine( line,( ( field | loc ) + reloc ), val, LINE_LOC_VAL ); punchLocObject( loc, val ); } /* punchOutObject() */ /******************************************************************************/ /* */ /* Function: punchLocObject */ /* */ /* Synopsis: Output the word (with origin if rim format) to the object file.*/ /* */ /******************************************************************************/ void punchLocObject( WORD16 loc, WORD16 val ) { if( rim_mode ) { punchOrigin( loc ); } punchObject(( val >> 6 ) & 0077 ); punchObject( val & 0077 ); } /* punchLocObject() */ /******************************************************************************/ /* */ /* Function: punchLiteralPool */ /* */ /* Synopsis: Output the current page data. */ /* */ /******************************************************************************/ void punchLiteralPool( LPOOL_T *p, BOOL punch_page0 ) { WORD16 loc; WORD16 tmplc; int lpool_page = 0; /* Silence false uninitialized error from GCC */ int i; for (i = MAX_PAGES-1; i >= 0; i--) { lpool_page = (i << 7) & 07600; if ( p[i].loc != p[i].last_punched && (punch_page0 || lpool_page != 0) ) { if( !rim_mode ) { /* Put out origin if not in rim mode. */ punchOrigin( p[i].loc | lpool_page ); } /* Put the literals in the object file. */ for( loc = p[i].loc; loc < p[i].last_punched; loc++ ) { tmplc = loc + lpool_page; printLine( line, (field | tmplc), p[i].pool[loc], LOC_VAL ); punchLocObject( tmplc, p[i].pool[loc] ); } p[i].last_punched = p[i].loc; } } } /* punchLiteralPool() */ /******************************************************************************/ /* */ /* Function: insertLiteral */ /* */ /* Synopsis: Add a value to the given literal pool if not already in pool. */ /* Return the location of the value in the pool. */ /* */ /******************************************************************************/ WORD16 insertLiteral( LPOOL_T *pool, WORD16 value, int fieldpage_index ) { WORD16 ix; LPOOL_T *p; p = &pool[fieldpage_index]; /* Search the literal pool for any occurence of the needed value. */ ix = PAGE_SIZE - 1; while( ix >= p->loc && p->pool[ix] != value ) { ix--; } /* Check if value found in literal pool. If not, then insert value. */ if( ix < p->loc ) { (p->loc)--; p->pool[p->loc] = value; ix = p->loc; if( max_page_used[fieldpage_index] >= p->loc ) { if ( (fieldpage_index & 017) == 0 ) { errorMessage( &pz_literal_overflow, -1 ); } else { errorMessage( &literal_overflow, -1 ); } } } return( ix ); } /* insertLiteral() */ /******************************************************************************/ /* */ /* Function: printSymbolTable */ /* */ /* Synopsis: Output the symbol table. */ /* */ /******************************************************************************/ void printSymbolTable() { int col; int cx; char *fmt; int ix; char mark; int page; int row; int symbol_base; int symbol_lines; symbol_base = number_of_fixed_symbols; for( page=0, list_lineno=0, col=0, ix=symbol_base; ix < symbol_top; page++ ) { topOfForm( list_title, s_symtable ); symbol_lines = LIST_LINES_PER_PAGE - page_lineno; for( row = 0; page_lineno < LIST_LINES_PER_PAGE && ix < symbol_top; row++) { list_lineno++; page_lineno++; fprintf( listfile, "%5d", list_lineno ); for( col = 0; col < SYMBOL_COLUMNS && ix < symbol_top; col++ ) { /* Get index of symbol for the current line and column */ cx = symbol_lines * ( SYMBOL_COLUMNS * page + col ) + row; cx += symbol_base; /* Make sure that there is a symbol to be printed. */ if( number_of_fixed_symbols <= cx && cx < symbol_top ) { switch( symtab[cx].type & LABEL ) { case LABEL: fmt = " %c%-6.6s %5.5o "; break; default: fmt = " %c%-6.6s %4.4o "; break; } switch( symtab[cx].type & ( DEFINED | REDEFINED )) { case UNDEFINED: mark = '?'; break; case REDEFINED: mark = '#'; break; default: mark = ' '; break; } fprintf( listfile, fmt, mark, symtab[cx].name, symtab[cx].val ); ix++; } } fprintf( listfile, "\n" ); } } } /* printSymbolTable() */ /******************************************************************************/ /* */ /* Function: printPermanentSymbolTable */ /* */ /* Synopsis: Output the permanent symbol table to a file suitable for */ /* being input after the EXPUNGE pseudo-op. */ /* */ /******************************************************************************/ void printPermanentSymbolTable() { int ix; FILE *permfile; char *s_type; if(( permfile = fopen( permpathname, "w" )) == NULL ) { exit( 2 ); } fprintf( permfile, "/ PERMANENT SYMBOL TABLE\n/\n" ); fprintf( permfile, " EXPUNGE\n/\n" ); /* Print the memory reference instructions first. */ s_type = "FIXMRI"; for( ix = 0; ix < symbol_top; ix++ ) { if( M_MRI( symtab[ix].type )) { fprintf( permfile, "%-7s %s=%4.4o\n", s_type, symtab[ix].name, symtab[ix].val ); } } s_type = " "; for( ix = 0; ix < symbol_top; ix++ ) { if( M_FIXED( symtab[ix].type )) { if( !M_MRI( symtab[ix].type ) && !M_PSEUDO( symtab[ix].type )) { fprintf( permfile, "%-7s %s=%4.4o\n", s_type, symtab[ix].name, symtab[ix].val ); } } } fprintf( permfile, "/\n FIXTAB\n" ); fclose( permfile ); } /* printPermanentSymbolTable() */ /******************************************************************************/ /* */ /* Function: printCrossReference */ /* */ /* Synopsis: Output a cross reference (concordance) for the file being */ /* assembled. */ /* */ /******************************************************************************/ void printCrossReference() { int ix; int symbol_base; int xc; int xc_index; int xc_refcount; int xc_cols; /* Force top of form for first page. */ page_lineno = LIST_LINES_PER_PAGE; list_lineno = 0; symbol_base = number_of_fixed_symbols; for( ix = symbol_base; ix < symbol_top; ix++ ) { list_lineno++; page_lineno++; if( page_lineno >= LIST_LINES_PER_PAGE ) { topOfForm( list_title, s_xref ); } fprintf( listfile, "%5d", list_lineno ); /* Get reference count & index into concordance table for this symbol. */ xc_refcount = symtab[ix].xref_count; xc_index = symtab[ix].xref_index; /* Determine how to label symbol on concordance. */ switch( symtab[ix].type & ( DEFINED | REDEFINED )) { case UNDEFINED: fprintf( listfile, " U "); break; case REDEFINED: fprintf( listfile, " M %5d ", xreftab[xc_index] ); break; default: fprintf( listfile, " A %5d ", xreftab[xc_index] ); break; } fprintf( listfile, "%-6.6s ", symtab[ix].name ); /* Output the references, 8 numbers per line after symbol name. */ for( xc_cols = 0, xc = 1; xc < xc_refcount + 1; xc++, xc_cols++ ) { if( xc_cols >= XREF_COLUMNS ) { xc_cols = 0; page_lineno++; if( page_lineno >= LIST_LINES_PER_PAGE ) { topOfForm( list_title, s_xref); } list_lineno++; fprintf( listfile, "\n%5d%-19s", list_lineno, " " ); } fprintf( listfile, " %5d", xreftab[xc_index + xc] ); } fprintf( listfile, "\n" ); } } /* printCrossReference() */ /******************************************************************************/ /* */ /* Function: topOfForm */ /* */ /* Synopsis: Prints title and sub-title on top of next page of listing. */ /* */ /******************************************************************************/ void topOfForm( char *title, char *sub_title ) { char temp[10]; list_pageno++; strcpy( temp, s_page ); sprintf( temp, "%s %d", s_page, list_pageno ); /* Output a top of form if not the first page of the listing. */ if( list_pageno > 1 ) { fprintf( listfile, "\f" ); } fprintf( listfile, "\n\n\n %-63s %10s\n", title, temp ); /* Reset the current page line counter. */ page_lineno = 3; if( sub_title != NULL ) { fprintf( listfile, "%80s\n", sub_title ); page_lineno++; } else { fprintf( listfile, "\n" ); page_lineno++; } fprintf( listfile, "\n" ); page_lineno++; } /* topOfForm() */ /******************************************************************************/ /* */ /* Function: lexemeToName */ /* */ /* Synopsis: Convert the current lexeme into a string. */ /* */ /******************************************************************************/ char *lexemeToName( char *name, int from, int term ) { int to; to = 0; while( from < term && to < ( SYMLEN - 1 )) { name[to++] = toupper( line[from++] ); } while( to < SYMLEN ) { name[to++] = '\0'; } return( name ); } /* lexemeToName() */ /******************************************************************************/ /* */ /* Function: defineLexeme */ /* */ /* Synopsis: Put lexeme into symbol table with a value. */ /* */ /******************************************************************************/ SYM_T *defineLexeme( int start, /* start of lexeme being defined. */ int term, /* end+1 of lexeme being defined. */ WORD16 val, /* value of lexeme being defined. */ SYMTYP type ) /* how symbol is being defined. */ { char name[SYMLEN]; lexemeToName( name, start, term); return( defineSymbol( name, val, type, start )); } /* defineLexeme() */ /******************************************************************************/ /* */ /* Function: defineSymbol */ /* */ /* Synopsis: Define a symbol in the symbol table, enter symbol name if not */ /* not already in table. */ /* */ /******************************************************************************/ SYM_T *defineSymbol( char *name, WORD16 val, SYMTYP type, WORD16 start ) { SYM_T *sym; int xref_count; if( strlen( name ) < 1 ) { return( &sym_undefined ); /* Protect against non-existent names. */ } sym = lookup( name ); /* OS/8 PAL8 seems to allow permanent symbold to be redefined without error */ if( ( M_FIXED( sym->type ) && pass == 1 && perm_redef_error ) || (M_PERM_REDEFINED( sym->type ) && (sym->val != val)) ) { type |= PERM_REDEFINED; } xref_count = 0; /* Set concordance for normal defintion. */ if( M_DEFINED( sym->type )) { if( pass == 2 && ( (sym->val & 07777) != (val & 07777) || M_PERM_REDEFINED(sym->type)) ) { /* Generate diagnostic if redefining a symbol. */ if( M_PERM_REDEFINED( sym->type ) && (M_LABEL(sym->type) || M_LABEL(type)) ) { errorSymbol( &illegal_redefine, sym->name, start ); } else { /* Generate diagnostic if redefining a symbol. */ if( M_REDEFINED( sym->type ) && (M_LABEL(sym->type) || M_LABEL(type)) ) { errorSymbol( &redefined_symbol, sym->name, start ); } } type = type | REDEFINED; sym->xref_count++; /* Referenced suymbol, count it. */ xref_count = sym->xref_count; } } if( pass == 2 && xref ) { /* Put the definition line number in the concordance table. */ /* Defined symbols are not counted as references. */ xreftab[sym->xref_index] = lineno; /* Put the line number in the concordance table. */ xreftab[sym->xref_index + xref_count] = lineno; } /* Now set the value and the type. */ sym->val = ( M_LABEL(type) ) ? val : val & 07777; sym->type = ( pass == 1 ) ? ( type | CONDITION ) : type; return( sym ); } /* defineSymbol() */ /******************************************************************************/ /* */ /* Function: lookup */ /* */ /* Synopsis: Find a symbol in table. If not in table, enter symbol in */ /* table as undefined. Return address of symbol in table. */ /* */ /******************************************************************************/ SYM_T *lookup( char *name ) { int ix; /* Insertion index */ int lx; /* Left index */ int rx; /* Right index */ /* First search the permanent symbols. */ lx = 0; ix = binarySearch( name, lx, number_of_fixed_symbols ); /* If symbol not in permanent symbol table. */ if( ix < 0 ) { /* Now try the user symbol table. */ ix = binarySearch( name, number_of_fixed_symbols, symbol_top ); /* If symbol not in user symbol table. */ if( ix < 0 ) { /* Must put symbol in table if index is negative. */ ix = ~ix; if( symbol_top + 1 >= SYMBOL_TABLE_SIZE ) { errorSymbol( &symbol_table_full, name, lexstart ); exit( 1 ); } for( rx = symbol_top; rx >= ix; rx-- ) { symtab[rx + 1] = symtab[rx]; } symbol_top++; /* Enter the symbol as UNDEFINED with a value of zero. */ strcpy( symtab[ix].name, name ); symtab[ix].type = UNDEFINED; symtab[ix].val = 0; symtab[ix].xref_count = 0; if( xref && pass == 2 ) { xreftab[symtab[ix].xref_index] = 0; } } } return( &symtab[ix] ); /* Return the location of the symbol. */ } /* lookup() */ /******************************************************************************/ /* */ /* Function: binarySearch */ /* */ /* Synopsis: Searches the symbol table within the limits given. If the */ /* symbol is not in the table, it returns the insertion point. */ /* */ /******************************************************************************/ int binarySearch( char *name, int start, int symbol_count ) { int lx; /* Left index */ int mx; /* Middle index */ int rx; /* Right index */ int compare; /* Results of comparison */ lx = start; rx = symbol_count - 1; while( lx <= rx ) { mx = ( lx + rx ) / 2; /* Find center of search area. */ compare = strcmp( name, symtab[mx].name ); if( compare < 0 ) { rx = mx - 1; } else if( compare > 0 ) { lx = mx + 1; } else { return( mx ); /* Found a match in symbol table. */ } } /* end while */ return( ~lx ); /* Return insertion point. */ } /* binarySearch() */ /******************************************************************************/ /* */ /* Function: compareSymbols */ /* */ /* Synopsis: Used to presort the symbol table when starting assembler. */ /* */ /******************************************************************************/ int compareSymbols( const void *a, const void *b ) { return( strcmp( ((SYM_T *) a)->name, ((SYM_T *) b)->name )); } /* compareSymbols() */ /******************************************************************************/ /* */ /* Function: evalSymbol */ /* */ /* Synopsis: Get the pointer for the symbol table entry if exists. */ /* If symbol doesn't exist, return a pointer to the undefined sym */ /* */ /******************************************************************************/ SYM_T *evalSymbol() { char name[SYMLEN]; SYM_T *sym; sym = lookup( lexemeToName( name, lexstart, lexterm )); /* The symbol goes in the concordance iff it is in a different position in */ /* the assembler source file. */ if( lexstart != last_xref_lexstart || lineno != last_xref_lineno ) { sym->xref_count++; /* Count the number of references to symbol. */ last_xref_lexstart = lexstart; last_xref_lineno = lineno; /* Put the line number in the concordance table. */ if( xref && pass == 2 ) { xreftab[sym->xref_index + sym->xref_count] = lineno; } } return( sym ); } /* evalSymbol() */ /******************************************************************************/ /* */ /* Function: moveToEndOfLine */ /* */ /* Synopsis: Move the parser input to the end of the current input line. */ /* */ /******************************************************************************/ void moveToEndOfLine() { while( !isend( line[cc] )) cc++; lexstart = cc; lexterm = cc; lexstartprev = lexstart; } /* moveToEndOfLine() */ /******************************************************************************/ /* */ /* Function: nextLexeme */ /* */ /* Synopsis: Get the next lexical element from input line. */ /* */ /******************************************************************************/ void nextLexeme() { /* Save start column of previous lexeme for diagnostic messages. */ lexstartprev = lexstart; lextermprev = lexterm; while( is_blank( line[cc] )) { cc++; } lexstart = cc; if( isalnum( line[cc] )) { while( isalnum( line[cc] )) { cc++; } } else if( isend( line[cc] )) { /* End-of-Line, don't advance cc! */ } else { switch( line[cc] ) { case '"': /* Quoted letter */ if( cc + 2 < maxcc ) { cc++; cc++; } else { errorMessage( &no_literal_value, lexstart ); cc++; } break; case '/': /* Comment, don't advance cc! */ break; default: /* All other punctuation. */ cc++; break; } } lexterm = cc; } /* nextLexeme() */ /******************************************************************************/ /* */ /* Function: nextLexBlank */ /* */ /* Synopsis: Used to prevent illegal blanks in expressions. */ /* */ /******************************************************************************/ void nextLexBlank() { nextLexeme(); if( is_blank( delimiter )) { errorMessage( &illegal_blank, lexstart - 1 ); } delimiter = line[lexterm]; } /* nextLexBlank() */ /******************************************************************************/ /* */ /* Function: pseudoOperators */ /* */ /* Synopsis: Process pseudo-ops (directives). */ /* */ /******************************************************************************/ BOOL pseudoOperators( PSEUDO_T val ) { int count, count2; int delim; int index; int ix; int lexstartsave; WORD16 newfield; WORD16 oldclc; int pack; BOOL status; SYM_T *sym; FILE *temp; int term; WORD16 value; char os8_name[8]; int reloc_clc; status = TRUE; switch( (PSEUDO_T) val ) { case ASCII: /* added 18-Jan-2003 PNT -- derived from TEXT */ delim = line[lexstart]; index = lexstart + 1; while( line[index] != delim && !isend( line[index] )) { punchOutObject( clc, (line[index] & 127) | 128 ); incrementClc(); index++; } if( isend( line[index] )) { cc = index; lexterm = cc; errorMessage( &text_string, cc ); } else { cc = index + 1; lexterm = cc; } nextLexeme(); break; case BANK: errorSymbol( &no_pseudo_op, "BANK", lexstartprev ); /* should select a different 32K out of 128K */ break; case BINPUNCH: /* If there has been data output and this is a mode switch, set up to */ /* output data in BIN mode. */ if( binary_data_output && rim_mode ) { clearLiteralTable(); punchLeader( 8 ); /* Generate a short leader/trailer. */ checksum = 0; binary_data_output = FALSE; } rim_mode = FALSE; break; case DECIMAL: radix = 10; break; case DUBL: inputDubl(); break; case EJECT: page_lineno = LIST_LINES_PER_PAGE; /* This will force a page break. */ status = FALSE; /* This will force reading of next line */ break; case ENPUNCH: if( pass == 2 ) { objectfile = objectsave; } break; case EXPUNGE: /* Erase symbol table */ if( pass == 1 ) { symtab[0] = sym_undefined; symbol_top = 0; number_of_fixed_symbols = symbol_top; fixed_symbols = &symtab[symbol_top - 1]; /* Enter the pseudo-ops into the symbol table. */ for( ix = 0; ix < DIM( pseudo ); ix++ ) { defineSymbol( pseudo[ix].name, pseudo[ix].val, pseudo[ix].type, 0 ); } /* Enter the really permanent symbols into the table. */ /* Also make them part of the permanent symbol table. */ for( ix = 0; ix < DIM( really_permanent_symbols ); ix++ ) { defineSymbol( really_permanent_symbols[ix].name, really_permanent_symbols[ix].val, really_permanent_symbols[ix].type | DEFFIX , 0 ); } number_of_fixed_symbols = symbol_top; fixed_symbols = &symtab[symbol_top - 1]; } break; case FIELD: /* Punch page 0 also */ punchLiteralPool( cp, 1 ); newfield = field >> 12; lexstartsave = lexstartprev; if( isdone( line[lexstart] )) { newfield += 1; /* Blank FIELD directive. */ } else { newfield = (getExpr())->val; /* FIELD with argument. */ } if( rim_mode ) { errorMessage( &in_rim_mode, lexstartsave ); /* Can't change fields. */ } else if( newfield > 7 || newfield < 0 ) { errorMessage( &illegal_field_value, lexstartprev ); } else { value = (( newfield & 0007 ) << 3 ) | 00300; punchObject( value ); if( objectfile != NULL ) /* Only fix checksum if punching */ { checksum -= value; /* Field punches are not added to checksum. */ } field = newfield << 12; } clc = 0200 | field; fieldlc = clc & 07777; if( !rim_mode ) { punchOrigin( clc ); } clearLiteralTable(); break; case FIXMRI: if( line[lexterm] == '=' && isalpha( line[lexstart] )) { lexstartsave = lexstart; term = lexterm; nextLexeme(); /* Skip symbol. */ nextLexeme(); /* Skip trailing = */ defineLexeme( lexstartsave, term, getExprs(), MRI ); } else { errorLexeme( &symbol_syntax, lexstart ); nextLexeme(); /* Skip symbol. */ nextLexeme(); /* Skip trailing = */ (void) getExprs(); /* Skip expression. */ } break; case FIXTAB: if (pass == 1) /* Only fix on first pass, on second all are defined */ { /* Mark all current symbols as permanent symbols. */ for( ix = 0; ix < symbol_top; ix++ ) { symtab[ix].type = symtab[ix].type | FIXED; } number_of_fixed_symbols = symbol_top; fixed_symbols = &symtab[symbol_top - 1]; /* Re-sort the symbol table */ qsort( symtab, symbol_top, sizeof(symtab[0]), compareSymbols ); } break; case FLTG: inputFltg(); /* errorSymbol( &no_pseudo_op, "FLTG", lexstartprev ); */ break; case IFDEF: if( isalpha( line[lexstart] )) { sym = evalSymbol(); nextLexeme(); if( M_DEFINED_CONDITIONALLY( sym->type )) { conditionTrue(); } else { conditionFalse(); } } else { errorLexeme( &label_syntax, lexstart ); } break; case IFNDEF: if( isalpha( line[lexstart] )) { sym = evalSymbol(); nextLexeme(); if( M_DEFINED_CONDITIONALLY( sym->type )) { conditionFalse(); } else { conditionTrue(); } } else { errorLexeme( &label_syntax, lexstart ); } break; case IFNZERO: if( getExprs() == 0 ) { conditionFalse(); } else { conditionTrue(); } break; case IFZERO: if( getExprs() == 0 ) { conditionTrue(); } else { conditionFalse(); } break; case NOPUNCH: if( pass == 2 ) { objectfile = NULL; } break; case OCTAL: radix = 8; break; case PAGE: reloc_clc = clc + reloc; punchLiteralPool( cp, 0 ); oldclc = clc; if( isdone( line[lexstart] )) { clc = (( reloc_clc + 0177 ) & 077600) - reloc; /* No argumnet. */ fieldlc = clc & 07777; } else { value = (getExpr())->val; clc = field + (( value & 037 ) << 7 ) - reloc; fieldlc = clc & 07777; } testForLiteralCollision( clc + reloc ); if( !rim_mode && clc != oldclc ) { punchOrigin( clc ); } break; case PAUSE: break; case RELOC: if( isdone( line[lexstart] )) { reloc = 0; /* Blank RELOC directive. */ } else { value = (getExpr())->val; /* RELOC with argument. */ reloc = (value & 07777) - ( clc & 07777); } break; case RIMPUNCH: /* If the assembler has output any BIN data, output the literal tables */ /* and the checksum for what has been assembled and setup for RIM mode. */ if( binary_data_output && !rim_mode ) { endOfBinary(); clearLiteralTable(); punchChecksum(); punchLeader( 8 ); /* Generate a short leader/trailer. */ } rim_mode = TRUE; break; case SEGMNT: punchLiteralPool( cp, 0 ); if( isdone( line[lexstart] )) { /* No argument. */ clc = ( clc & 06000 ) + 02000; fieldlc = clc & 07777; } else { getExpr(); clc = ( val & 003 ) << 10; fieldlc = clc & 07777; } if( !rim_mode ) { punchOrigin( clc ); } testForLiteralCollision( clc ); break; case TEXT: delim = line[lexstart]; pack = 0; count = 0; index = lexstart + 1; while( line[index] != delim && !isend( line[index] )) { pack = ( pack << 6 ) | ( line[index] & 077 ); count++; if( count > 1 ) { punchOutObject( clc, pack ); incrementClc(); count = 0; pack = 0; } index++; } if( count != 0 ) { punchOutObject( clc, pack << 6 ); incrementClc(); } else { punchOutObject( clc, 0 ); incrementClc(); } if( isend( line[index] )) { cc = index; lexterm = cc; errorMessage( &text_string, cc ); } else { cc = index + 1; lexterm = cc; } nextLexeme(); break; case FILENAME: memset(os8_name, 0, sizeof(os8_name)); delimiter=line[lexstart]; if (delimiter != '.') { for (index = lexstart, count = 0; index < lexterm && count < 6; index++) { os8_name[count++] = line[index]; } delimiter=line[lexterm]; if (delimiter == '.') { nextLexeme(); /* Skip . */ } } nextLexeme(); if (delimiter == '.') { for (index = lexstart, count = 6; index < lexterm && count < 8; index++) { os8_name[count++] = line[index]; } } pack = 0; count = 0; for (count2 = 0; count2 < 8; count2++) { pack = ( pack << 6 ) | ( os8_name[count2] & 077 ); count++; if( count > 1 ) { punchOutObject( clc, pack ); incrementClc(); count = 0; pack = 0; } } nextLexeme(); break; case DEVICE: memset(os8_name, 0, sizeof(os8_name)); for (index = lexstart, count = 0; index < lexterm && count < 4; index++) { os8_name[count++] = line[index]; } pack = 0; count = 0; for (count2 = 0; count2 < 4; count2++) { pack = ( pack << 6 ) | ( os8_name[count2] & 077 ); count++; if( count > 1 ) { punchOutObject( clc, pack ); incrementClc(); count = 0; pack = 0; } } nextLexeme(); break; case TITLE: delim = line[lexstart]; ix = lexstart + 1; /* Find string delimiter. */ do { if( list_title[ix] == delim && list_title[ix + 1] == delim ) { ix++; } ix++; } while( line[ix] != delim && !isend(line[ix]) ); if( line[ix] == delim ) { count = 0; ix = lexstart + 1; do { if( list_title[ix] == delim && list_title[ix + 1] == delim ) { ix++; } list_title[count] = line[ix]; count++; ix++; list_title[count] = '\0'; } while( line[ix] != delim && !isend(line[ix]) ); if( strlen( list_title ) > TITLELEN ) { list_title[TITLELEN] = '\0'; } cc = ix + 1; lexterm = cc; page_lineno = LIST_LINES_PER_PAGE;/* Force top of page for new titles. */ list_title_set = TRUE; } else { cc = ix; lexterm = cc; errorMessage( &text_string, cc ); } nextLexeme(); break; case XLIST: if( isdone( line[lexstart] )) { temp = listfile; /* Blank XLIST directive. */ listfile = listsave; listsave = temp; } else { if( (getExpr())->val == 0 ) { if( listfile == NULL ) { listfile = listsave; listsave = NULL; } } else { if( listfile != NULL ) { listsave = listfile; listfile = NULL; } } } break; case ZBLOCK: value = (getExpr())->val; if( value < 0 ) { errorMessage( &zblock_too_small, lexstartprev ); } else if( value + ( clc & 07777 ) - 1 > 07777 ) { errorMessage( &zblock_too_large, lexstartprev ); } else { for( ; value > 0; value-- ) { punchOutObject( clc, 0 ); incrementClc(); } } break; default: break; } /* end switch for pseudo-ops */ return( status ); } /* pseudoOperators() */ /******************************************************************************/ /* */ /* Function: conditionFalse */ /* */ /* Synopsis: Called when a false conditional has been evaluated. */ /* Lex should be the opening <; ignore all text until */ /* the closing >. */ /* */ /******************************************************************************/ void conditionFalse() { int level; if( line[lexstart] == '<' ) { /* Invariant: line[cc] is the next unexamined character. */ level = 1; while( level > 0 ) { if( isend( line[cc] )) { readLine(); } else { switch( line[cc] ) { case '>': level--; cc++; break; case '<': level++; cc++; break; case '$': level = 0; cc++; break; default: cc++; break; } /* end switch */ } /* end if */ } /* end while */ nextLexeme(); } else { errorMessage( <_expected, lexstart ); } } /* conditionFalse() */ /******************************************************************************/ /* */ /* Function: conditionTrue */ /* */ /* Synopsis: Called when a true conditional has been evaluated. */ /* Lex should be the opening <; skip it and setup for */ /* normal assembly. */ /* */ /******************************************************************************/ void conditionTrue() { if( line[lexstart] == '<' ) { nextLexeme(); /* Skip the opening '<' */ } else { errorMessage( <_expected, lexstart ); } } /* conditionTrue() */ /******************************************************************************/ /* */ /* Function: errorLexeme */ /* */ /* Synopsis: Display an error message using the current lexical element. */ /* */ /******************************************************************************/ void errorLexeme( EMSG_T *mesg, int col ) { char name[SYMLEN]; errorSymbol( mesg, lexemeToName( name, lexstart, lexterm ), col ); } /* errorLexeme() */ /******************************************************************************/ /* */ /* Function: errorSymbol */ /* */ /* Synopsis: Display an error message with a given string. */ /* */ /******************************************************************************/ void errorSymbol( EMSG_T *mesg, char *name, int col ) { char linecol[12]; char *s; if( pass == 2 ) { s = ( name == NULL ) ? "" : name ; errors++; sprintf( linecol, "(%d:%d)", lineno, col + 1 ); fprintf( errorfile, "%s%-9s : error: %s \"%s\" at Loc = %5.5o\n", filename, linecol, mesg->file, s, clc ); saveError( mesg->list, col ); } error_in_line = TRUE; } /* errorSymbol() */ /******************************************************************************/ /* */ /* Function: errorMessage */ /* */ /* Synopsis: Display an error message without a name argument. */ /* */ /******************************************************************************/ void errorMessage( EMSG_T *mesg, int col ) { char linecol[12]; if( pass == 2 ) { errors++; sprintf( linecol, "(%d:%d)", lineno, col + 1 ); fprintf( errorfile, "%s%-9s : error: %s at Loc = %5.5o\n", filename, linecol, mesg->file, clc ); saveError( mesg->list, col ); } error_in_line = TRUE; } /* errorMessage() */ /******************************************************************************/ /* */ /* Function: saveError */ /* */ /* Synopsis: Save the current error in a list so it may displayed after the */ /* the current line is printed. */ /* */ /******************************************************************************/ void saveError( char *mesg, int col ) { if( save_error_count < DIM( error_list )) { error_list[save_error_count].mesg = mesg; error_list[save_error_count].col = col; save_error_count++; } error_in_line = TRUE; if( listed ) { printErrorMessages(); } } /* saveError() */ /* End-of-File */ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | # schofield-brtval.R: Generate SVG graph of the brightness curves # produced by Ian Schofield's ILS patch. # # The schofield-brtval.svg file checked into Fossil is modified from the # version output by this program: # # 1. The colors are modified to match the scheme on tangentsoft.com/pidp8i # # 2. The data line thickness was increased # # 3. The data lines were smoothed by Inkscape's "simplify" function # # Copyright © 2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above shall # not be used in advertising or otherwise to promote the sale, use or other # dealings in this Software without prior written authorization from those # authors. # min = 0 max = 32 a = min b = max rising = c(min); falling = c(max); for (i in 1:400) { a = a + (max - a) * 0.01 b = b + (min - b) * 0.01 rising[i] = a falling[i] = b if (a > 31 || b < 1) break } data = data.frame(Rising = rising, Falling = falling) dts = ts(data) svg("schofield-brtval.svg", width=8, height=6) plot.ts(dts, plot.type='single', ylab='Brightness', yaxp=c(min, max, 8)) dev.off() |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="576pt" height="396.73468pt" viewBox="0 0 576 396.73468" version="1.1" id="svg4276" inkscape:version="0.91 r13725" sodipodi:docname="schofield-brtval.svg"> <title id="title4481">Schofield ILS Brightness Curves</title> <metadata id="metadata267"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title>Schofield ILS Brightness Curves</dc:title> <cc:license rdf:resource="https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md" /> <dc:date>2017-02-02</dc:date> <dc:creator> <cc:Agent> <dc:title>Warren Young</dc:title> </cc:Agent> </dc:creator> <dc:language>English</dc:language> <dc:description>Curves showing the brightness levels of an LED driven from 0 to full brightness and from full brightness back to 0 under Ian Schofield's indandescent lamp simulator for the PiDP-8/I.</dc:description> </cc:Work> </rdf:RDF> </metadata> <sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="2560" inkscape:window-height="1391" id="namedview4548" showgrid="false" inkscape:zoom="1.6333333" inkscape:cx="360" inkscape:cy="253.95917" inkscape:window-x="0" inkscape:window-y="1" inkscape:window-maximized="1" inkscape:current-layer="svg4276" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" /> <defs id="defs4278"> <g id="g4280"> <symbol overflow="visible" id="glyph0-0" style="overflow:visible"> <path style="stroke:none" d="m 0.390625,0 0,-8.609375 6.828125,0 0,8.609375 z m 5.75,-1.078125 0,-6.453125 -4.671875,0 0,6.453125 z" id="path4283" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph0-1" style="overflow:visible"> <path style="stroke:none" d="m 7.171875,-8.609375 0,1.03125 -2.890625,0 0,7.578125 -1.1875,0 0,-7.578125 -2.90625,0 0,-1.03125 z" id="path4286" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph0-2" style="overflow:visible"> <path style="stroke:none" d="m 0.78125,-6.25 1.0625,0 0,6.25 -1.0625,0 z m 0,-2.359375 1.0625,0 0,1.203125 -1.0625,0 z" id="path4289" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph0-3" style="overflow:visible"> <path style="stroke:none" d="m 0.78125,-6.28125 1.03125,0 0,0.890625 C 2.0625,-5.691406 2.289062,-5.914062 2.5,-6.0625 c 0.34375,-0.238281 0.738281,-0.359375 1.1875,-0.359375 0.5,0 0.898438,0.125 1.203125,0.375 0.164063,0.136719 0.320313,0.34375 0.46875,0.625 0.226563,-0.34375 0.5,-0.59375 0.8125,-0.75 0.320313,-0.164063 0.679687,-0.25 1.078125,-0.25 0.84375,0 1.414062,0.308594 1.71875,0.921875 0.164062,0.324219 0.25,0.765625 0.25,1.328125 L 9.21875,0 8.125,0 l 0,-4.359375 C 8.125,-4.773438 8.019531,-5.0625 7.8125,-5.21875 7.601562,-5.375 7.347656,-5.453125 7.046875,-5.453125 c -0.417969,0 -0.777344,0.140625 -1.078125,0.421875 -0.292969,0.273438 -0.4375,0.730469 -0.4375,1.375 l 0,3.65625 -1.078125,0 0,-4.09375 c 0,-0.425781 -0.054687,-0.738281 -0.15625,-0.9375 C 4.140625,-5.320312 3.84375,-5.46875 3.40625,-5.46875 3.007812,-5.46875 2.644531,-5.3125 2.3125,-5 1.988281,-4.695312 1.828125,-4.140625 1.828125,-3.328125 L 1.828125,0 0.78125,0 Z" id="path4292" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph0-4" style="overflow:visible"> <path style="stroke:none" d="m 3.390625,-6.421875 c 0.445313,0 0.878906,0.105469 1.296875,0.3125 0.414062,0.210937 0.734375,0.480469 0.953125,0.8125 0.207031,0.324219 0.347656,0.695313 0.421875,1.109375 0.0625,0.292969 0.09375,0.757812 0.09375,1.390625 l -4.609375,0 C 1.566406,-2.160156 1.71875,-1.648438 2,-1.265625 2.28125,-0.878906 2.71875,-0.6875 3.3125,-0.6875 c 0.550781,0 0.988281,-0.179688 1.3125,-0.546875 C 4.8125,-1.441406 4.945312,-1.6875 5.03125,-1.96875 l 1.03125,0 C 6.039062,-1.738281 5.953125,-1.484375 5.796875,-1.203125 5.640625,-0.921875 5.46875,-0.6875 5.28125,-0.5 4.957031,-0.1875 4.554688,0.0195312 4.078125,0.125 3.828125,0.1875 3.539062,0.21875 3.21875,0.21875 2.4375,0.21875 1.773438,-0.0625 1.234375,-0.625 c -0.542969,-0.570312 -0.8125,-1.367188 -0.8125,-2.390625 0,-1.007813 0.269531,-1.828125 0.8125,-2.453125 0.550781,-0.632812 1.269531,-0.953125 2.15625,-0.953125 z M 5.0625,-3.640625 C 5.019531,-4.097656 4.921875,-4.460938 4.765625,-4.734375 4.484375,-5.242188 4.003906,-5.5 3.328125,-5.5 2.835938,-5.5 2.425781,-5.320312 2.09375,-4.96875 1.769531,-4.625 1.597656,-4.179688 1.578125,-3.640625 Z m -1.78125,-2.78125 z" id="path4295" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph0-5" style="overflow:visible"> <path style="stroke:none" d="m 3.25,-8.390625 c 1.082031,0 1.867188,0.449219 2.359375,1.34375 0.375,0.6875 0.5625,1.636719 0.5625,2.84375 C 6.171875,-3.066406 6,-2.125 5.65625,-1.375 5.164062,-0.300781 4.359375,0.234375 3.234375,0.234375 c -1,0 -1.75,-0.4375 -2.25,-1.3125 C 0.578125,-1.816406 0.375,-2.800781 0.375,-4.03125 c 0,-0.945312 0.125,-1.765625 0.375,-2.453125 0.457031,-1.269531 1.289062,-1.90625 2.5,-1.90625 z m -0.015625,7.65625 c 0.550781,0 0.988281,-0.238281 1.3125,-0.71875 0.320313,-0.488281 0.484375,-1.394531 0.484375,-2.71875 0,-0.945313 -0.121094,-1.726563 -0.359375,-2.34375 C 4.441406,-7.128906 3.988281,-7.4375 3.3125,-7.4375 c -0.625,0 -1.085938,0.292969 -1.375,0.875 -0.28125,0.585938 -0.421875,1.445312 -0.421875,2.578125 0,0.855469 0.09375,1.542969 0.28125,2.0625 0.28125,0.792969 0.757813,1.1875 1.4375,1.1875 z" id="path4298" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph0-6" style="overflow:visible"> <path style="stroke:none" d="m 1.484375,-2.140625 c 0.070313,0.605469 0.351563,1.023437 0.84375,1.25 0.25,0.117187 0.535156,0.171875 0.859375,0.171875 0.625,0 1.085938,-0.195312 1.390625,-0.59375 C 4.878906,-1.707031 5.03125,-2.148438 5.03125,-2.640625 5.03125,-3.222656 4.847656,-3.675781 4.484375,-4 4.128906,-4.320312 3.703125,-4.484375 3.203125,-4.484375 c -0.367187,0 -0.679687,0.074219 -0.9375,0.21875 C 2.003906,-4.128906 1.785156,-3.9375 1.609375,-3.6875 L 0.6875,-3.734375 1.328125,-8.25 l 4.359375,0 0,1.015625 -3.5625,0 -0.359375,2.328125 c 0.195313,-0.144531 0.382813,-0.253906 0.5625,-0.328125 0.3125,-0.125 0.671875,-0.1875 1.078125,-0.1875 0.769531,0 1.421875,0.25 1.953125,0.75 0.539063,0.492187 0.8125,1.117187 0.8125,1.875 0,0.792969 -0.25,1.496094 -0.75,2.109375 -0.492187,0.6054688 -1.273437,0.90625 -2.34375,0.90625 -0.679687,0 -1.28125,-0.1953125 -1.8125,-0.578125 -0.523437,-0.382813 -0.8125,-0.976563 -0.875,-1.78125 z" id="path4301" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph0-7" style="overflow:visible"> <path style="stroke:none" d="m 1.15625,-5.9375 0,-0.8125 c 0.757812,-0.070312 1.285156,-0.195312 1.578125,-0.375 0.300781,-0.175781 0.53125,-0.585938 0.6875,-1.234375 l 0.828125,0 L 4.25,0 3.125,0 l 0,-5.9375 z" id="path4304" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph0-8" style="overflow:visible"> <path style="stroke:none" d="M 0.375,0 C 0.414062,-0.71875 0.566406,-1.34375 0.828125,-1.875 1.085938,-2.414062 1.59375,-2.90625 2.34375,-3.34375 L 3.46875,-4 c 0.5,-0.289062 0.851562,-0.539062 1.0625,-0.75 0.320312,-0.320312 0.484375,-0.691406 0.484375,-1.109375 0,-0.488281 -0.152344,-0.875 -0.453125,-1.15625 -0.292969,-0.289063 -0.679688,-0.4375 -1.15625,-0.4375 -0.730469,0 -1.230469,0.273437 -1.5,0.8125 -0.15625,0.304687 -0.242188,0.710937 -0.25,1.21875 l -1.078125,0 c 0.007813,-0.726563 0.144531,-1.320313 0.40625,-1.78125 0.457031,-0.8125 1.265625,-1.21875 2.421875,-1.21875 0.957031,0 1.65625,0.261719 2.09375,0.78125 0.445312,0.523437 0.671875,1.101563 0.671875,1.734375 0,0.667969 -0.234375,1.242188 -0.703125,1.71875 C 5.195312,-3.90625 4.707031,-3.566406 4,-3.171875 l -0.8125,0.4375 C 2.8125,-2.523438 2.515625,-2.320312 2.296875,-2.125 1.898438,-1.789062 1.648438,-1.414062 1.546875,-1 l 4.59375,0 0,1 z" id="path4307" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph0-9" style="overflow:visible"> <path style="stroke:none" d="m 3.125,0.234375 c -1,0 -1.726562,-0.2695312 -2.171875,-0.8125 -0.449219,-0.550781 -0.671875,-1.21875 -0.671875,-2 l 1.109375,0 c 0.039063,0.542969 0.140625,0.9375 0.296875,1.1875 0.28125,0.4375 0.773438,0.65625 1.484375,0.65625 0.5625,0 1.007813,-0.144531 1.34375,-0.4375 0.332031,-0.300781 0.5,-0.6875 0.5,-1.15625 0,-0.570313 -0.179687,-0.972656 -0.53125,-1.203125 -0.355469,-0.238281 -0.84375,-0.359375 -1.46875,-0.359375 -0.074219,0 -0.148437,0.00781 -0.21875,0.015625 -0.074219,0 -0.148437,0 -0.21875,0 l 0,-0.9375 c 0.113281,0.023438 0.207031,0.03125 0.28125,0.03125 0.070313,0 0.148437,0 0.234375,0 0.394531,0 0.71875,-0.0625 0.96875,-0.1875 C 4.507812,-5.1875 4.734375,-5.578125 4.734375,-6.140625 4.734375,-6.554688 4.582031,-6.875 4.28125,-7.09375 3.988281,-7.320312 3.644531,-7.4375 3.25,-7.4375 c -0.699219,0 -1.183594,0.234375 -1.453125,0.703125 -0.148437,0.25 -0.230469,0.617187 -0.25,1.09375 l -1.046875,0 c 0,-0.625 0.125,-1.15625 0.375,-1.59375 0.425781,-0.78125 1.179688,-1.171875 2.265625,-1.171875 0.851563,0 1.515625,0.195312 1.984375,0.578125 0.46875,0.375 0.703125,0.929687 0.703125,1.65625 0,0.511719 -0.136719,0.929687 -0.40625,1.25 -0.179687,0.199219 -0.402344,0.355469 -0.671875,0.46875 0.4375,0.125 0.78125,0.359375 1.03125,0.703125 0.25,0.34375 0.375,0.765625 0.375,1.265625 0,0.804687 -0.265625,1.460937 -0.796875,1.96875 -0.523437,0.5 -1.265625,0.75 -2.234375,0.75 z" id="path4310" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-0" style="overflow:visible"> <path style="stroke:none" d="m 0,-0.390625 -8.609375,0 0,-6.828125 8.609375,0 z m -1.078125,-5.75 -6.453125,0 0,4.671875 6.453125,0 z" id="path4313" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-1" style="overflow:visible"> <path style="stroke:none" d="m -4.96875,-4.15625 c 0,-0.488281 -0.066406,-0.867188 -0.203125,-1.140625 -0.21875,-0.425781 -0.601563,-0.640625 -1.15625,-0.640625 -0.5625,0 -0.941406,0.230469 -1.140625,0.6875 -0.113281,0.25 -0.171875,0.632812 -0.171875,1.140625 l 0,2.078125 2.671875,0 z M -1,-4.546875 c 0,-0.707031 -0.207031,-1.21875 -0.625,-1.53125 -0.257812,-0.1875 -0.570312,-0.28125 -0.9375,-0.28125 -0.625,0 -1.050781,0.28125 -1.28125,0.84375 -0.125,0.292969 -0.1875,0.683594 -0.1875,1.171875 l 0,2.3125 3.03125,0 z m -7.609375,3.65625 0,-3.6875 c 0,-1.007813 0.304687,-1.726563 0.90625,-2.15625 0.355469,-0.25 0.765625,-0.375 1.234375,-0.375 0.542969,0 0.984375,0.15625 1.328125,0.46875 0.1875,0.15625 0.355469,0.386719 0.5,0.6875 0.167969,-0.4375 0.359375,-0.765625 0.578125,-0.984375 0.375,-0.394531 0.890625,-0.59375 1.546875,-0.59375 0.554687,0 1.054687,0.179688 1.5,0.53125 C -0.335938,-6.476562 0,-5.65625 0,-4.53125 l 0,3.640625 z" id="path4316" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-2" style="overflow:visible"> <path style="stroke:none" d="m -6.28125,-0.796875 0,-1.015625 1.09375,0 c -0.21875,-0.070312 -0.476562,-0.269531 -0.78125,-0.59375 -0.300781,-0.320312 -0.453125,-0.691406 -0.453125,-1.109375 0,-0.019531 0.00781,-0.050781 0.015625,-0.09375 0,-0.050781 0.00781,-0.132813 0.015625,-0.25 l 1.109375,0 c -0.00781,0.0625 -0.015625,0.121094 -0.015625,0.171875 0,0.054688 0,0.109375 0,0.171875 0,0.53125 0.171875,0.945313 0.515625,1.234375 0.335938,0.28125 0.726562,0.421875 1.171875,0.421875 l 3.609375,0 0,1.0625 z" id="path4319" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-3" style="overflow:visible"> <path style="stroke:none" d="m -6.25,-0.78125 0,-1.0625 6.25,0 0,1.0625 z m -2.359375,0 0,-1.0625 1.203125,0 0,1.0625 z" id="path4322" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-4" style="overflow:visible"> <path style="stroke:none" d="m -6.390625,-2.984375 c 0,-0.5 0.121094,-0.929687 0.359375,-1.296875 0.148438,-0.195312 0.351562,-0.398438 0.609375,-0.609375 l -0.796875,0 0,-0.96875 5.703125,0 c 0.800781,0 1.429687,0.117187 1.890625,0.34375 0.851562,0.4375 1.28125,1.265625 1.28125,2.484375 0,0.679688 -0.152344,1.246094 -0.453125,1.703125 -0.304687,0.460937 -0.777344,0.71875 -1.421875,0.78125 l 0,-1.078125 c 0.28125,-0.050781 0.5,-0.148438 0.65625,-0.296875 0.226562,-0.238281 0.34375,-0.613281 0.34375,-1.125 0,-0.8125 -0.289062,-1.34375 -0.859375,-1.59375 C 0.585938,-4.785156 -0.0078125,-4.851562 -0.875,-4.84375 c 0.324219,0.210938 0.5625,0.464844 0.71875,0.765625 0.15625,0.292969 0.234375,0.683594 0.234375,1.171875 0,0.679688 -0.238281,1.273438 -0.71875,1.78125 -0.488281,0.511719 -1.289063,0.765625 -2.40625,0.765625 -1.050781,0 -1.867187,-0.253906 -2.453125,-0.765625 -0.59375,-0.519531 -0.890625,-1.140625 -0.890625,-1.859375 z m 3.21875,-1.90625 c -0.769531,0 -1.34375,0.164063 -1.71875,0.484375 -0.375,0.324219 -0.5625,0.730469 -0.5625,1.21875 0,0.75 0.351563,1.261719 1.046875,1.53125 0.367188,0.148438 0.851562,0.21875 1.453125,0.21875 0.710937,0 1.25,-0.140625 1.625,-0.421875 0.367187,-0.289063 0.546875,-0.679687 0.546875,-1.171875 0,-0.757812 -0.34375,-1.289062 -1.03125,-1.59375 -0.382812,-0.175781 -0.835938,-0.265625 -1.359375,-0.265625 z m -3.25,1.78125 z" id="path4325" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-5" style="overflow:visible"> <path style="stroke:none" d="m -8.640625,-0.78125 0,-1.046875 3.21875,0 C -5.742188,-2.078125 -5.96875,-2.300781 -6.09375,-2.5 -6.3125,-2.84375 -6.421875,-3.269531 -6.421875,-3.78125 c 0,-0.90625 0.320313,-1.519531 0.953125,-1.84375 0.34375,-0.175781 0.824219,-0.265625 1.4375,-0.265625 l 4.03125,0 0,1.078125 -3.953125,0 c -0.457031,0 -0.796875,0.0625 -1.015625,0.1875 -0.34375,0.1875 -0.515625,0.546875 -0.515625,1.078125 0,0.4375 0.152344,0.835937 0.453125,1.1875 0.304688,0.355469 0.871094,0.53125 1.703125,0.53125 l 3.328125,0 0,1.046875 z" id="path4328" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-6" style="overflow:visible"> <path style="stroke:none" d="m -8.03125,-0.984375 0,-1.0625 1.75,0 0,-1 0.859375,0 0,1 4.109375,0 c 0.21875,0 0.367188,-0.078125 0.4375,-0.234375 0.042969,-0.070312 0.0625,-0.207031 0.0625,-0.40625 0,-0.050781 0,-0.101562 0,-0.15625 -0.007812,-0.0625 -0.015625,-0.128906 -0.015625,-0.203125 l 0.828125,0 c 0.03125,0.117187 0.0507812,0.242187 0.0625,0.375 0.0195312,0.125 0.03125,0.265625 0.03125,0.421875 0,0.492188 -0.125,0.824219 -0.375,1 -0.25,0.179688 -0.578125,0.265625 -0.984375,0.265625 l -4.15625,0 0,0.84375 -0.859375,0 0,-0.84375 z" id="path4331" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-7" style="overflow:visible"> <path style="stroke:none" d="m -6.28125,-0.78125 0,-1 0.890625,0 c -0.363281,-0.289062 -0.625,-0.601562 -0.78125,-0.9375 -0.164063,-0.332031 -0.25,-0.703125 -0.25,-1.109375 0,-0.882813 0.3125,-1.484375 0.9375,-1.796875 0.34375,-0.175781 0.828125,-0.265625 1.453125,-0.265625 l 4.03125,0 0,1.078125 -3.953125,0 c -0.382813,0 -0.691406,0.058594 -0.921875,0.171875 -0.394531,0.1875 -0.59375,0.527344 -0.59375,1.015625 0,0.25 0.027344,0.453125 0.078125,0.609375 0.085937,0.292969 0.257813,0.546875 0.515625,0.765625 0.210938,0.179688 0.421875,0.292969 0.640625,0.34375 0.21875,0.054688 0.539063,0.078125 0.953125,0.078125 l 3.28125,0 0,1.046875 z M -6.421875,-3.25 Z" id="path4334" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-8" style="overflow:visible"> <path style="stroke:none" d="m -6.421875,-3.390625 c 0,-0.445313 0.105469,-0.878906 0.3125,-1.296875 0.210937,-0.414062 0.480469,-0.734375 0.8125,-0.953125 0.324219,-0.207031 0.695313,-0.347656 1.109375,-0.421875 0.292969,-0.0625 0.757812,-0.09375 1.390625,-0.09375 l 0,4.609375 C -2.160156,-1.566406 -1.648438,-1.71875 -1.265625,-2 -0.878906,-2.28125 -0.6875,-2.71875 -0.6875,-3.3125 c 0,-0.550781 -0.179688,-0.988281 -0.546875,-1.3125 C -1.441406,-4.8125 -1.6875,-4.945312 -1.96875,-5.03125 l 0,-1.03125 c 0.230469,0.023438 0.484375,0.109375 0.765625,0.265625 0.28125,0.15625 0.515625,0.328125 0.703125,0.515625 0.3125,0.324219 0.5195312,0.726562 0.625,1.203125 0.0625,0.25 0.09375,0.539063 0.09375,0.859375 0,0.78125 -0.28125,1.445312 -0.84375,1.984375 -0.570312,0.542969 -1.367188,0.8125 -2.390625,0.8125 -1.007813,0 -1.828125,-0.269531 -2.453125,-0.8125 -0.632812,-0.550781 -0.953125,-1.269531 -0.953125,-2.15625 z m 2.78125,-1.671875 c -0.457031,0.042969 -0.820313,0.140625 -1.09375,0.296875 -0.507813,0.28125 -0.765625,0.761719 -0.765625,1.4375 0,0.492187 0.179688,0.902344 0.53125,1.234375 0.34375,0.324219 0.789062,0.496094 1.328125,0.515625 z m -2.78125,1.78125 z" id="path4337" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-9" style="overflow:visible"> <path style="stroke:none" d="m -1.96875,-1.40625 c 0.355469,-0.03125 0.625,-0.117188 0.8125,-0.265625 0.335938,-0.257813 0.5,-0.71875 0.5,-1.375 0,-0.394531 -0.082031,-0.738281 -0.25,-1.03125 -0.164062,-0.300781 -0.425781,-0.453125 -0.78125,-0.453125 -0.269531,0 -0.476562,0.121094 -0.625,0.359375 -0.082031,0.15625 -0.179688,0.460937 -0.296875,0.90625 L -2.8125,-2.421875 C -2.945312,-1.890625 -3.097656,-1.5 -3.265625,-1.25 c -0.28125,0.460938 -0.675781,0.6875 -1.1875,0.6875 -0.59375,0 -1.070313,-0.210938 -1.4375,-0.640625 C -6.253906,-1.628906 -6.4375,-2.207031 -6.4375,-2.9375 c 0,-0.9375 0.277344,-1.613281 0.828125,-2.03125 0.355469,-0.269531 0.734375,-0.398438 1.140625,-0.390625 l 0,1 c -0.238281,0.023437 -0.457031,0.105469 -0.65625,0.25 -0.269531,0.242187 -0.40625,0.664063 -0.40625,1.265625 0,0.398438 0.078125,0.699219 0.234375,0.90625 0.148437,0.199219 0.34375,0.296875 0.59375,0.296875 0.273437,0 0.492187,-0.132813 0.65625,-0.40625 0.09375,-0.15625 0.179687,-0.382813 0.25,-0.6875 l 0.171875,-0.6875 c 0.1875,-0.757813 0.367188,-1.269531 0.53125,-1.53125 0.273438,-0.40625 0.699219,-0.609375 1.28125,-0.609375 0.554688,0 1.03125,0.214844 1.4375,0.640625 0.40625,0.417969 0.609375,1.058594 0.609375,1.921875 0,0.9375 -0.2109375,1.605469 -0.625,2 -0.425781,0.386719 -0.953125,0.589844 -1.578125,0.609375 z m -4.453125,-1.546875 z" id="path4340" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-10" style="overflow:visible"> <path style="stroke:none" d="m -8.390625,-3.25 c 0,-1.082031 0.449219,-1.867188 1.34375,-2.359375 0.6875,-0.375 1.636719,-0.5625 2.84375,-0.5625 1.136719,0 2.078125,0.171875 2.828125,0.515625 1.074219,0.492188 1.609375,1.296875 1.609375,2.421875 0,1 -0.4375,1.75 -1.3125,2.25 -0.738281,0.40625 -1.722656,0.609375 -2.953125,0.609375 -0.945312,0 -1.765625,-0.125 -2.453125,-0.375 -1.269531,-0.457031 -1.90625,-1.289062 -1.90625,-2.5 z m 7.65625,0.015625 c 0,-0.550781 -0.238281,-0.988281 -0.71875,-1.3125 -0.488281,-0.320313 -1.394531,-0.484375 -2.71875,-0.484375 -0.945313,0 -1.726563,0.121094 -2.34375,0.359375 -0.613281,0.230469 -0.921875,0.683594 -0.921875,1.359375 0,0.625 0.292969,1.085938 0.875,1.375 0.585938,0.28125 1.445312,0.421875 2.578125,0.421875 0.855469,0 1.542969,-0.09375 2.0625,-0.28125 0.792969,-0.28125 1.1875,-0.757813 1.1875,-1.4375 z" id="path4343" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-11" style="overflow:visible"> <path style="stroke:none" d="m -2.96875,-3.96875 -3.8125,0 3.8125,2.6875 z M 0,-3.984375 l -2.046875,0 0,3.671875 -1.03125,0 -5.34375,-3.84375 0,-0.890625 5.453125,0 0,-1.234375 0.921875,0 0,1.234375 2.046875,0 z" id="path4346" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-12" style="overflow:visible"> <path style="stroke:none" d="m -4.875,-3.265625 c 0,-0.46875 -0.128906,-0.832031 -0.390625,-1.09375 C -5.523438,-4.617188 -5.832031,-4.75 -6.1875,-4.75 c -0.3125,0 -0.597656,0.125 -0.859375,0.375 -0.269531,0.25 -0.40625,0.632812 -0.40625,1.140625 0,0.511719 0.136719,0.882813 0.40625,1.109375 0.261719,0.230469 0.5625,0.34375 0.90625,0.34375 0.398437,0 0.710937,-0.144531 0.9375,-0.4375 0.21875,-0.300781 0.328125,-0.648438 0.328125,-1.046875 z m 4.15625,-0.0625 c 0,-0.488281 -0.128906,-0.894531 -0.390625,-1.21875 -0.269531,-0.320313 -0.664063,-0.484375 -1.1875,-0.484375 -0.539063,0 -0.953125,0.167969 -1.234375,0.5 -0.28125,0.335938 -0.421875,0.761719 -0.421875,1.28125 0,0.5 0.148437,0.914062 0.4375,1.234375 0.28125,0.3125 0.679687,0.46875 1.1875,0.46875 0.4375,0 0.820313,-0.144531 1.140625,-0.4375 0.3125,-0.289063 0.46875,-0.738281 0.46875,-1.34375 z m -3.75,1.5 c -0.125,0.292969 -0.269531,0.523437 -0.4375,0.6875 -0.3125,0.304687 -0.71875,0.453125 -1.21875,0.453125 -0.625,0 -1.160156,-0.222656 -1.609375,-0.671875 -0.457031,-0.457031 -0.6875,-1.097656 -0.6875,-1.921875 0,-0.8125 0.214844,-1.441406 0.640625,-1.890625 0.429688,-0.457031 0.921875,-0.6875 1.484375,-0.6875 0.523437,0 0.949219,0.132813 1.28125,0.390625 0.179687,0.148438 0.355469,0.375 0.53125,0.6875 0.15625,-0.34375 0.339844,-0.613281 0.546875,-0.8125 0.398438,-0.375 0.90625,-0.5625 1.53125,-0.5625 0.742188,0 1.367188,0.25 1.875,0.75 0.5117188,0.492188 0.765625,1.1875 0.765625,2.09375 0,0.824219 -0.21875,1.515625 -0.65625,2.078125 -0.445313,0.5625 -1.09375,0.84375 -1.9375,0.84375 -0.488281,0 -0.914063,-0.117187 -1.28125,-0.359375 -0.363281,-0.238281 -0.640625,-0.597656 -0.828125,-1.078125 z" id="path4349" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-13" style="overflow:visible"> <path style="stroke:none" d="m -5.9375,-1.15625 -0.8125,0 c -0.070312,-0.757812 -0.195312,-1.285156 -0.375,-1.578125 -0.175781,-0.300781 -0.585938,-0.53125 -1.234375,-0.6875 l 0,-0.828125 8.359375,0 0,1.125 -5.9375,0 z" id="path4352" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-14" style="overflow:visible"> <path style="stroke:none" d="M 0,-0.375 C -0.71875,-0.414062 -1.34375,-0.566406 -1.875,-0.828125 -2.414062,-1.085938 -2.90625,-1.59375 -3.34375,-2.34375 L -4,-3.46875 c -0.289062,-0.5 -0.539062,-0.851562 -0.75,-1.0625 -0.320312,-0.320312 -0.691406,-0.484375 -1.109375,-0.484375 -0.488281,0 -0.875,0.152344 -1.15625,0.453125 -0.289063,0.292969 -0.4375,0.679688 -0.4375,1.15625 0,0.730469 0.273437,1.230469 0.8125,1.5 0.304687,0.15625 0.710937,0.242188 1.21875,0.25 l 0,1.078125 c -0.726563,-0.007813 -1.320313,-0.144531 -1.78125,-0.40625 -0.8125,-0.457031 -1.21875,-1.265625 -1.21875,-2.421875 0,-0.957031 0.261719,-1.65625 0.78125,-2.09375 0.523437,-0.445312 1.101563,-0.671875 1.734375,-0.671875 0.667969,0 1.242188,0.234375 1.71875,0.703125 0.28125,0.273438 0.621094,0.761719 1.015625,1.46875 l 0.4375,0.8125 c 0.210937,0.375 0.414063,0.671875 0.609375,0.890625 0.335938,0.398437 0.710938,0.648437 1.125,0.75 l 0,-4.59375 1,0 z" id="path4355" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-15" style="overflow:visible"> <path style="stroke:none" d="m -8.421875,-3.515625 c 0,-0.9375 0.246094,-1.585937 0.734375,-1.953125 0.480469,-0.375 0.980469,-0.5625 1.5,-0.5625 l 0,1.046875 c -0.332031,0.0625 -0.59375,0.164063 -0.78125,0.296875 C -7.320312,-4.425781 -7.5,-4.039062 -7.5,-3.53125 c 0,0.59375 0.277344,1.070312 0.828125,1.421875 0.542969,0.34375 1.320313,0.53125 2.328125,0.5625 -0.351562,-0.238281 -0.617188,-0.539063 -0.796875,-0.90625 -0.15625,-0.332031 -0.234375,-0.707031 -0.234375,-1.125 0,-0.707031 0.226562,-1.320313 0.671875,-1.84375 0.449219,-0.519531 1.121094,-0.78125 2.015625,-0.78125 0.761719,0 1.4375,0.25 2.03125,0.75 0.5859375,0.492187 0.875,1.195313 0.875,2.109375 0,0.792969 -0.296875,1.476562 -0.890625,2.046875 -0.601563,0.5625 -1.609375,0.84375 -3.015625,0.84375 -1.039062,0 -1.925781,-0.125 -2.65625,-0.375 -1.382812,-0.488281 -2.078125,-1.382813 -2.078125,-2.6875 z M -0.71875,-3.4375 c 0,-0.550781 -0.1875,-0.960938 -0.5625,-1.234375 -0.375,-0.28125 -0.816406,-0.421875 -1.328125,-0.421875 -0.425781,0 -0.832031,0.125 -1.21875,0.375 -0.382813,0.242188 -0.578125,0.6875 -0.578125,1.34375 0,0.449219 0.152344,0.84375 0.453125,1.1875 0.292969,0.34375 0.742187,0.515625 1.34375,0.515625 0.53125,0 0.980469,-0.15625 1.34375,-0.46875 0.367187,-0.3125 0.546875,-0.742187 0.546875,-1.296875 z" id="path4358" inkscape:connector-curvature="0" /> </symbol> <symbol overflow="visible" id="glyph1-16" style="overflow:visible"> <path style="stroke:none" d="m 0.234375,-3.125 c 0,1 -0.2695312,1.726562 -0.8125,2.171875 -0.550781,0.449219 -1.21875,0.671875 -2,0.671875 l 0,-1.109375 c 0.542969,-0.039063 0.9375,-0.140625 1.1875,-0.296875 0.4375,-0.28125 0.65625,-0.773438 0.65625,-1.484375 0,-0.5625 -0.144531,-1.007813 -0.4375,-1.34375 -0.300781,-0.332031 -0.6875,-0.5 -1.15625,-0.5 -0.570313,0 -0.972656,0.179687 -1.203125,0.53125 -0.238281,0.355469 -0.359375,0.84375 -0.359375,1.46875 0,0.074219 0.00781,0.148437 0.015625,0.21875 0,0.074219 0,0.148437 0,0.21875 l -0.9375,0 c 0.023438,-0.113281 0.03125,-0.207031 0.03125,-0.28125 0,-0.070313 0,-0.148437 0,-0.234375 0,-0.394531 -0.0625,-0.71875 -0.1875,-0.96875 -0.21875,-0.445312 -0.609375,-0.671875 -1.171875,-0.671875 -0.414063,0 -0.734375,0.152344 -0.953125,0.453125 -0.226562,0.292969 -0.34375,0.636719 -0.34375,1.03125 0,0.699219 0.234375,1.183594 0.703125,1.453125 0.25,0.148437 0.617187,0.230469 1.09375,0.25 l 0,1.046875 c -0.625,0 -1.15625,-0.125 -1.59375,-0.375 -0.78125,-0.425781 -1.171875,-1.179688 -1.171875,-2.265625 0,-0.851563 0.195312,-1.515625 0.578125,-1.984375 0.375,-0.46875 0.929687,-0.703125 1.65625,-0.703125 0.511719,0 0.929687,0.136719 1.25,0.40625 0.199219,0.179687 0.355469,0.402344 0.46875,0.671875 0.125,-0.4375 0.359375,-0.78125 0.703125,-1.03125 0.34375,-0.25 0.765625,-0.375 1.265625,-0.375 0.804687,0 1.460937,0.265625 1.96875,0.796875 0.5,0.523437 0.75,1.265625 0.75,2.234375 z" id="path4361" inkscape:connector-curvature="0" /> </symbol> </g> </defs> <rect id="rect4364" style="fill:#fff3df;fill-opacity:1;stroke:none" height="396.73468" width="576" y="0" x="0" /> <path style="fill:none;stroke:#45873b;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" d="M 88.266406,310.63218 C 122.02676,237.79712 168.07359,167.7088 234.99687,121.36656 298.00502,77.074005 374.52101,57.963738 449.84844,47.956407 c 29.57913,-3.956704 59.3163,-6.634684 89.08593,-8.656254" id="path4366" inkscape:connector-curvature="0" /> <path style="fill:none;stroke:#95473f;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" d="M 88.266406,33.300157 C 122.02506,106.13557 168.07177,176.22644 234.99687,222.56578 c 63.74354,44.80848 141.26877,63.83721 217.47266,73.75781 28.71422,3.77216 57.57485,6.34594 86.46484,8.31216" id="path4368" inkscape:connector-curvature="0" /> <g id="g4370" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-41.632655)"> <use height="100%" width="100%" id="use4372" y="413.28125" x="289.06641" xlink:href="#glyph0-1" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4374" y="413.28125" x="296.39648" xlink:href="#glyph0-2" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4376" y="413.28125" x="299.0625" xlink:href="#glyph0-3" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4378" y="413.28125" x="309.05859" xlink:href="#glyph0-4" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4380" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4382" y="237.14844" x="12.960938" xlink:href="#glyph1-1" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4384" y="229.14453" x="12.960938" xlink:href="#glyph1-2" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4386" y="225.14844" x="12.960938" xlink:href="#glyph1-3" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4388" y="222.48242" x="12.960938" xlink:href="#glyph1-4" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4390" y="215.80859" x="12.960938" xlink:href="#glyph1-5" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4392" y="209.13477" x="12.960938" xlink:href="#glyph1-6" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4394" y="205.80078" x="12.960938" xlink:href="#glyph1-7" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4396" y="199.12695" x="12.960938" xlink:href="#glyph1-8" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4398" y="192.45312" x="12.960938" xlink:href="#glyph1-9" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4400" y="186.45312" x="12.960938" xlink:href="#glyph1-9" style="fill:#5d4734;fill-opacity:1" /> </g> <path inkscape:connector-curvature="0" id="path4402" d="m 86.957812,321.72593 458.527348,0" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4404" d="m 86.957812,321.72593 0,7.20313" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4406" d="m 152.46172,321.72593 0,7.20313" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4408" d="m 217.96562,321.72593 0,7.20313" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4410" d="m 283.46953,321.72593 0,7.20313" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4412" d="m 348.97344,321.72593 0,7.20313" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4414" d="m 414.47734,321.72593 0,7.20313" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4416" d="m 479.98125,321.72593 0,7.20313" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4418" d="m 545.48516,321.72593 0,7.20313" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <g id="g4420" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4422" y="384.48047" x="72.421875" xlink:href="#glyph0-5" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4424" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4426" y="384.48047" x="134.58984" xlink:href="#glyph0-6" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4428" y="384.48047" x="141.26367" xlink:href="#glyph0-5" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4430" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4432" y="384.48047" x="196.75391" xlink:href="#glyph0-7" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4434" y="384.48047" x="203.42773" xlink:href="#glyph0-5" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4436" y="384.48047" x="210.10156" xlink:href="#glyph0-5" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4438" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4440" y="384.48047" x="262.25781" xlink:href="#glyph0-7" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4442" y="384.48047" x="268.93164" xlink:href="#glyph0-6" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4444" y="384.48047" x="275.60547" xlink:href="#glyph0-5" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4446" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4448" y="384.48047" x="327.76172" xlink:href="#glyph0-8" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4450" y="384.48047" x="334.43555" xlink:href="#glyph0-5" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4452" y="384.48047" x="341.10938" xlink:href="#glyph0-5" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4454" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4456" y="384.48047" x="393.26562" xlink:href="#glyph0-8" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4458" y="384.48047" x="399.93945" xlink:href="#glyph0-6" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4460" y="384.48047" x="406.61328" xlink:href="#glyph0-5" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4462" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4464" y="384.48047" x="458.76953" xlink:href="#glyph0-9" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4466" y="384.48047" x="465.44336" xlink:href="#glyph0-5" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4468" y="384.48047" x="472.11719" xlink:href="#glyph0-5" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4470" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4472" y="384.48047" x="524.27344" xlink:href="#glyph0-9" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4474" y="384.48047" x="530.94727" xlink:href="#glyph0-6" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4476" y="384.48047" x="537.62109" xlink:href="#glyph0-5" style="fill:#5d4734;fill-opacity:1" /> </g> <path inkscape:connector-curvature="0" id="path4478" d="m 70.239062,313.46421 0,-282.992177" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4480" d="m 70.239062,313.46421 -7.199218,0" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4482" d="m 70.239062,278.08921 -7.199218,0" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4484" d="m 70.239062,242.71421 -7.199218,0" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4486" d="m 70.239062,207.34312 -7.199218,0" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4488" d="m 70.239062,171.96812 -7.199218,0" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4490" d="m 70.239062,136.59312 -7.199218,0" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4492" d="m 70.239062,101.21812 -7.199218,0" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4494" d="m 70.239062,65.843125 -7.199218,0" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4496" d="m 70.239062,30.472033 -7.199218,0" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> <g id="g4498" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4500" y="353.63281" x="41.761719" xlink:href="#glyph1-10" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4502" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4504" y="318.25781" x="41.761719" xlink:href="#glyph1-11" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4506" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4508" y="282.88281" x="41.761719" xlink:href="#glyph1-12" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4510" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4512" y="250.84766" x="41.761719" xlink:href="#glyph1-13" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4514" y="244.17383" x="41.761719" xlink:href="#glyph1-14" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4516" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4518" y="215.47266" x="41.761719" xlink:href="#glyph1-13" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4520" y="208.79883" x="41.761719" xlink:href="#glyph1-15" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4522" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4524" y="180.09766" x="41.761719" xlink:href="#glyph1-14" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4526" y="173.42383" x="41.761719" xlink:href="#glyph1-10" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4528" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4530" y="144.72266" x="41.761719" xlink:href="#glyph1-14" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4532" y="138.04883" x="41.761719" xlink:href="#glyph1-11" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4534" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4536" y="109.34766" x="41.761719" xlink:href="#glyph1-14" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4538" y="102.67383" x="41.761719" xlink:href="#glyph1-12" style="fill:#5d4734;fill-opacity:1" /> </g> <g id="g4540" style="fill:#5d4734;fill-opacity:1" transform="translate(11.2,-36.832655)"> <use height="100%" width="100%" id="use4542" y="73.976562" x="41.761719" xlink:href="#glyph1-16" style="fill:#5d4734;fill-opacity:1" /> <use height="100%" width="100%" id="use4544" y="67.302734" x="41.761719" xlink:href="#glyph1-14" style="fill:#5d4734;fill-opacity:1" /> </g> <path inkscape:connector-curvature="0" id="path4546" d="m 70.239062,321.72593 486.722658,0 0,-299.519523 -486.722658,0 0,299.519523" style="fill:none;stroke:#5d4734;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /> </svg> |
cannot compute difference between binary files
cannot compute difference between binary files
cannot compute difference between binary files
cannot compute difference between binary files
cannot compute difference between binary files
cannot compute difference between binary files
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | ######################################################################## # Makefile.in - Processed by autosetup's configure script to generate # an intermediate GNU make(1) file for building the PiDP-8/I software # from within its src/ subdirectory. # # The resulting Makefile will redirect simple "make" calls to the top # level as well as the major top-level targets (e.g. "make clean") but # purposefully will not redirect anything like an installation or "run # the system" type target. Its only purpose is to help out those who # are working on the PiDP-8/I project's C source code from within this # directory. If you need to work on the wider system, do it from the # project's top level. # # If you are seeing this at the top of a file called Makefile and you # intend to make edits, do that in Makefile.in. Saying "make" will then # re-build Makefile from that modified Makefile.in before proceeding to # do the "make" operation. # # Copyright © 2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## all clean ctags distclean tags reconfig: cd @builddir@; make $@ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | ######################################################################## # Makefile.in - Processed by autosetup's configure script to generate # an intermediate GNU make(1) file for building the PiDP-8/I software # from within its src/PDP8 subdirectory. # # The resulting Makefile will redirect simple "make" calls to the top # level as well as the major top-level targets (e.g. "make clean") but # purposefully will not redirect anything like an installation or "run # the system" type target. Its only purpose is to help out those who # are working on the PiDP-8/I project's C source code from within this # directory. If you need to work on the wider system, do it from the # project's top level. # # If you are seeing this at the top of a file called Makefile and you # intend to make edits, do that in Makefile.in. Saying "make" will then # re-build Makefile from that modified Makefile.in before proceeding to # do the "make" operation. # # Copyright © 2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## all clean ctags distclean tags reconfig: cd @builddir@; make $@ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | /* pdp8_clk.c: PDP-8 real-time clock simulator Copyright (c) 1993-2012, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. clk real time clock 18-Apr-12 RMS Added clock coscheduling 18-Jun-07 RMS Added UNIT_IDLE flag 01-Mar-03 RMS Aded SET/SHOW CLK FREQ support 04-Oct-02 RMS Added DIB, device number support 30-Dec-01 RMS Removed for generalized timers 05-Sep-01 RMS Added terminal multiplexor support 17-Jul-01 RMS Moved function prototype 05-Mar-01 RMS Added clock calibration support Note: includes the IOT's for both the PDP-8/E and PDP-8/A clocks */ #include "pdp8_defs.h" extern int32 int_req, int_enable, dev_done, stop_inst; int32 clk_tps = 60; /* ticks/second */ int32 tmxr_poll = 16000; /* term mux poll */ int32 clk (int32 IR, int32 AC); t_stat clk_svc (UNIT *uptr); t_stat clk_reset (DEVICE *dptr); t_stat clk_set_freq (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, CONST void *desc); /* CLK data structures clk_dev CLK device descriptor clk_unit CLK unit descriptor clk_reg CLK register list */ DIB clk_dib = { DEV_CLK, 1, { &clk } }; UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE, 0), 16000 }; REG clk_reg[] = { { FLDATAD (DONE, dev_done, INT_V_CLK, "device done flag") }, { FLDATAD (ENABLE, int_enable, INT_V_CLK, "interrupt enable flag") }, { FLDATAD (INT, int_req, INT_V_CLK, "interrupt pending flag") }, { DRDATAD (TIME, clk_unit.wait, 24, "clock interval"), REG_NZ + PV_LEFT }, { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, { NULL } }; MTAB clk_mod[] = { { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", &clk_set_freq, NULL, NULL }, { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", &clk_set_freq, NULL, NULL }, { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, NULL, &clk_show_freq, NULL }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, { 0 } }; DEVICE clk_dev = { "CLK", &clk_unit, clk_reg, clk_mod, 1, 0, 0, 0, 0, 0, NULL, NULL, &clk_reset, NULL, NULL, NULL, &clk_dib, 0 }; /* IOT routine IOT's 6131-6133 are the PDP-8/E clock IOT's 6135-6137 are the PDP-8/A clock */ int32 clk (int32 IR, int32 AC) { switch (IR & 07) { /* decode IR<9:11> */ case 1: /* CLEI */ int_enable = int_enable | INT_CLK; /* enable clk ints */ int_req = INT_UPDATE; /* update interrupts */ return AC; case 2: /* CLDI */ int_enable = int_enable & ~INT_CLK; /* disable clk ints */ int_req = int_req & ~INT_CLK; /* update interrupts */ return AC; case 3: /* CLSC */ if (dev_done & INT_CLK) { /* flag set? */ dev_done = dev_done & ~INT_CLK; /* clear flag */ int_req = int_req & ~INT_CLK; /* clear int req */ return IOT_SKP + AC; } return AC; case 5: /* CLLE */ if (AC & 1) /* test AC<11> */ int_enable = int_enable | INT_CLK; else int_enable = int_enable & ~INT_CLK; int_req = INT_UPDATE; /* update interrupts */ return AC; case 6: /* CLCL */ dev_done = dev_done & ~INT_CLK; /* clear flag */ int_req = int_req & ~INT_CLK; /* clear int req */ return AC; case 7: /* CLSK */ return (dev_done & INT_CLK)? IOT_SKP + AC: AC; default: return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ } /* Unit service */ t_stat clk_svc (UNIT *uptr) { dev_done = dev_done | INT_CLK; /* set done */ int_req = INT_UPDATE; /* update interrupts */ tmxr_poll = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */ sim_activate_after (uptr, 1000000/clk_tps); /* reactivate unit */ return SCPE_OK; } /* Reset routine */ t_stat clk_reset (DEVICE *dptr) { dev_done = dev_done & ~INT_CLK; /* clear done, int */ int_req = int_req & ~INT_CLK; int_enable = int_enable & ~INT_CLK; /* clear enable */ if (!sim_is_running) { /* RESET (not CAF)? */ tmxr_poll = sim_rtcn_init_unit (&clk_unit, clk_unit.wait, TMR_CLK);/* init 100Hz timer */ sim_activate_after (&clk_unit, 1000000/clk_tps); /* activate 100Hz unit */ } return SCPE_OK; } /* Set frequency */ t_stat clk_set_freq (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { if (cptr) return SCPE_ARG; if ((val != 50) && (val != 60)) return SCPE_IERR; clk_tps = val; return SCPE_OK; } /* Show frequency */ t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { fprintf (st, (clk_tps == 50)? "50Hz": "60Hz"); return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 | /* pdp8_cpu.c: PDP-8 CPU simulator Copyright (c) 1993-2017, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. ---------------------------------------------------------------------------- Portions copyright (c) 2015-2017, Oscar Vermeulen and Warren Young Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the names of the authors above shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from those authors. ---------------------------------------------------------------------------- cpu central processor 09-Mar-17 RMS Fixed PCQ_ENTRY for interrupts (COVERITY) 13-Feb-17 RMS RESET clear L'AC, per schematics 28-Jan-17 RMS Renamed switch register variable to SR, per request 18-Sep-16 RMS Added alternate dispatch table for non-contiguous devices 17-Sep-13 RMS Fixed boot in wrong field problem (Dave Gesswein) 28-Apr-07 RMS Removed clock initialization 30-Oct-06 RMS Added idle and infinite loop detection 30-Sep-06 RMS Fixed SC value after DVI overflow (Don North) 22-Sep-05 RMS Fixed declarations (Sterling Garwood) 16-Aug-05 RMS Fixed C++ declaration and cast problems 06-Nov-04 RMS Added =n to SHOW HISTORY 31-Dec-03 RMS Fixed bug in set_cpu_hist 13-Oct-03 RMS Added instruction history Added TSC8-75 support (Bernhard Baehr) 12-Mar-03 RMS Added logical name support 04-Oct-02 RMS Revamped device dispatching, added device number support 06-Jan-02 RMS Added device enable/disable routines 30-Dec-01 RMS Added old PC queue 16-Dec-01 RMS Fixed bugs in EAE 07-Dec-01 RMS Revised to use new breakpoint package 30-Nov-01 RMS Added RL8A, extended SET/SHOW support 16-Sep-01 RMS Fixed bug in reset routine, added KL8A support 10-Aug-01 RMS Removed register from declarations 17-Jul-01 RMS Moved function prototype 07-Jun-01 RMS Fixed bug in JMS to non-existent memory 25-Apr-01 RMS Added device enable/disable support 18-Mar-01 RMS Added DF32 support 05-Mar-01 RMS Added clock calibration support 15-Feb-01 RMS Added DECtape support 14-Apr-99 RMS Changed t_addr to unsigned The register state for the PDP-8 is: AC<0:11> accumulator MQ<0:11> multiplier-quotient L link flag PC<0:11> program counter IF<0:2> instruction field IB<0:2> instruction buffer DF<0:2> data field UF user flag UB user buffer SF<0:6> interrupt save field The PDP-8 has three instruction formats: memory reference, I/O transfer, and operate. The memory reference format is: 0 1 2 3 4 5 6 7 8 9 10 11 +--+--+--+--+--+--+--+--+--+--+--+--+ | op |in|zr| page offset | memory reference +--+--+--+--+--+--+--+--+--+--+--+--+ <0:2> mnemonic action 000 AND AC = AC & M[MA] 001 TAD L'AC = AC + M[MA] 010 DCA M[MA] = AC, AC = 0 011 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 100 JMS M[MA] = PC, PC = MA + 1 101 JMP PC = MA <3:4> mode action 00 page zero MA = IF'0'IR<5:11> 01 current page MA = IF'PC<0:4>'IR<5:11> 10 indirect page zero MA = xF'M[IF'0'IR<5:11>] 11 indirect current page MA = xF'M[IF'PC<0:4>'IR<5:11>] where x is D for AND, TAD, ISZ, DCA, and I for JMS, JMP. Memory reference instructions can access an address space of 32K words. The address space is divided into eight 4K word fields; each field is divided into thirty-two 128 word pages. An instruction can directly address, via its 7b offset, locations 0-127 on page zero or on the current page. All 32k words can be accessed via indirect addressing and the instruction and data field registers. If an indirect address is in locations 0010-0017 of any field, the indirect address is incremented and rewritten to memory before use. The I/O transfer format is as follows: 0 1 2 3 4 5 6 7 8 9 10 11 +--+--+--+--+--+--+--+--+--+--+--+--+ | op | device | pulse | I/O transfer +--+--+--+--+--+--+--+--+--+--+--+--+ The IO transfer instruction sends the the specified pulse to the specified I/O device. The I/O device may take data from the AC, return data to the AC, initiate or cancel operations, or skip on status. The operate format is as follows: +--+--+--+--+--+--+--+--+--+--+--+--+ | 1| 1| 1| 0| | | | | | | | | operate group 1 +--+--+--+--+--+--+--+--+--+--+--+--+ | | | | | | | | | | | | | | | +--- increment AC 3 | | | | | | +--- rotate 1 or 2 4 | | | | | +--- rotate left 4 | | | | +--- rotate right 4 | | | +--- complement L 2 | | +--- complement AC 2 | +--- clear L 1 +-- clear AC 1 +--+--+--+--+--+--+--+--+--+--+--+--+ | 1| 1| 1| 1| | | | | | | | 0| operate group 2 +--+--+--+--+--+--+--+--+--+--+--+--+ | | | | | | | | | | | | | +--- halt 3 | | | | | +--- or switch register 3 | | | | +--- reverse skip sense 1 | | | +--- skip on L != 0 1 | | +--- skip on AC == 0 1 | +--- skip on AC < 0 1 +-- clear AC 2 +--+--+--+--+--+--+--+--+--+--+--+--+ | 1| 1| 1| 1| | | | | | | | 1| operate group 3 +--+--+--+--+--+--+--+--+--+--+--+--+ | | | | \______/ | | | | | | | +--|-----+--- EAE command 3 | | +--- AC -> MQ, 0 -> AC 2 | +--- MQ v AC --> AC 2 +-- clear AC 1 The operate instruction can be microprogrammed to perform operations on the AC, MQ, and link. This routine is the instruction decode routine for the PDP-8. It is called from the simulator control program to execute instructions in simulated memory, starting at the simulated PC. It runs until 'reason' is set non-zero. General notes: 1. Reasons to stop. The simulator can be stopped by: HALT instruction breakpoint encountered unimplemented instruction and stop_inst flag set I/O error in I/O simulator 2. Interrupts. Interrupts are maintained by three parallel variables: dev_done device done flags int_enable interrupt enable flags int_req interrupt requests In addition, int_req contains the interrupt enable flag, the CIF not pending flag, and the ION not pending flag. If all three of these flags are set, and at least one interrupt request is set, then an interrupt occurs. 3. Non-existent memory. On the PDP-8, reads to non-existent memory return zero, and writes are ignored. In the simulator, the largest possible memory is instantiated and initialized to zero. Thus, only writes outside the current field (indirect writes) need be checked against actual memory size. 3. Adding I/O devices. These modules must be modified: pdp8_defs.h add device number and interrupt definitions pdp8_sys.c add sim_devices table entry */ /* ---PiDP change------------------------------------------------------------------------------------------- */ #include "gpio-common.h" #include "pidp8i.h" /* ---PiDP end---------------------------------------------------------------------------------------------- */ #define PCQ_SIZE 64 /* must be 2**n */ #define PCQ_MASK (PCQ_SIZE - 1) #define PCQ_ENTRY(x) pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = x #define UNIT_V_NOEAE (UNIT_V_UF) /* EAE absent */ #define UNIT_NOEAE (1 << UNIT_V_NOEAE) #define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */ #define UNIT_MSIZE (1 << UNIT_V_MSIZE) #define OP_KSF 06031 /* for idle */ #define HIST_PC 0x40000000 #define HIST_MIN 64 #define HIST_MAX 65536 typedef struct { int32 pc; int32 ea; int16 ir; int16 opnd; int16 lac; int16 mq; } InstHistory; uint16 M[MAXMEMSIZE] = { 0 }; /* main memory */ int32 saved_LAC = 0; /* saved L'AC */ int32 saved_MQ = 0; /* saved MQ */ int32 saved_PC = 0; /* saved IF'PC */ int32 saved_DF = 0; /* saved Data Field */ int32 IB = 0; /* Instruction Buffer */ int32 SF = 0; /* Save Field */ int32 emode = 0; /* EAE mode */ int32 gtf = 0; /* EAE gtf flag */ int32 SC = 0; /* EAE shift count */ int32 UB = 0; /* User mode Buffer */ int32 UF = 0; /* User mode Flag */ int32 SR = 0; /* Switch Register */ int32 tsc_ir = 0; /* TSC8-75 IR */ int32 tsc_pc = 0; /* TSC8-75 PC */ int32 tsc_cdf = 0; /* TSC8-75 CDF flag */ int32 tsc_enb = 0; /* TSC8-75 enabled */ int32 cpu_astop = 0; /* address stop */ int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ int32 pcq_p = 0; /* PC queue ptr */ REG *pcq_r = NULL; /* PC queue reg ptr */ int32 dev_done = 0; /* dev done flags */ int32 int_enable = INT_INIT_ENABLE; /* intr enables */ int32 int_req = 0; /* intr requests */ int32 stop_inst = 0; /* trap on ill inst */ int32 (*dev_tab[DEV_MAX])(int32 IR, int32 dat); /* device dispatch */ int32 hst_p = 0; /* history pointer */ int32 hst_lnt = 0; /* history length */ InstHistory *hst = NULL; /* instruction history */ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_reset (DEVICE *dptr); t_stat cpu_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_bool build_dev_tab (void); /* CPU data structures cpu_dev CPU device descriptor cpu_unit CPU unit descriptor cpu_reg CPU register list cpu_mod CPU modifier list */ UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) }; REG cpu_reg[] = { { ORDATAD (PC, saved_PC, 15, "program counter") }, { ORDATAD (AC, saved_LAC, 12, "accumulator") }, { FLDATAD (L, saved_LAC, 12, "link") }, { ORDATAD (MQ, saved_MQ, 12, "multiplier-quotient") }, { ORDATAD (SR, SR, 12, "front panel switches") }, { GRDATAD (IF, saved_PC, 8, 3, 12, "instruction field") }, { GRDATAD (DF, saved_DF, 8, 3, 12, "data field") }, { GRDATAD (IB, IB, 8, 3, 12, "instruction field buffter") }, { ORDATAD (SF, SF, 7, "save field") }, { FLDATAD (UB, UB, 0, "user mode buffer") }, { FLDATAD (UF, UF, 0, "user mode flag") }, { ORDATAD (SC, SC, 5, "EAE shift counter") }, { FLDATAD (GTF, gtf, 0, "EAE greater than flag") }, { FLDATAD (EMODE, emode, 0, "EAE mode (0 = A, 1 = B)") }, { FLDATAD (ION, int_req, INT_V_ION, "interrupt enable") }, { FLDATAD (ION_DELAY, int_req, INT_V_NO_ION_PENDING, "interrupt enable delay for ION") }, { FLDATAD (CIF_DELAY, int_req, INT_V_NO_CIF_PENDING, "interrupt enable delay for CIF") }, { FLDATAD (PWR_INT, int_req, INT_V_PWR, "power fail interrupt") }, { FLDATAD (UF_INT, int_req, INT_V_UF, "user mode violation interrupt") }, { ORDATAD (INT, int_req, INT_V_ION+1, "interrupt pending flags"), REG_RO }, { ORDATAD (DONE, dev_done, INT_V_DIRECT, "device done flags"), REG_RO }, { ORDATAD (ENABLE, int_enable, INT_V_DIRECT, "device interrupt enable flags"), REG_RO }, { BRDATAD (PCQ, pcq, 8, 15, PCQ_SIZE, "PC prior to last JMP, JMS, or interrupt; most recent PC change first"), REG_RO+REG_CIRC }, { ORDATA (PCQP, pcq_p, 6), REG_HRO }, { FLDATAD (STOP_INST, stop_inst, 0, "stop on undefined instruction") }, { ORDATAD (WRU, sim_int_char, 8, "interrupt character") }, { NULL } }; MTAB cpu_mod[] = { { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL }, { UNIT_NOEAE, 0, "EAE", "EAE", NULL }, { MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle }, { MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL }, { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size }, { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size }, { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", &cpu_set_hist, &cpu_show_hist }, { 0 } }; DEVICE cpu_dev = { "CPU", &cpu_unit, cpu_reg, cpu_mod, 1, 8, 15, 1, 8, 12, &cpu_ex, &cpu_dep, &cpu_reset, NULL, NULL, NULL, NULL, 0 }; t_stat sim_instr (void) { int32 IR, MB, IF, DF, LAC, MQ; uint32 PC, MA; int32 device, pulse, temp, iot_data; t_stat reason; /* Restore register state */ if (build_dev_tab ()) /* build dev_tab */ return SCPE_STOP; PC = saved_PC & 007777; /* load local copies */ IF = saved_PC & 070000; DF = saved_DF & 070000; LAC = saved_LAC & 017777; MQ = saved_MQ & 07777; int_req = INT_UPDATE; reason = 0; /* ---PiDP add--------------------------------------------------------------------------------------------- */ // PiDP-8/I specific flag, set when the last instruction was an IOT // instruction to a real device. SIMH doesn't track this, but the front // panel needs it. int Pause = 0; // Set our initial IPS value from the throttle, if given. static time_t last_update = 0; static size_t max_skips = 0; static const size_t pidp8i_updates_per_sec = 3200; max_skips = get_pidp8i_initial_max_skips (pidp8i_updates_per_sec); srand48 (time (&last_update)); // Reset display info in case we're re-entering the simulator from Ctrl-E extern display display_bufs[2]; memset (display_bufs, 0, sizeof(display_bufs)); static size_t skip_count, dither, inst_count; skip_count = dither = inst_count = 0; /* ---PiDP end---------------------------------------------------------------------------------------------- */ /* Main instruction fetch/decode loop */ while (reason == 0) { /* loop until halted */ // Allow clean exit to SCP: https://github.com/simh/simh/issues/387 if (cpu_astop != 0) { cpu_astop = 0; reason = SCPE_STOP; break; } if (sim_interval <= 0) { /* check clock queue */ if ((reason = sim_process_event ())) { /* ---PiDP add--------------------------------------------------------------------------------------------- */ // We're about to leave the loop, so repaint one last time // in case this is a Ctrl-E and we later get a "cont" // command. Set a flag that will let us auto-resume. extern int resumeFromInstructionLoopExit, swStop, swSingInst; resumeFromInstructionLoopExit = swStop = swSingInst = 1; set_pidp8i_leds (PC, MA, MB, IR, LAC, MQ, IF, DF, SC, int_req, Pause); // Also copy SR hardware value to software register in case // the user tries poking at it from the sim> prompt. SR = get_switch_register(); /* ---PiDP end---------------------------------------------------------------------------------------------- */ break; } } /* ---PiDP add--------------------------------------------------------------------------------------------- */ switch (handle_flow_control_switches(M, &PC, &MA, &MB, &LAC, &IF, &DF, &int_req)) { case pft_stop: // Tell the SIMH event queue to keep running even though // we're stopped. Without this, it will ignore Ctrl-E // until the simulator is back in free-running mode. sim_interval = sim_interval - 1; // Have to keep display updated while stopped. This does // mean if the software starts with the STOP switch held // down, we'll put garbage onto the display for MA, MB, and // IR, but that's what the real hardware does, too. See // https://github.com/simh/simh/issues/386 set_pidp8i_leds (PC, MA, MB, IR, LAC, MQ, IF, DF, SC, int_req, Pause); // Go no further in STOP mode. In particular, fetch no more // instructions, and do not touch PC! continue; case pft_halt: // Clear all registers and halt simulator PC = saved_PC = 0; IF = saved_PC = 0; DF = saved_DF = 0; LAC = saved_LAC = 0; MQ = saved_MQ = 0; int_req = 0; reason = STOP_HALT; continue; case pft_normal: // execute normally break; } /* ---PiDP end---------------------------------------------------------------------------------------------- */ if (int_req > INT_PENDING) { /* interrupt? */ int_req = int_req & ~INT_ION; /* interrupts off */ SF = (UF << 6) | (IF >> 9) | (DF >> 12); /* form save field */ PCQ_ENTRY (IF | PC); /* save old PC with IF */ IF = IB = DF = UF = UB = 0; /* clear mem ext */ M[0] = PC; /* save PC in 0 */ PC = 1; /* fetch next from 1 */ } MA = IF | PC; /* form PC */ if (sim_brk_summ && sim_brk_test (MA, (1u << SIM_BKPT_V_SPC) | SWMASK ('E'))) { /* breakpoint? */ reason = STOP_IBKPT; /* stop simulation */ break; } IR = M[MA]; /* fetch instruction */ if (sim_brk_summ && sim_brk_test (IR, (2u << SIM_BKPT_V_SPC) | SWMASK ('I'))) { /* breakpoint? */ reason = STOP_OPBKPT; /* stop simulation */ break; } PC = (PC + 1) & 07777; /* increment PC */ int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */ sim_interval = sim_interval - 1; /* Instruction decoding. The opcode (IR<0:2>), indirect flag (IR<3>), and page flag (IR<4>) are decoded together. This produces 32 decode points, four per major opcode. For IOT, the extra decode points are not useful; for OPR, only the group flag (IR<3>) is used. AND, TAD, ISZ, DCA calculate a full 15b effective address. JMS, JMP calculate a 12b field-relative effective address. Autoindex calculations always occur within the same field as the instruction fetch. The field must exist; otherwise, the instruction fetched would be 0000, and indirect addressing could not occur. Note that MA contains IF'PC. */ if (hst_lnt) { /* history enabled? */ int32 ea; hst_p = (hst_p + 1); /* next entry */ if (hst_p >= hst_lnt) hst_p = 0; hst[hst_p].pc = MA | HIST_PC; /* save PC, IR, LAC, MQ */ hst[hst_p].ir = IR; hst[hst_p].lac = LAC; hst[hst_p].mq = MQ; if (IR < 06000) { /* mem ref? */ if (IR & 0200) ea = (MA & 077600) | (IR & 0177); else ea = IF | (IR & 0177); /* direct addr */ if (IR & 0400) { /* indirect? */ if (IR < 04000) { /* mem operand? */ if ((ea & 07770) != 00010) ea = DF | M[ea]; else ea = DF | ((M[ea] + 1) & 07777); } else { /* no, jms/jmp */ if ((ea & 07770) != 00010) ea = IB | M[ea]; else ea = IB | ((M[ea] + 1) & 07777); } } hst[hst_p].ea = ea; /* save eff addr */ hst[hst_p].opnd = M[ea]; /* save operand */ } } switch ((IR >> 7) & 037) { /* decode IR<0:4> */ /* Opcode 0, AND */ case 000: /* AND, dir, zero */ MA = IF | (IR & 0177); /* dir addr, page zero */ LAC = LAC & (M[MA] | 010000); break; case 001: /* AND, dir, curr */ MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ LAC = LAC & (M[MA] | 010000); break; case 002: /* AND, indir, zero */ MA = IF | (IR & 0177); /* dir addr, page zero */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ LAC = LAC & (M[MA] | 010000); break; case 003: /* AND, indir, curr */ MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ LAC = LAC & (M[MA] | 010000); break; /* Opcode 1, TAD */ case 004: /* TAD, dir, zero */ MA = IF | (IR & 0177); /* dir addr, page zero */ LAC = (LAC + M[MA]) & 017777; break; case 005: /* TAD, dir, curr */ MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ LAC = (LAC + M[MA]) & 017777; break; case 006: /* TAD, indir, zero */ MA = IF | (IR & 0177); /* dir addr, page zero */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ LAC = (LAC + M[MA]) & 017777; break; case 007: /* TAD, indir, curr */ MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ LAC = (LAC + M[MA]) & 017777; break; /* Opcode 2, ISZ */ case 010: /* ISZ, dir, zero */ MA = IF | (IR & 0177); /* dir addr, page zero */ M[MA] = MB = (M[MA] + 1) & 07777; /* field must exist */ if (MB == 0) PC = (PC + 1) & 07777; break; case 011: /* ISZ, dir, curr */ MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ M[MA] = MB = (M[MA] + 1) & 07777; /* field must exist */ if (MB == 0) PC = (PC + 1) & 07777; break; case 012: /* ISZ, indir, zero */ MA = IF | (IR & 0177); /* dir addr, page zero */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ MB = (M[MA] + 1) & 07777; if (MEM_ADDR_OK (MA)) M[MA] = MB; if (MB == 0) PC = (PC + 1) & 07777; break; case 013: /* ISZ, indir, curr */ MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ MB = (M[MA] + 1) & 07777; if (MEM_ADDR_OK (MA)) M[MA] = MB; if (MB == 0) PC = (PC + 1) & 07777; break; /* Opcode 3, DCA */ case 014: /* DCA, dir, zero */ MA = IF | (IR & 0177); /* dir addr, page zero */ M[MA] = LAC & 07777; LAC = LAC & 010000; break; case 015: /* DCA, dir, curr */ MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ M[MA] = LAC & 07777; LAC = LAC & 010000; break; case 016: /* DCA, indir, zero */ MA = IF | (IR & 0177); /* dir addr, page zero */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; LAC = LAC & 010000; break; case 017: /* DCA, indir, curr */ MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; LAC = LAC & 010000; break; /* Opcode 4, JMS. From Bernhard Baehr's description of the TSC8-75: (In user mode) the current JMS opcode is moved to the ERIOT register, the ECDF flag is cleared. The address of the JMS instruction is loaded into the ERTB register and the TSC8-75 I/O flag is raised. When the TSC8-75 is enabled, the target addess of the JMS is loaded into PC, but nothing else (loading of IF, UF, clearing the interrupt inhibit flag, storing of the return address in the first word of the subroutine) happens. When the TSC8-75 is disabled, the JMS is performed as usual. */ case 020: /* JMS, dir, zero */ PCQ_ENTRY (MA); MA = IR & 0177; /* dir addr, page zero */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ tsc_cdf = 0; /* clear flag */ } if (UF && tsc_enb) { /* user mode, TSC enab? */ tsc_pc = (PC - 1) & 07777; /* save PC */ int_req = int_req | INT_TSC; /* request intr */ } else { /* normal */ IF = IB; /* change IF */ UF = UB; /* change UF */ int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ MA = IF | MA; if (MEM_ADDR_OK (MA)) M[MA] = PC; } PC = (MA + 1) & 07777; break; case 021: /* JMS, dir, curr */ PCQ_ENTRY (MA); MA = (MA & 007600) | (IR & 0177); /* dir addr, curr page */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ tsc_cdf = 0; /* clear flag */ } if (UF && tsc_enb) { /* user mode, TSC enab? */ tsc_pc = (PC - 1) & 07777; /* save PC */ int_req = int_req | INT_TSC; /* request intr */ } else { /* normal */ IF = IB; /* change IF */ UF = UB; /* change UF */ int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ MA = IF | MA; if (MEM_ADDR_OK (MA)) M[MA] = PC; } PC = (MA + 1) & 07777; break; case 022: /* JMS, indir, zero */ PCQ_ENTRY (MA); MA = IF | (IR & 0177); /* dir addr, page zero */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = M[MA]; else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ tsc_cdf = 0; /* clear flag */ } if (UF && tsc_enb) { /* user mode, TSC enab? */ tsc_pc = (PC - 1) & 07777; /* save PC */ int_req = int_req | INT_TSC; /* request intr */ } else { /* normal */ IF = IB; /* change IF */ UF = UB; /* change UF */ int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ MA = IF | MA; if (MEM_ADDR_OK (MA)) M[MA] = PC; } PC = (MA + 1) & 07777; break; case 023: /* JMS, indir, curr */ PCQ_ENTRY (MA); MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = M[MA]; else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ tsc_cdf = 0; /* clear flag */ } if (UF && tsc_enb) { /* user mode, TSC enab? */ tsc_pc = (PC - 1) & 07777; /* save PC */ int_req = int_req | INT_TSC; /* request intr */ } else { /* normal */ IF = IB; /* change IF */ UF = UB; /* change UF */ int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ MA = IF | MA; if (MEM_ADDR_OK (MA)) M[MA] = PC; } PC = (MA + 1) & 07777; break; /* Opcode 5, JMP. From Bernhard Baehr's description of the TSC8-75: (In user mode) the current JMP opcode is moved to the ERIOT register, the ECDF flag is cleared. The address of the JMP instruction is loaded into the ERTB register and the TSC8-75 I/O flag is raised. Then the JMP is performed as usual (including the setting of IF, UF and clearing the interrupt inhibit flag). */ case 024: /* JMP, dir, zero */ PCQ_ENTRY (MA); MA = IR & 0177; /* dir addr, page zero */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ tsc_cdf = 0; /* clear flag */ if (tsc_enb) { /* TSC8 enabled? */ tsc_pc = (PC - 1) & 07777; /* save PC */ int_req = int_req | INT_TSC; /* request intr */ } } IF = IB; /* change IF */ UF = UB; /* change UF */ int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ PC = MA; break; /* If JMP direct, also check for idle (KSF/JMP *-1) and infinite loop */ case 025: /* JMP, dir, curr */ PCQ_ENTRY (MA); MA = (MA & 007600) | (IR & 0177); /* dir addr, curr page */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ tsc_cdf = 0; /* clear flag */ if (tsc_enb) { /* TSC8 enabled? */ tsc_pc = (PC - 1) & 07777; /* save PC */ int_req = int_req | INT_TSC; /* request intr */ } } if (sim_idle_enab && /* idling enabled? */ (IF == IB)) { /* to same bank? */ if (MA == ((PC - 2) & 07777)) { /* 1) JMP *-1? */ if (!(int_req & (INT_ION|INT_TTI)) && /* iof, TTI flag off? */ (M[IB|((PC - 2) & 07777)] == OP_KSF)) /* next is KSF? */ sim_idle (TMR_CLK, FALSE); /* we're idle */ } /* end JMP *-1 */ else if (MA == ((PC - 1) & 07777)) { /* 2) JMP *? */ if (!(int_req & INT_ION)) /* iof? */ reason = STOP_LOOP; /* then infinite loop */ else if (!(int_req & INT_ALL)) /* ion, not intr? */ sim_idle (TMR_CLK, FALSE); /* we're idle */ } /* end JMP */ } /* end idle enabled */ IF = IB; /* change IF */ UF = UB; /* change UF */ int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ PC = MA; break; case 026: /* JMP, indir, zero */ PCQ_ENTRY (MA); MA = IF | (IR & 0177); /* dir addr, page zero */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = M[MA]; else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ tsc_cdf = 0; /* clear flag */ if (tsc_enb) { /* TSC8 enabled? */ tsc_pc = (PC - 1) & 07777; /* save PC */ int_req = int_req | INT_TSC; /* request intr */ } } IF = IB; /* change IF */ UF = UB; /* change UF */ int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ PC = MA; break; case 027: /* JMP, indir, curr */ PCQ_ENTRY (MA); MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = M[MA]; else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (UF) { /* user mode? */ tsc_ir = IR; /* save instruction */ tsc_cdf = 0; /* clear flag */ if (tsc_enb) { /* TSC8 enabled? */ tsc_pc = (PC - 1) & 07777; /* save PC */ int_req = int_req | INT_TSC; /* request intr */ } } IF = IB; /* change IF */ UF = UB; /* change UF */ int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ PC = MA; break; /* Opcode 7, OPR group 1 */ case 034:case 035: /* OPR, group 1 */ switch ((IR >> 4) & 017) { /* decode IR<4:7> */ case 0: /* nop */ break; case 1: /* CML */ LAC = LAC ^ 010000; break; case 2: /* CMA */ LAC = LAC ^ 07777; break; case 3: /* CMA CML */ LAC = LAC ^ 017777; break; case 4: /* CLL */ LAC = LAC & 07777; break; case 5: /* CLL CML = STL */ LAC = LAC | 010000; break; case 6: /* CLL CMA */ LAC = (LAC ^ 07777) & 07777; break; case 7: /* CLL CMA CML */ LAC = (LAC ^ 07777) | 010000; break; case 010: /* CLA */ LAC = LAC & 010000; break; case 011: /* CLA CML */ LAC = (LAC & 010000) ^ 010000; break; case 012: /* CLA CMA = STA */ LAC = LAC | 07777; break; case 013: /* CLA CMA CML */ LAC = (LAC | 07777) ^ 010000; break; case 014: /* CLA CLL */ LAC = 0; break; case 015: /* CLA CLL CML */ LAC = 010000; break; case 016: /* CLA CLL CMA */ LAC = 07777; break; case 017: /* CLA CLL CMA CML */ LAC = 017777; break; } /* end switch opers */ if (IR & 01) /* IAC */ LAC = (LAC + 1) & 017777; switch ((IR >> 1) & 07) { /* decode IR<8:10> */ case 0: /* nop */ break; case 1: /* BSW */ LAC = (LAC & 010000) | ((LAC >> 6) & 077) | ((LAC & 077) << 6); break; case 2: /* RAL */ LAC = ((LAC << 1) | (LAC >> 12)) & 017777; break; case 3: /* RTL */ LAC = ((LAC << 2) | (LAC >> 11)) & 017777; break; case 4: /* RAR */ LAC = ((LAC >> 1) | (LAC << 12)) & 017777; break; case 5: /* RTR */ LAC = ((LAC >> 2) | (LAC << 11)) & 017777; break; case 6: /* RAL RAR - undef */ LAC = LAC & (IR | 010000); /* uses AND path */ break; case 7: /* RTL RTR - undef */ LAC = (LAC & 010000) | (MA & 07600) | (IR & 0177); break; /* uses address path */ } /* end switch shifts */ break; /* end group 1 */ /* OPR group 2. From Bernhard Baehr's description of the TSC8-75: (In user mode) HLT (7402), OSR (7404) and microprogrammed combinations with HLT and OSR: Additional to raising a user mode interrupt, the current OPR opcode is moved to the ERIOT register and the ECDF flag is cleared. */ case 036:case 037: /* OPR, groups 2, 3 */ if ((IR & 01) == 0) { /* group 2 */ switch ((IR >> 3) & 017) { /* decode IR<6:8> */ case 0: /* nop */ break; case 1: /* SKP */ PC = (PC + 1) & 07777; break; case 2: /* SNL */ if (LAC >= 010000) PC = (PC + 1) & 07777; break; case 3: /* SZL */ if (LAC < 010000) PC = (PC + 1) & 07777; break; case 4: /* SZA */ if ((LAC & 07777) == 0) PC = (PC + 1) & 07777; break; case 5: /* SNA */ if ((LAC & 07777) != 0) PC = (PC + 1) & 07777; break; case 6: /* SZA | SNL */ if ((LAC == 0) || (LAC >= 010000)) PC = (PC + 1) & 07777; break; case 7: /* SNA & SZL */ if ((LAC != 0) && (LAC < 010000)) PC = (PC + 1) & 07777; break; case 010: /* SMA */ if ((LAC & 04000) != 0) PC = (PC + 1) & 07777; break; case 011: /* SPA */ if ((LAC & 04000) == 0) PC = (PC + 1) & 07777; break; case 012: /* SMA | SNL */ if (LAC >= 04000) PC = (PC + 1) & 07777; break; case 013: /* SPA & SZL */ if (LAC < 04000) PC = (PC + 1) & 07777; break; case 014: /* SMA | SZA */ if (((LAC & 04000) != 0) || ((LAC & 07777) == 0)) PC = (PC + 1) & 07777; break; case 015: /* SPA & SNA */ if (((LAC & 04000) == 0) && ((LAC & 07777) != 0)) PC = (PC + 1) & 07777; break; case 016: /* SMA | SZA | SNL */ if ((LAC >= 04000) || (LAC == 0)) PC = (PC + 1) & 07777; break; case 017: /* SPA & SNA & SZL */ if ((LAC < 04000) && (LAC != 0)) PC = (PC + 1) & 07777; break; } /* end switch skips */ if (IR & 0200) /* CLA */ LAC = LAC & 010000; if ((IR & 06) && UF) { /* user mode? */ int_req = int_req | INT_UF; /* request intr */ tsc_ir = IR; /* save instruction */ tsc_cdf = 0; /* clear flag */ } else { if (IR & 04) { /* OSR */ /* ---PiDP add--------------------------------------------------------------------------------------------- */ SR = get_switch_register(); /* get current SR */ /* ---PiDP end---------------------------------------------------------------------------------------------- */ LAC = LAC | SR; } if (IR & 02) { /* HLT */ //--- PiDP change----------------------------------------------------------------------- // reason = STOP_HALT; extern int swStop; swStop = 1; } //--- end of PiDP change---------------------------------------------------------------- } break; } /* end if group 2 */ /* OPR group 3 standard MQA!MQL exchanges AC and MQ, as follows: temp = MQ; MQ = LAC & 07777; LAC = LAC & 010000 | temp; */ temp = MQ; /* group 3 */ if (IR & 0200) /* CLA */ LAC = LAC & 010000; if (IR & 0020) { /* MQL */ MQ = LAC & 07777; LAC = LAC & 010000; } if (IR & 0100) /* MQA */ LAC = LAC | temp; if ((IR & 0056) && (cpu_unit.flags & UNIT_NOEAE)) { reason = stop_inst; /* EAE not present */ break; } /* OPR group 3 EAE The EAE operates in two modes: Mode A, PDP-8/I compatible Mode B, extended capability Mode B provides eight additional subfunctions; in addition, some of the Mode A functions operate differently in Mode B. The mode switch instructions are decoded explicitly and cannot be microprogrammed with other EAE functions (SWAB performs an MQL as part of standard group 3 decoding). If mode switching is decoded, all other EAE timing is suppressed. */ if (IR == 07431) { /* SWAB */ emode = 1; /* set mode flag */ break; } if (IR == 07447) { /* SWBA */ emode = gtf = 0; /* clear mode, gtf */ break; } /* If not switching modes, the EAE operation is determined by the mode and IR<6,8:10>: <6:10> mode A mode B comments 0x000 NOP NOP 0x001 SCL ACS 0x010 MUY MUY if mode B, next = address 0x011 DVI DVI if mode B, next = address 0x100 NMI NMI if mode B, clear AC if result = 4000'0000 0x101 SHL SHL if mode A, extra shift 0x110 ASR ASR if mode A, extra shift 0x111 LSR LSR if mode A, extra shift 1x000 SCA SCA 1x001 SCA + SCL DAD 1x010 SCA + MUY DST 1x011 SCA + DVI SWBA NOP if not detected earlier 1x100 SCA + NMI DPSZ 1x101 SCA + SHL DPIC must be combined with MQA!MQL 1x110 SCA + ASR DCM must be combined with MQA!MQL 1x111 SCA + LSR SAM EAE instructions which fetch memory operands use the CPU's DEFER state to read the first word; if the address operand is in locations x0010 - x0017, it is autoincremented. */ if (emode == 0) /* mode A? clr gtf */ gtf = 0; switch ((IR >> 1) & 027) { /* decode IR<6,8:10> */ case 020: /* mode A, B: SCA */ LAC = LAC | SC; break; case 000: /* mode A, B: NOP */ break; case 021: /* mode B: DAD */ if (emode) { MA = IF | PC; if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ MQ = MQ + M[MA]; MA = DF | ((MA + 1) & 07777); LAC = (LAC & 07777) + M[MA] + (MQ >> 12); MQ = MQ & 07777; PC = (PC + 1) & 07777; break; } LAC = LAC | SC; /* mode A: SCA then */ case 001: /* mode B: ACS */ if (emode) { SC = LAC & 037; LAC = LAC & 010000; } else { /* mode A: SCL */ SC = (~M[IF | PC]) & 037; PC = (PC + 1) & 07777; } break; case 022: /* mode B: DST */ if (emode) { MA = IF | PC; if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (MEM_ADDR_OK (MA)) M[MA] = MQ & 07777; MA = DF | ((MA + 1) & 07777); if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; PC = (PC + 1) & 07777; break; } LAC = LAC | SC; /* mode A: SCA then */ case 002: /* MUY */ MA = IF | PC; if (emode) { /* mode B: defer */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ } temp = (MQ * M[MA]) + (LAC & 07777); LAC = (temp >> 12) & 07777; MQ = temp & 07777; PC = (PC + 1) & 07777; SC = 014; /* 12 shifts */ break; case 023: /* mode B: SWBA */ if (emode) break; LAC = LAC | SC; /* mode A: SCA then */ case 003: /* DVI */ MA = IF | PC; if (emode) { /* mode B: defer */ if ((MA & 07770) != 00010) /* indirect; autoinc? */ MA = DF | M[MA]; else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ } if ((LAC & 07777) >= M[MA]) { /* overflow? */ LAC = LAC | 010000; /* set link */ MQ = ((MQ << 1) + 1) & 07777; /* rotate MQ */ SC = 0; /* no shifts */ } else { temp = ((LAC & 07777) << 12) | MQ; MQ = temp / M[MA]; LAC = temp % M[MA]; SC = 015; /* 13 shifts */ } PC = (PC + 1) & 07777; break; case 024: /* mode B: DPSZ */ if (emode) { if (((LAC | MQ) & 07777) == 0) PC = (PC + 1) & 07777; break; } LAC = LAC | SC; /* mode A: SCA then */ case 004: /* NMI */ temp = (LAC << 12) | MQ; /* preserve link */ for (SC = 0; ((temp & 017777777) != 0) && (temp & 040000000) == ((temp << 1) & 040000000); SC++) temp = temp << 1; LAC = (temp >> 12) & 017777; MQ = temp & 07777; if (emode && ((LAC & 07777) == 04000) && (MQ == 0)) LAC = LAC & 010000; /* clr if 4000'0000 */ break; case 025: /* mode B: DPIC */ if (emode) { temp = (LAC + 1) & 07777; /* SWP already done! */ LAC = MQ + (temp == 0); MQ = temp; break; } LAC = LAC | SC; /* mode A: SCA then */ case 5: /* SHL */ SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ if (SC > 25) /* >25? result = 0 */ temp = 0; else temp = ((LAC << 12) | MQ) << SC; /* <=25? shift LAC:MQ */ LAC = (temp >> 12) & 017777; MQ = temp & 07777; PC = (PC + 1) & 07777; SC = emode? 037: 0; /* SC = 0 if mode A */ break; case 026: /* mode B: DCM */ if (emode) { temp = (-LAC) & 07777; /* SWP already done! */ LAC = (MQ ^ 07777) + (temp == 0); MQ = temp; break; } LAC = LAC | SC; /* mode A: SCA then */ case 6: /* ASR */ SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ temp = ((LAC & 07777) << 12) | MQ; /* sext from AC0 */ if (LAC & 04000) temp = temp | ~037777777; if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1; if (SC > 25) temp = (LAC & 04000)? -1: 0; else temp = temp >> SC; LAC = (temp >> 12) & 017777; MQ = temp & 07777; PC = (PC + 1) & 07777; SC = emode? 037: 0; /* SC = 0 if mode A */ break; case 027: /* mode B: SAM */ if (emode) { temp = LAC & 07777; LAC = MQ + (temp ^ 07777) + 1; /* L'AC = MQ - AC */ gtf = (temp <= MQ) ^ ((temp ^ MQ) >> 11); break; } LAC = LAC | SC; /* mode A: SCA then */ case 7: /* LSR */ SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ temp = ((LAC & 07777) << 12) | MQ; /* clear link */ if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1; if (SC > 24) /* >24? result = 0 */ temp = 0; else temp = temp >> SC; /* <=24? shift AC:MQ */ LAC = (temp >> 12) & 07777; MQ = temp & 07777; PC = (PC + 1) & 07777; SC = emode? 037: 0; /* SC = 0 if mode A */ break; } /* end switch */ break; /* end case 7 */ /* Opcode 6, IOT. From Bernhard Baehr's description of the TSC8-75: (In user mode) Additional to raising a user mode interrupt, the current IOT opcode is moved to the ERIOT register. When the IOT is a CDF instruction (62x1), the ECDF flag is set, otherwise it is cleared. */ case 030:case 031:case 032:case 033: /* IOT */ if (UF) { /* privileged? */ int_req = int_req | INT_UF; /* request intr */ tsc_ir = IR; /* save instruction */ if ((IR & 07707) == 06201) /* set/clear flag */ tsc_cdf = 1; else tsc_cdf = 0; break; } device = (IR >> 3) & 077; /* device = IR<3:8> */ pulse = IR & 07; /* pulse = IR<9:11> */ iot_data = LAC & 07777; /* AC unchanged */ switch (device) { /* decode IR<3:8> */ case 000: /* CPU control */ switch (pulse) { /* decode IR<9:11> */ case 0: /* SKON */ if (int_req & INT_ION) PC = (PC + 1) & 07777; int_req = int_req & ~INT_ION; break; case 1: /* ION */ int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING; break; case 2: /* IOF */ int_req = int_req & ~INT_ION; break; case 3: /* SRQ */ if (int_req & INT_ALL) PC = (PC + 1) & 07777; break; case 4: /* GTF */ LAC = (LAC & 010000) | ((LAC & 010000) >> 1) | (gtf << 10) | (((int_req & INT_ALL) != 0) << 9) | (((int_req & INT_ION) != 0) << 7) | SF; break; case 5: /* RTF */ gtf = ((LAC & 02000) >> 10); UB = (LAC & 0100) >> 6; IB = (LAC & 0070) << 9; DF = (LAC & 0007) << 12; LAC = ((LAC & 04000) << 1) | iot_data; int_req = (int_req | INT_ION) & ~INT_NO_CIF_PENDING; break; case 6: /* SGT */ if (gtf) PC = (PC + 1) & 07777; break; case 7: /* CAF */ gtf = 0; emode = 0; int_req = int_req & INT_NO_CIF_PENDING; dev_done = 0; int_enable = INT_INIT_ENABLE; LAC = 0; reset_all (1); /* reset all dev */ break; } /* end switch pulse */ break; /* end case 0 */ case 020:case 021:case 022:case 023: case 024:case 025:case 026:case 027: /* memory extension */ switch (pulse) { /* decode IR<9:11> */ case 1: /* CDF */ DF = (IR & 0070) << 9; break; case 2: /* CIF */ IB = (IR & 0070) << 9; int_req = int_req & ~INT_NO_CIF_PENDING; break; case 3: /* CDF CIF */ DF = IB = (IR & 0070) << 9; int_req = int_req & ~INT_NO_CIF_PENDING; break; case 4: switch (device & 07) { /* decode IR<6:8> */ case 0: /* CINT */ int_req = int_req & ~INT_UF; break; case 1: /* RDF */ LAC = LAC | (DF >> 9); break; case 2: /* RIF */ LAC = LAC | (IF >> 9); break; case 3: /* RIB */ LAC = LAC | SF; break; case 4: /* RMF */ UB = (SF & 0100) >> 6; IB = (SF & 0070) << 9; DF = (SF & 0007) << 12; int_req = int_req & ~INT_NO_CIF_PENDING; break; case 5: /* SINT */ if (int_req & INT_UF) PC = (PC + 1) & 07777; break; case 6: /* CUF */ UB = 0; int_req = int_req & ~INT_NO_CIF_PENDING; break; case 7: /* SUF */ UB = 1; int_req = int_req & ~INT_NO_CIF_PENDING; break; } /* end switch device */ break; default: reason = stop_inst; break; } /* end switch pulse */ break; /* end case 20-27 */ case 010: /* power fail */ switch (pulse) { /* decode IR<9:11> */ case 1: /* SBE */ break; case 2: /* SPL */ if (int_req & INT_PWR) PC = (PC + 1) & 07777; break; case 3: /* CAL */ int_req = int_req & ~INT_PWR; break; default: reason = stop_inst; break; } /* end switch pulse */ break; /* end case 10 */ default: /* I/O device */ if (dev_tab[device]) { /* dev present? */ /* ---PiDP add--------------------------------------------------------------------------------------------- */ // Any other device will trigger IOP, so light pause Pause = 1; /* ---PiDP end---------------------------------------------------------------------------------------------- */ iot_data = dev_tab[device] (IR, iot_data); LAC = (LAC & 010000) | (iot_data & 07777); if (iot_data & IOT_SKP) PC = (PC + 1) & 07777; if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON; } else reason = stop_inst; /* stop on flag */ break; } /* end switch device */ break; /* end case IOT */ } /* end switch opcode */ /* ---PiDP add--------------------------------------------------------------------------------------------- */ // Update the front panel with this instruction's final state. // // There's no point saving *every* LED "on" count. We just need a // suitable amount of oversampling. We can skip this if we called // set_pidp8i_leds recently enough, avoiding all the expensive bit // shift and memory update work it does. // // The trick here is figuring out what "recently enough" means // without making expensive OS timer calls. These timers aren't // hopelessly slow (http://stackoverflow.com/a/13096917/142454) but // we still don't want to be taking dozens of cycles per instruction // just to keep our update estimate current in the face of system // load changes and SET THROTTLE updates. // // Instead, we maintain a model of the current IPS value — seeded // with the initial "SET THROTTLE" value, if any — to figure out // how many calls we can skip while still meeting our other goals. // This involves a bit of math, but when paid only once a second, // it amortizes much nicer than estimating the skip count directly // based on a more accurate time source which is more expensive // to call. It's also cheaper than continually asking SIMH to // estimate the SIMH IPS value, since it uses FP math. // // Each LED panel repaint takes about 10 ms, so we do about 100 // full-panel updates per second. We need a bare minimum of 32 // discernible brightness values per update for ILS, so if we don't // update the LED status data at least 3,200 times per second, we // don't have enough data for smooth panel updates. Fortunately, // computers are pretty quick, and our slowest script runs at 30 // kIPS. (5.script.) // // We deliberately add some timing jitter here to get stochastic // sampling of the incoming instructions to avoid beat frequencies // between our update rate and the instruction pattern being // executed by the front panel. It's a form of dithering. // // You might think to move this code to the top of set_pidp8i_leds, // but the function call itself is a nontrivial hit. In fact, you // don't even want to move all of this to a function here in this // module and try to get GCC to inline it: that's good for a 1 MIPS // speed hit in my testing! (GCC 4.9.2, Raspbian Jessie on Pi 3B.) if (++skip_count >= (max_skips - dither)) { // Save skips to inst counter and reset inst_count += skip_count; skip_count = 0; // We need to update the LED data again set_pidp8i_leds (PC, MA, MB, IR, LAC, MQ, IF, DF, SC, int_req, Pause); Pause = 0; // Has it been ~1s since we updated our max_skips value? time_t now; if (time(&now) > last_update) { // Yep; simulator IPS may have changed, so freshen it. last_update = now; max_skips = inst_count / pidp8i_updates_per_sec; //printf("Inst./repaint: %zu - %zu; %.2f MIPS\r\n", // max_skips, dither, inst_count / 1e6); inst_count = 0; } dither = max_skips > 32 ? lrand48() % (max_skips >> 3) : 0; // 12.5% } /* ---PiDP end---------------------------------------------------------------------------------------------- */ } /* end while */ /* Simulation halted */ saved_PC = IF | (PC & 07777); /* save copies */ saved_DF = DF & 070000; saved_LAC = LAC & 017777; saved_MQ = MQ & 07777; pcq_r->qptr = pcq_p; /* update pc q ptr */ return reason; } /* end sim_instr */ /* Reset routine */ t_stat cpu_reset (DEVICE *dptr) { saved_LAC = 0; int_req = (int_req & ~INT_ION) | INT_NO_CIF_PENDING; saved_DF = IB = saved_PC & 070000; UF = UB = gtf = emode = 0; pcq_r = find_reg ("PCQ", NULL, dptr); if (pcq_r) pcq_r->qptr = 0; else return SCPE_IERR; sim_brk_types = SWMASK ('E') | SWMASK('I'); sim_brk_dflt = SWMASK ('E'); return SCPE_OK; } /* Set PC for boot (PC<14:12> will typically be 0) */ void cpu_set_bootpc (int32 pc) { saved_PC = pc; /* set PC, IF */ saved_DF = IB = pc & 070000; /* set IB, DF */ return; } /* Memory examine */ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { if (addr >= MEMSIZE) return SCPE_NXM; if (vptr != NULL) *vptr = M[addr] & 07777; return SCPE_OK; } /* Memory deposit */ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { if (addr >= MEMSIZE) return SCPE_NXM; M[addr] = val & 07777; return SCPE_OK; } /* Memory size change */ t_stat cpu_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int32 mc = 0; uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) return SCPE_ARG; for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; } /* Change device number for a device */ t_stat set_dev (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { DEVICE *dptr; DIB *dibp; uint32 newdev; t_stat r; if (cptr == NULL) return SCPE_ARG; if (uptr == NULL) return SCPE_IERR; dptr = find_dev_from_unit (uptr); if (dptr == NULL) return SCPE_IERR; dibp = (DIB *) dptr->ctxt; if (dibp == NULL) return SCPE_IERR; newdev = get_uint (cptr, 8, DEV_MAX - 1, &r); /* get new */ if ((r != SCPE_OK) || (newdev == dibp->dev)) return r; dibp->dev = newdev; /* store */ return SCPE_OK; } /* Show device number for a device */ t_stat show_dev (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { DEVICE *dptr; DIB *dibp; if (uptr == NULL) return SCPE_IERR; dptr = find_dev_from_unit (uptr); if (dptr == NULL) return SCPE_IERR; dibp = (DIB *) dptr->ctxt; if (dibp == NULL) return SCPE_IERR; fprintf (st, "devno=%02o", dibp->dev); if (dibp->num > 1) fprintf (st, "-%2o", dibp->dev + dibp->num - 1); return SCPE_OK; } /* CPU device handler - should never get here! */ int32 bad_dev (int32 IR, int32 AC) { return (SCPE_IERR << IOT_V_REASON) | AC; /* broken! */ } /* Build device dispatch table */ t_bool build_dev_tab (void) { DEVICE *dptr; DIB *dibp; uint32 i, j; static const uint8 std_dev[] = { 000, 010, 020, 021, 022, 023, 024, 025, 026, 027 }; for (i = 0; i < DEV_MAX; i++) /* clr table */ dev_tab[i] = NULL; for (i = 0; i < ((uint32) sizeof (std_dev)); i++) /* std entries */ dev_tab[std_dev[i]] = &bad_dev; for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* add devices */ dibp = (DIB *) dptr->ctxt; /* get DIB */ if (dibp && !(dptr->flags & DEV_DIS)) { /* enabled? */ if (dibp->dsp_tbl) { /* dispatch table? */ DIB_DSP *dspp = dibp->dsp_tbl; /* set ptr */ for (j = 0; j < dibp->num; j++, dspp++) { /* loop thru tbl */ if (dspp->dsp) { /* any dispatch? */ if (dev_tab[dspp->dev]) { /* already filled? */ sim_printf ("%s device number conflict at %02o\n", sim_dname (dptr), dibp->dev + j); return TRUE; } dev_tab[dspp->dev] = dspp->dsp; /* fill */ } /* end if dsp */ } /* end for j */ } /* end if dsp_tbl */ else { /* inline dispatches */ for (j = 0; j < dibp->num; j++) { /* loop thru disp */ if (dibp->dsp[j]) { /* any dispatch? */ if (dev_tab[dibp->dev + j]) { /* already filled? */ sim_printf ("%s device number conflict at %02o\n", sim_dname (dptr), dibp->dev + j); return TRUE; } dev_tab[dibp->dev + j] = dibp->dsp[j]; /* fill */ } /* end if dsp */ } /* end for j */ } /* end else */ } /* end if enb */ } /* end for i */ return FALSE; } /* Set history */ t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int32 i, lnt; t_stat r; if (cptr == NULL) { for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; hst_p = 0; return SCPE_OK; } lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { free (hst); hst_lnt = 0; hst = NULL; } if (lnt) { hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); if (hst == NULL) return SCPE_MEM; hst_lnt = lnt; } return SCPE_OK; } /* Show history */ t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { int32 l, k, di, lnt; const char *cptr = (const char *) desc; t_stat r; t_value sim_eval; InstHistory *h; if (hst_lnt == 0) /* enabled? */ return SCPE_NOFNC; if (cptr) { lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "PC L AC MQ ea IR\n\n"); for (k = 0; k < lnt; k++) { /* print specified */ h = &hst[(++di) % hst_lnt]; /* entry pointer */ if (h->pc & HIST_PC) { /* instruction? */ l = (h->lac >> 12) & 1; /* link */ fprintf (st, "%05o %o %04o %04o ", h->pc & ADDRMASK, l, h->lac & 07777, h->mq); if (h->ir < 06000) fprintf (st, "%05o ", h->ea); else fprintf (st, " "); sim_eval = h->ir; if ((fprint_sym (st, h->pc & ADDRMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) fprintf (st, "(undefined) %04o", h->ir); if (h->ir < 04000) fprintf (st, " [%04o]", h->opnd); fputc ('\n', st); /* end line */ } /* end else instruction */ } /* end for */ return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 | /* pdp8_ct.c: PDP-8 cassette tape simulator Copyright (c) 2006-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. ct TA8E/TU60 cassette tape 17-Sep-07 RMS Changed to use central set_bootpc routine 13-Aug-07 RMS Fixed handling of BEOT 06-Aug-07 RMS Foward op at BOT skips initial file gap 30-May-07 RMS Fixed typo (Norm Lastovica) Magnetic tapes are represented as a series of variable records of the form: 32b byte count byte 0 byte 1 : byte n-2 byte n-1 32b byte count If the byte count is odd, the record is padded with an extra byte of junk. File marks are represented by a byte count of 0. Cassette format differs in one very significant way: it has file gaps rather than file marks. If the controller spaces or reads into a file gap and then reverses direction, the file gap is not seen again. This is in contrast to magnetic tapes, where the file mark is a character sequence and is seen again if direction is reversed. In addition, cassettes have an initial file gap which is automatically skipped on forward operations from beginning of tape. Note that the read and write sequences for the cassette are asymmetric: Read: KLSA /SELECT READ KGOA /INIT READ, CLEAR DF <data flag sets, char in buf> KGOA /READ 1ST CHAR, CLEAR DF DCA CHAR : <data flag sets, char in buf> KGOA /READ LAST CHAR, CLEAR DF DCA CHAR <data flag sets, CRC1 in buf> KLSA /SELECT CRC MODE KGOA /READ 1ST CRC <data flag sets, CRC2 in buf> KGOA /READ 2ND CRC <ready flag/CRC error flag sets> Write: KLSA /SELECT WRITE TAD CHAR /1ST CHAR KGOA /INIT WRITE, CHAR TO BUF, CLEAR DF <data flag sets, char to tape> : TAD CHAR /LAST CHAR KGOA /CHAR TO BUF, CLEAR DF <data flag sets, char to tape> KLSA /SELECT CRC MODE KGOA /WRITE CRC, CLEAR DF <ready flag sets, CRC on tape> */ #include "pdp8_defs.h" #include "sim_tape.h" #define CT_NUMDR 2 /* #drives */ #define FNC u3 /* unit function */ #define UST u4 /* unit status */ #define CT_MAXFR (CT_SIZE) /* max record lnt */ #define CT_SIZE 93000 /* chars/tape */ /* Status Register A */ #define SRA_ENAB 0200 /* enable */ #define SRA_V_UNIT 6 /* unit */ #define SRA_M_UNIT (CT_NUMDR - 1) #define SRA_V_FNC 3 /* function */ #define SRA_M_FNC 07 #define SRA_READ 00 #define SRA_REW 01 #define SRA_WRITE 02 #define SRA_SRF 03 #define SRA_WFG 04 #define SRA_SRB 05 #define SRA_CRC 06 #define SRA_SFF 07 #define SRA_2ND 010 #define SRA_IE 0001 /* int enable */ #define GET_UNIT(x) (((x) >> SRA_V_UNIT) & SRA_M_UNIT) #define GET_FNC(x) (((x) >> SRA_V_FNC) & SRA_M_FNC) /* Function code flags */ #define OP_WRI 01 /* op is a write */ #define OP_REV 02 /* op is rev motion */ #define OP_FWD 04 /* op is fwd motion */ /* Unit status flags */ #define UST_REV (OP_REV) /* last op was rev */ #define UST_GAP 01 /* last op hit gap */ /* Status Register B, ^ = computed on the fly */ #define SRB_WLE 0400 /* "write lock err" */ #define SRB_CRC 0200 /* CRC error */ #define SRB_TIM 0100 /* timing error */ #define SRB_BEOT 0040 /* ^BOT/EOT */ #define SRB_EOF 0020 /* end of file */ #define SRB_EMP 0010 /* ^drive empty */ #define SRB_REW 0004 /* rewinding */ #define SRB_WLK 0002 /* ^write locked */ #define SRB_RDY 0001 /* ^ready */ #define SRB_ALLERR (SRB_WLE|SRB_CRC|SRB_TIM|SRB_BEOT|SRB_EOF|SRB_EMP) #define SRB_XFRERR (SRB_WLE|SRB_CRC|SRB_TIM|SRB_EOF) extern int32 int_req, stop_inst; extern UNIT cpu_unit; uint32 ct_sra = 0; /* status reg A */ uint32 ct_srb = 0; /* status reg B */ uint32 ct_db = 0; /* data buffer */ uint32 ct_df = 0; /* data flag */ uint32 ct_write = 0; /* TU60 write flag */ uint32 ct_bptr = 0; /* buf ptr */ uint32 ct_blnt = 0; /* buf length */ int32 ct_stime = 1000; /* start time */ int32 ct_ctime = 100; /* char latency */ uint32 ct_stopioe = 1; /* stop on error */ uint8 *ct_xb = NULL; /* transfer buffer */ static uint8 ct_fnc_tab[SRA_M_FNC + 1] = { OP_FWD, 0 , OP_WRI|OP_FWD, OP_REV, OP_WRI|OP_FWD, OP_REV, 0, OP_FWD }; int32 ct70 (int32 IR, int32 AC); t_stat ct_svc (UNIT *uptr); t_stat ct_reset (DEVICE *dptr); t_stat ct_attach (UNIT *uptr, CONST char *cptr); t_stat ct_detach (UNIT *uptr); t_stat ct_boot (int32 unitno, DEVICE *dptr); uint32 ct_updsta (UNIT *uptr); int32 ct_go_start (int32 AC); int32 ct_go_cont (UNIT *uptr, int32 AC); t_stat ct_map_err (UNIT *uptr, t_stat st); UNIT *ct_busy (void); void ct_set_df (t_bool timchk); t_bool ct_read_char (void); uint32 ct_crc (uint8 *buf, uint32 cnt); /* CT data structures ct_dev CT device descriptor ct_unit CT unit list ct_reg CT register list ct_mod CT modifier list */ DIB ct_dib = { DEV_CT, 1, { &ct70 } }; UNIT ct_unit[] = { { UDATA (&ct_svc, UNIT_ATTABLE+UNIT_ROABLE, CT_SIZE) }, { UDATA (&ct_svc, UNIT_ATTABLE+UNIT_ROABLE, CT_SIZE) }, }; REG ct_reg[] = { { ORDATAD (CTSRA, ct_sra, 8, "status register A") }, { ORDATAD (CTSRB, ct_srb, 8, "status register B") }, { ORDATAD (CTDB, ct_db, 8, "data buffer") }, { FLDATAD (CTDF, ct_df, 0, "data flag") }, { FLDATAD (RDY, ct_srb, 0, "ready flag") }, { FLDATAD (WLE, ct_srb, 8, "write lock error") }, { FLDATAD (WRITE, ct_write, 0, "TA60 write operation flag") }, { FLDATAD (INT, int_req, INT_V_CT, "interrupt request") }, { DRDATAD (BPTR, ct_bptr, 17, "buffer pointer") }, { DRDATAD (BLNT, ct_blnt, 17, "buffer length") }, { DRDATAD (STIME, ct_stime, 24, "operation start time"), PV_LEFT + REG_NZ }, { DRDATAD (CTIME, ct_ctime, 24, "character latency"), PV_LEFT + REG_NZ }, { FLDATAD (STOP_IOE, ct_stopioe, 0, "stop on I/O errors flag") }, { URDATA (UFNC, ct_unit[0].FNC, 8, 4, 0, CT_NUMDR, REG_HRO) }, { URDATA (UST, ct_unit[0].UST, 8, 2, 0, CT_NUMDR, REG_HRO) }, { URDATAD (POS, ct_unit[0].pos, 10, T_ADDR_W, 0, CT_NUMDR, PV_LEFT | REG_RO, "position, units 0-1") }, { FLDATA (DEVNUM, ct_dib.dev, 6), REG_HRO }, { NULL } }; MTAB ct_mod[] = { { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, // { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", // &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, { MTAB_XTD|MTAB_VUN, 0, "CAPACITY", NULL, NULL, &sim_tape_show_capac, NULL }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { 0 } }; DEVICE ct_dev = { "CT", ct_unit, ct_reg, ct_mod, CT_NUMDR, 10, 31, 1, 8, 8, NULL, NULL, &ct_reset, &ct_boot, &ct_attach, &ct_detach, &ct_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_TAPE }; /* IOT routines */ int32 ct70 (int32 IR, int32 AC) { int32 srb; UNIT *uptr; srb = ct_updsta (NULL); /* update status */ switch (IR & 07) { /* decode IR<9:11> */ case 0: /* KCLR */ ct_reset (&ct_dev); /* reset the world */ break; case 1: /* KSDR */ if (ct_df) AC |= IOT_SKP; break; case 2: /* KSEN */ if (srb & SRB_ALLERR) AC |= IOT_SKP; break; case 3: /* KSBF */ if ((srb & SRB_RDY) && !(srb & SRB_EMP)) AC |= IOT_SKP; break; case 4: /* KLSA */ ct_sra = AC & 0377; ct_updsta (NULL); return ct_sra ^ 0377; case 5: /* KSAF */ if (ct_df || (srb & (SRB_ALLERR|SRB_RDY))) AC |= IOT_SKP; break; case 6: /* KGOA */ ct_df = 0; /* clear data flag */ if ((uptr = ct_busy ())) /* op in progress? */ AC = ct_go_cont (uptr, AC); /* yes */ else AC = ct_go_start (AC); /* no, start */ ct_updsta (NULL); break; case 7: /* KSRB */ return srb & 0377; } /* end switch */ return AC; } /* Start a new operation - cassette is not busy */ int32 ct_go_start (int32 AC) { UNIT *uptr = ct_dev.units + GET_UNIT (ct_sra); uint32 fnc = GET_FNC (ct_sra); uint32 flg = ct_fnc_tab[fnc]; uint32 old_ust = uptr->UST; if (DEBUG_PRS (ct_dev)) fprintf (sim_deb, ">>CT start: op=%o, old_sta = %o, pos=%d\n", fnc, uptr->UST, uptr->pos); if ((ct_sra & SRA_ENAB) && (uptr->flags & UNIT_ATT)) { /* enabled, att? */ ct_srb &= ~(SRB_XFRERR|SRB_REW); /* clear err, rew */ if (flg & OP_WRI) { /* write-type op? */ if (sim_tape_wrp (uptr)) { /* locked? */ ct_srb |= SRB_WLE; /* set flag, abort */ return AC; } ct_write = 1; /* set TU60 wr flag */ ct_db = AC & 0377; } else { ct_write = 0; ct_db = 0; } ct_srb &= ~SRB_BEOT; /* tape in motion */ if (fnc == SRA_REW) /* rew? set flag */ ct_srb |= SRB_REW; if ((fnc != SRA_REW) && !(flg & OP_WRI)) { /* read cmd? */ t_mtrlnt t; t_stat st; uptr->UST = flg & UST_REV; /* save direction */ if (sim_tape_bot (uptr) && (flg & OP_FWD)) { /* spc/read fwd bot? */ st = sim_tape_rdrecf (uptr, ct_xb, &t, CT_MAXFR); /* skip file gap */ if (st != MTSE_TMK) /* not there? */ sim_tape_rewind (uptr); /* restore tap pos */ else old_ust = 0; /* defang next */ } if ((old_ust ^ uptr->UST) == (UST_REV|UST_GAP)) { /* rev in gap? */ if (DEBUG_PRS (ct_dev)) fprintf (sim_deb, ">>CT skip gap: op=%o, old_sta = %o, pos=%d\n", fnc, uptr->UST, uptr->pos); if (uptr->UST) /* skip file gap */ sim_tape_rdrecr (uptr, ct_xb, &t, CT_MAXFR); else sim_tape_rdrecf (uptr, ct_xb, &t, CT_MAXFR); } } else uptr->UST = 0; ct_bptr = 0; /* init buffer */ ct_blnt = 0; uptr->FNC = fnc; /* save function */ sim_activate (uptr, ct_stime); /* schedule op */ } if ((fnc == SRA_READ) || (fnc == SRA_CRC)) /* read or CRC? */ return 0; /* get "char" */ return AC; } /* Continue an in-progress operation - cassette is in motion */ int32 ct_go_cont (UNIT *uptr, int32 AC) { int32 fnc = GET_FNC (ct_sra); switch (fnc) { /* case on function */ case SRA_READ: /* read */ return ct_db; /* return data */ case SRA_WRITE: /* write */ ct_db = AC & 0377; /* save data */ break; case SRA_CRC: /* CRC */ if ((uptr->FNC & SRA_M_FNC) != SRA_CRC) /* if not CRC */ uptr->FNC = SRA_CRC; /* start CRC seq */ if (!ct_write) /* read? AC <- buf */ return ct_db; break; default: break; } return AC; } /* Unit service */ t_stat ct_svc (UNIT *uptr) { uint32 i, crc; uint32 flgs = ct_fnc_tab[uptr->FNC & SRA_M_FNC]; t_mtrlnt tbc; t_stat st, r; if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ ct_updsta (uptr); /* update status */ return (ct_stopioe? SCPE_UNATT: SCPE_OK); } if (((flgs & OP_REV) && sim_tape_bot (uptr)) || /* rev at BOT or */ ((flgs & OP_FWD) && sim_tape_eot (uptr))) { /* fwd at EOT? */ ct_srb |= SRB_BEOT; /* error */ ct_updsta (uptr); /* op done */ return SCPE_OK; } r = SCPE_OK; switch (uptr->FNC) { /* case on function */ case SRA_READ: /* read start */ st = sim_tape_rdrecf (uptr, ct_xb, &ct_blnt, CT_MAXFR); /* get rec */ if (st == MTSE_RECE) /* rec in err? */ ct_srb |= SRB_CRC; else if (st != MTSE_OK) { /* other error? */ r = ct_map_err (uptr, st); /* map error */ break; } crc = ct_crc (ct_xb, ct_blnt); /* calculate CRC */ ct_xb[ct_blnt++] = (crc >> 8) & 0377; /* append to buffer */ ct_xb[ct_blnt++] = crc & 0377; uptr->FNC |= SRA_2ND; /* next state */ sim_activate (uptr, ct_ctime); /* sched next char */ return SCPE_OK; case SRA_READ|SRA_2ND: /* read char */ if (!ct_read_char ()) /* read, overrun? */ break; ct_set_df (TRUE); /* set data flag */ sim_activate (uptr, ct_ctime); /* sched next char */ return SCPE_OK; case SRA_WRITE: /* write start */ for (i = 0; i < CT_MAXFR; i++) /* clear buffer */ ct_xb[i] = 0; uptr->FNC |= SRA_2ND; /* next state */ sim_activate (uptr, ct_ctime); /* sched next char */ return SCPE_OK; case SRA_WRITE|SRA_2ND: /* write char */ if ((ct_bptr < CT_MAXFR) && /* room in buf? */ ((uptr->pos + ct_bptr) < uptr->capac)) /* room on tape? */ ct_xb[ct_bptr++] = ct_db; /* store char */ ct_set_df (TRUE); /* set data flag */ sim_activate (uptr, ct_ctime); /* sched next char */ return SCPE_OK; case SRA_CRC: /* CRC */ if (ct_write) { /* write? */ if ((st = sim_tape_wrrecf (uptr, ct_xb, ct_bptr)))/* write, err? */ r = ct_map_err (uptr, st); /* map error */ break; /* write done */ } ct_read_char (); /* get second CRC */ ct_set_df (FALSE); /* set df */ uptr->FNC |= SRA_2ND; /* next state */ sim_activate (uptr, ct_ctime); return SCPE_OK; case SRA_CRC|SRA_2ND: /* second read CRC */ if (ct_bptr != ct_blnt) { /* partial read? */ crc = ct_crc (ct_xb, ct_bptr); /* actual CRC */ if (crc != 0) /* must be zero */ ct_srb |= SRB_CRC; } break; /* read done */ case SRA_WFG: /* write file gap */ if ((st = sim_tape_wrtmk (uptr))) /* write tmk, err? */ r = ct_map_err (uptr, st); /* map error */ break; case SRA_REW: /* rewind */ sim_tape_rewind (uptr); ct_srb |= SRB_BEOT; /* set BOT */ break; case SRA_SRB: /* space rev blk */ if ((st = sim_tape_sprecr (uptr, &tbc))) /* space rev, err? */ r = ct_map_err (uptr, st); /* map error */ break; case SRA_SRF: /* space rev file */ while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ; r = ct_map_err (uptr, st); /* map error */ break; case SRA_SFF: /* space fwd file */ while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ; r = ct_map_err (uptr, st); /* map error */ break; default: /* never get here! */ return SCPE_IERR; } /* end case */ ct_updsta (uptr); /* update status */ if (DEBUG_PRS (ct_dev)) fprintf (sim_deb, ">>CT done: op=%o, statusA = %o, statusB = %o, pos=%d\n", uptr->FNC, ct_sra, ct_srb, uptr->pos); return r; } /* Update controller status */ uint32 ct_updsta (UNIT *uptr) { int32 srb; if (uptr == NULL) { /* unit specified? */ uptr = ct_busy (); /* use busy unit */ if ((uptr == NULL) && (ct_sra & SRA_ENAB)) /* none busy? */ uptr = ct_dev.units + GET_UNIT (ct_sra); /* use sel unit */ } else if (ct_srb & SRB_EOF) /* save gap */ uptr->UST |= UST_GAP; if (uptr) { /* any unit? */ ct_srb &= ~(SRB_WLK|SRB_EMP|SRB_RDY); /* clear dyn flags */ if ((uptr->flags & UNIT_ATT) == 0) /* unattached? */ ct_srb = (ct_srb | SRB_EMP|SRB_WLK) & ~SRB_REW; /* empty, locked */ if (!sim_is_active (uptr)) { /* not busy? */ ct_srb = (ct_srb | SRB_RDY) & ~SRB_REW; /* ready, ~rew */ } if (sim_tape_wrp (uptr) || (ct_srb & SRB_REW)) /* locked or rew? */ ct_srb |= SRB_WLK; /* set locked */ } if (ct_sra & SRA_ENAB) /* can TA see TU60? */ srb = ct_srb; else srb = 0; /* no */ if ((ct_sra & SRA_IE) && /* int enabled? */ (ct_df || (srb & (SRB_ALLERR|SRB_RDY)))) /* any flag? */ int_req |= INT_CT; /* set int req */ else int_req &= ~INT_CT; /* no, clr int req */ return srb; } /* Set data flag */ void ct_set_df (t_bool timchk) { if (ct_df && timchk) /* flag still set? */ ct_srb |= SRB_TIM; ct_df = 1; /* set data flag */ if (ct_sra & SRA_IE) /* if ie, int req */ int_req |= INT_CT; return; } /* Read character */ t_bool ct_read_char (void) { if (ct_bptr < ct_blnt) { /* more chars? */ ct_db = ct_xb[ct_bptr++]; return TRUE; } ct_db = 0; ct_srb |= SRB_CRC; /* overrun */ return FALSE; } /* Test if controller busy */ UNIT *ct_busy (void) { uint32 u; UNIT *uptr; for (u = 0; u < CT_NUMDR; u++) { /* loop thru units */ uptr = ct_dev.units + u; if (sim_is_active (uptr)) return uptr; } return NULL; } /* Calculate CRC on buffer */ uint32 ct_crc (uint8 *buf, uint32 cnt) { uint32 crc, i, j; crc = 0; for (i = 0; i < cnt; i++) { crc = crc ^ (((uint32) buf[i]) << 8); for (j = 0; j < 8; j++) { if (crc & 1) crc = (crc >> 1) ^ 0xA001; else crc = crc >> 1; } } return crc; } /* Map error status */ t_stat ct_map_err (UNIT *uptr, t_stat st) { switch (st) { case MTSE_FMT: /* illegal fmt */ case MTSE_UNATT: /* unattached */ ct_srb |= SRB_CRC; case MTSE_OK: /* no error */ return SCPE_IERR; /* never get here! */ case MTSE_TMK: /* end of file */ ct_srb |= SRB_EOF; break; case MTSE_IOERR: /* IO error */ ct_srb |= SRB_CRC; /* set crc err */ if (ct_stopioe) return SCPE_IOERR; break; case MTSE_INVRL: /* invalid rec lnt */ ct_srb |= SRB_CRC; /* set crc err */ return SCPE_MTRLNT; case MTSE_RECE: /* record in error */ case MTSE_EOM: /* end of medium */ ct_srb |= SRB_CRC; /* set crc err */ break; case MTSE_BOT: /* reverse into BOT */ ct_srb |= SRB_BEOT; /* set BOT */ break; case MTSE_WRP: /* write protect */ ct_srb |= SRB_WLE; /* set wlk err */ break; } return SCPE_OK; } /* Reset routine */ t_stat ct_reset (DEVICE *dptr) { uint32 u; UNIT *uptr; ct_sra = 0; ct_srb = 0; ct_df = 0; ct_db = 0; ct_write = 0; ct_bptr = 0; ct_blnt = 0; int_req = int_req & ~INT_CT; /* clear interrupt */ for (u = 0; u < CT_NUMDR; u++) { /* loop thru units */ uptr = ct_dev.units + u; sim_cancel (uptr); /* cancel activity */ sim_tape_reset (uptr); /* reset tape */ } if (ct_xb == NULL) ct_xb = (uint8 *) calloc (CT_MAXFR + 2, sizeof (uint8)); if (ct_xb == NULL) return SCPE_MEM; return SCPE_OK; } /* Attach routine */ t_stat ct_attach (UNIT *uptr, CONST char *cptr) { t_stat r; r = sim_tape_attach (uptr, cptr); if (r != SCPE_OK) return r; ct_updsta (NULL); uptr->UST = 0; return r; } /* Detach routine */ t_stat ct_detach (UNIT* uptr) { t_stat r; if (!(uptr->flags & UNIT_ATT)) /* check attached */ return SCPE_OK; r = sim_tape_detach (uptr); ct_updsta (NULL); uptr->UST = 0; return r; } /* Bootstrap routine */ #define BOOT_START 04000 #define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) static const uint16 boot_rom[] = { 01237, /* BOOT, TAD M50 /change CRC to REW */ 01206, /* CRCCHK, TAD L260 /crc op */ 06704, /* KLSA /load op */ 06706, /* KGOA /start */ 06703, /* KSBF /ready? */ 05204, /* RDCOD, JMP .-1 /loop */ 07264, /* L260, CML STA RAL /L = 1, AC = halt */ 06702, /* KSEN /error? */ 07610, /* SKP CLA /halt on any error */ 03211, /* DCA . /except REW or FFG */ 03636, /* DCA I PTR /TAD I PTR mustn't change L */ 01205, /* TAD RDCOD /read op */ 06704, /* KLSA /load op */ 06706, /* KGOA /start */ 06701, /* LOOP, KSDF /data ready? */ 05216, /* JMP .-1 /loop */ 07002, /* BSW /to upper 6b */ 07430, /* SZL /second byte? */ 01636, /* TAD I PTR /yes */ 07022, /* CML BSW /swap back */ 03636, /* DCA I PTR /store in mem */ 07420, /* SNL /done with both bytes? */ 02236, /* ISZ PTR /yes, bump mem ptr */ 02235, /* ISZ KNT /done with record? */ 05215, /* JMP LOOP /next byte */ 07346, /* STA CLL RTL */ 07002, /* BSW /AC = 7757 */ 03235, /* STA KNT /now read 200 byte record */ 05201, /* JMP CRCCHK /go check CRC */ 07737, /* KNT, 7737 /1's compl of byte count */ 03557, /* PTR, 3557 /load point */ 07730, /* M50, 7730 /CLA SPA SZL */ }; t_stat ct_boot (int32 unitno, DEVICE *dptr) { size_t i; extern uint16 M[]; if ((ct_dib.dev != DEV_CT) || unitno) /* only std devno */ return STOP_NOTSTD; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; cpu_set_bootpc (BOOT_START); return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | /* pdp8_defs.h: PDP-8 simulator definitions Copyright (c) 1993-2016, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 18-Sep-16 RMS Added support for 16 additional terminals 18-Sep-13 RMS Added set_bootpc prototype 18-Apr-12 RMS Removed separate timer for additional terminals; Added clock_cosched prototype 22-May-10 RMS Added check for 64b definitions 21-Aug-07 RMS Added FPP8 support 13-Dec-06 RMS Added TA8E support 30-Oct-06 RMS Added infinite loop stop 13-Oct-03 RMS Added TSC8-75 support 04-Oct-02 RMS Added variable device number support 20-Jan-02 RMS Fixed bug in TTx interrupt enable initialization 25-Nov-01 RMS Added RL8A support 16-Sep-01 RMS Added multiple KL support 18-Mar-01 RMS Added DF32 support 15-Feb-01 RMS Added DECtape support 14-Apr-99 RMS Changed t_addr to unsigned 19-Mar-95 RMS Added dynamic memory size 02-May-94 RMS Added non-existent memory handling The author gratefully acknowledges the help of Max Burnet, Richie Lary, and Bill Haygood in resolving questions about the PDP-8 */ #ifndef PDP8_DEFS_H_ #define PDP8_DEFS_H_ 0 #include "sim_defs.h" /* simulator defns */ #if defined(USE_INT64) || defined(USE_ADDR64) #error "PDP-8 does not support 64b values!" #endif /* Simulator stop codes */ #define STOP_RSRV 1 /* must be 1 */ #define STOP_HALT 2 /* HALT */ #define STOP_IBKPT 3 /* breakpoint */ #define STOP_OPBKPT 4 /* Opcode/Instruction breakpoint */ #define STOP_NOTSTD 5 /* non-std devno */ #define STOP_DTOFF 6 /* DECtape off reel */ #define STOP_LOOP 7 /* infinite loop */ /* Memory */ #define MAXMEMSIZE 32768 /* max memory size */ #define MEMSIZE (cpu_unit.capac) /* actual memory size */ #define ADDRMASK (MAXMEMSIZE - 1) /* address mask */ #define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) /* IOT subroutine return codes */ #define IOT_V_SKP 12 /* skip */ #define IOT_V_REASON 13 /* reason */ #define IOT_SKP (1 << IOT_V_SKP) #define IOT_REASON (1 << IOT_V_REASON) #define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ /* Timers */ #define TMR_CLK 0 /* timer 0 = clock */ /* Device information block */ #define DEV_MAXBLK 8 /* max dev block */ #define DEV_MAX 64 /* total devices */ typedef struct { uint32 dev; /* device number */ int32 (*dsp)(int32 IR, int32 dat); /* dispatch */ } DIB_DSP; typedef struct { uint32 dev; /* base dev number */ uint32 num; /* number of slots */ int32 (*dsp[DEV_MAXBLK])(int32 IR, int32 dat); DIB_DSP *dsp_tbl; /* optional table */ } DIB; /* Standard device numbers */ #define DEV_PTR 001 /* paper tape reader */ #define DEV_PTP 002 /* paper tape punch */ #define DEV_TTI 003 /* console input */ #define DEV_TTO 004 /* console output */ #define DEV_CLK 013 /* clock */ #define DEV_TSC 036 #define DEV_KJ8 040 /* extra terminals */ #define DEV_FPP 055 /* floating point */ #define DEV_DF 060 /* DF32 */ #define DEV_RF 060 /* RF08 */ #define DEV_RL 060 /* RL8A */ #define DEV_LPT 066 /* line printer */ #define DEV_MT 070 /* TM8E */ #define DEV_CT 070 /* TA8E */ #define DEV_RK 074 /* RK8E */ #define DEV_RX 075 /* RX8E/RX28 */ #define DEV_DTA 076 /* TC08 */ #define DEV_TD8E 077 /* TD8E */ /* Extra PTO8/KL8JA devices */ #define DEV_TTI1 040 #define DEV_TTO1 041 #define DEV_TTI2 042 #define DEV_TTO2 043 #define DEV_TTI3 044 #define DEV_TTO3 045 #define DEV_TTI4 046 #define DEV_TTO4 047 #define DEV_TTI5 034 #define DEV_TTO5 035 #define DEV_TTI6 011 #define DEV_TTO6 012 #define DEV_TTI7 030 #define DEV_TTO7 031 #define DEV_TTI8 032 #define DEV_TTO8 033 #define DEV_TTI9 050 #define DEV_TTO9 051 #define DEV_TTI10 052 #define DEV_TTO10 053 #define DEV_TTI11 054 #define DEV_TTO11 055 /* conflict: FPP */ #define DEV_TTI12 056 /* conflict: FPP */ #define DEV_TTO12 057 #define DEV_TTI13 070 /* conflict: CT, MT */ #define DEV_TTO13 071 #define DEV_TTI14 036 /* conflict: TSC */ #define DEV_TTO14 037 #define DEV_TTI15 072 #define DEV_TTO15 073 #define DEV_TTI16 006 #define DEV_TTO16 007 /* Interrupt flags The interrupt flags consist of three groups: 1. Devices with individual interrupt enables. These record their interrupt requests in device_done and their enables in device_enable, and must occupy the low bit positions. 2. Devices without interrupt enables. These record their interrupt requests directly in int_req, and must occupy the middle bit positions. 3. Overhead. These exist only in int_req and must occupy the high bit positions. Because the PDP-8 does not have priority interrupts, the order of devices within groups does not matter. Note: all extra KL input and output interrupts must be assigned to contiguous bits. */ #define INT_V_START 0 /* enable start */ #define INT_V_LPT (INT_V_START+0) /* line printer */ #define INT_V_PTP (INT_V_START+1) /* tape punch */ #define INT_V_PTR (INT_V_START+2) /* tape reader */ #define INT_V_TTO (INT_V_START+3) /* terminal */ #define INT_V_TTI (INT_V_START+4) /* keyboard */ #define INT_V_CLK (INT_V_START+5) /* clock */ #define INT_V_TTO1 (INT_V_START+6) /* tto1 */ //#define INT_V_TTO2 (INT_V_START+7) /* tto2 */ //#define INT_V_TTO3 (INT_V_START+8) /* tto3 */ //#define INT_V_TTO4 (INT_V_START+9) /* tto4 */ #define INT_V_TTI1 (INT_V_START+10) /* tti1 */ //#define INT_V_TTI2 (INT_V_START+11) /* tti2 */ //#define INT_V_TTI3 (INT_V_START+12) /* tti3 */ //#define INT_V_TTI4 (INT_V_START+13) /* tti4 */ #define INT_V_DIRECT (INT_V_START+14) /* direct start */ #define INT_V_RX (INT_V_DIRECT+0) /* RX8E */ #define INT_V_RK (INT_V_DIRECT+1) /* RK8E */ #define INT_V_RF (INT_V_DIRECT+2) /* RF08 */ #define INT_V_DF (INT_V_DIRECT+3) /* DF32 */ #define INT_V_MT (INT_V_DIRECT+4) /* TM8E */ #define INT_V_DTA (INT_V_DIRECT+5) /* TC08 */ #define INT_V_RL (INT_V_DIRECT+6) /* RL8A */ #define INT_V_CT (INT_V_DIRECT+7) /* TA8E int */ #define INT_V_PWR (INT_V_DIRECT+8) /* power int */ #define INT_V_UF (INT_V_DIRECT+9) /* user int */ #define INT_V_TSC (INT_V_DIRECT+10) /* TSC8-75 int */ #define INT_V_FPP (INT_V_DIRECT+11) /* FPP8 */ #define INT_V_OVHD (INT_V_DIRECT+12) /* overhead start */ #define INT_V_NO_ION_PENDING (INT_V_OVHD+0) /* ion pending */ #define INT_V_NO_CIF_PENDING (INT_V_OVHD+1) /* cif pending */ #define INT_V_ION (INT_V_OVHD+2) /* interrupts on */ #define INT_LPT (1 << INT_V_LPT) #define INT_PTP (1 << INT_V_PTP) #define INT_PTR (1 << INT_V_PTR) #define INT_TTO (1 << INT_V_TTO) #define INT_TTI (1 << INT_V_TTI) #define INT_CLK (1 << INT_V_CLK) #define INT_TTO1 (1 << INT_V_TTO1) //#define INT_TTO2 (1 << INT_V_TTO2) //#define INT_TTO3 (1 << INT_V_TTO3) //#define INT_TTO4 (1 << INT_V_TTO4) #define INT_TTI1 (1 << INT_V_TTI1) //#define INT_TTI2 (1 << INT_V_TTI2) //#define INT_TTI3 (1 << INT_V_TTI3) //#define INT_TTI4 (1 << INT_V_TTI4) #define INT_RX (1 << INT_V_RX) #define INT_RK (1 << INT_V_RK) #define INT_RF (1 << INT_V_RF) #define INT_DF (1 << INT_V_DF) #define INT_MT (1 << INT_V_MT) #define INT_DTA (1 << INT_V_DTA) #define INT_RL (1 << INT_V_RL) #define INT_CT (1 << INT_V_CT) #define INT_PWR (1 << INT_V_PWR) #define INT_UF (1 << INT_V_UF) #define INT_TSC (1 << INT_V_TSC) #define INT_FPP (1 << INT_V_FPP) #define INT_NO_ION_PENDING (1 << INT_V_NO_ION_PENDING) #define INT_NO_CIF_PENDING (1 << INT_V_NO_CIF_PENDING) #define INT_ION (1 << INT_V_ION) #define INT_DEV_ENABLE ((1 << INT_V_DIRECT) - 1) /* devices w/enables */ #define INT_ALL ((1 << INT_V_OVHD) - 1) /* all interrupts */ #define INT_INIT_ENABLE (INT_TTI+INT_TTO+INT_PTR+INT_PTP+INT_LPT) | \ (INT_TTI1+INT_TTO1) #define INT_PENDING (INT_ION+INT_NO_CIF_PENDING+INT_NO_ION_PENDING) #define INT_UPDATE ((int_req & ~INT_DEV_ENABLE) | (dev_done & int_enable)) /* Function prototypes */ t_stat set_dev (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat show_dev (FILE *st, UNIT *uptr, int32 val, CONST void *desc); void cpu_set_bootpc (int32 pc); #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | /* pdp8_df.c: DF32 fixed head disk simulator Copyright (c) 1993-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. df DF32 fixed head disk 17-Sep-13 RMS Changed to use central set_bootpc routine 03-Sep-13 RMS Added explicit void * cast 15-May-06 RMS Fixed bug in autosize attach (Dave Gesswein) 07-Jan-06 RMS Fixed unaligned register access bug (Doug Carman) 04-Jan-04 RMS Changed sim_fsize calling sequence 26-Oct-03 RMS Cleaned up buffer copy code 26-Jul-03 RMS Fixed bug in set size routine 14-Mar-03 RMS Fixed variable platter interaction with save/restore 03-Mar-03 RMS Fixed autosizing 02-Feb-03 RMS Added variable platter and autosizing support 04-Oct-02 RMS Added DIBs, device number support 28-Nov-01 RMS Added RL8A support 25-Apr-01 RMS Added device enable/disable support The DF32 is a head-per-track disk. It uses the three cycle data break facility. To minimize overhead, the entire DF32 is buffered in memory. Two timing parameters are provided: df_time Interword timing, must be non-zero df_burst Burst mode, if 0, DMA occurs cycle by cycle; otherwise, DMA occurs in a burst */ #include "pdp8_defs.h" #include <math.h> #define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ #define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */ #define UNIT_M_PLAT 03 #define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) #define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1) #define UNIT_AUTO (1 << UNIT_V_AUTO) #define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) /* Constants */ #define DF_NUMWD 2048 /* words/track */ #define DF_NUMTR 16 /* tracks/disk */ #define DF_DKSIZE (DF_NUMTR * DF_NUMWD) /* words/disk */ #define DF_NUMDK 4 /* disks/controller */ #define DF_WC 07750 /* word count */ #define DF_MA 07751 /* mem address */ #define DF_WMASK (DF_NUMWD - 1) /* word mask */ /* Parameters in the unit descriptor */ #define FUNC u4 /* function */ #define DF_READ 2 /* read */ #define DF_WRITE 4 /* write */ /* Status register */ #define DFS_PCA 04000 /* photocell status */ #define DFS_DEX 03700 /* disk addr extension */ #define DFS_MEX 00070 /* mem addr extension */ #define DFS_DRL 00004 /* data late error */ #define DFS_WLS 00002 /* write lock error */ #define DFS_NXD 00002 /* non-existent disk */ #define DFS_PER 00001 /* parity error */ #define DFS_ERR (DFS_DRL | DFS_WLS | DFS_PER) #define DFS_V_DEX 6 #define DFS_V_MEX 3 #define GET_MEX(x) (((x) & DFS_MEX) << (12 - DFS_V_MEX)) #define GET_DEX(x) (((x) & DFS_DEX) << (12 - DFS_V_DEX)) #define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ ((double) DF_NUMWD))) #define UPDATE_PCELL if (GET_POS (df_time) < 6) df_sta = df_sta | DFS_PCA; \ else df_sta = df_sta & ~DFS_PCA extern uint16 M[]; extern int32 int_req, stop_inst; extern UNIT cpu_unit; int32 df_sta = 0; /* status register */ int32 df_da = 0; /* disk address */ int32 df_done = 0; /* done flag */ int32 df_wlk = 0; /* write lock */ int32 df_time = 10; /* inter-word time */ int32 df_burst = 1; /* burst mode flag */ int32 df_stopioe = 1; /* stop on error */ int32 df60 (int32 IR, int32 AC); int32 df61 (int32 IR, int32 AC); int32 df62 (int32 IR, int32 AC); t_stat df_svc (UNIT *uptr); t_stat pcell_svc (UNIT *uptr); t_stat df_reset (DEVICE *dptr); t_stat df_boot (int32 unitno, DEVICE *dptr); t_stat df_attach (UNIT *uptr, CONST char *cptr); t_stat df_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc); /* DF32 data structures df_dev RF device descriptor df_unit RF unit descriptor pcell_unit photocell timing unit (orphan) df_reg RF register list */ DIB df_dib = { DEV_DF, 3, { &df60, &df61, &df62 } }; UNIT df_unit = { UDATA (&df_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, DF_DKSIZE) }; REG df_reg[] = { { ORDATAD (STA, df_sta, 12, "status, disk and memory address extension") }, { ORDATAD (DA, df_da, 12, "low order disk address") }, { ORDATAD (WC, M[DF_WC], 12, "word count (in memory)"), REG_FIT }, { ORDATAD (MA, M[DF_MA], 12, "memory address (in memory)"), REG_FIT }, { FLDATAD (DONE, df_done, 0, "device done flag") }, { FLDATAD (INT, int_req, INT_V_DF, "interrupt pending flag") }, { ORDATAD (WLS, df_wlk, 8, "write lock switches") }, { DRDATAD (TIME, df_time, 24, "rotational delay, per word"), REG_NZ + PV_LEFT }, { FLDATAD (BURST, df_burst, 0, "burst flag") }, { FLDATAD (STOP_IOE, df_stopioe, 0, "stop on I/O error") }, { DRDATA (CAPAC, df_unit.capac, 18), REG_HRO }, { ORDATA (DEVNUM, df_dib.dev, 6), REG_HRO }, { NULL } }; MTAB df_mod[] = { { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &df_set_size }, { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &df_set_size }, { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &df_set_size }, { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &df_set_size }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { 0 } }; DEVICE df_dev = { "DF", &df_unit, df_reg, df_mod, 1, 8, 17, 1, 8, 12, NULL, NULL, &df_reset, &df_boot, &df_attach, NULL, &df_dib, DEV_DISABLE }; /* IOT routines */ int32 df60 (int32 IR, int32 AC) { int32 t; int32 pulse = IR & 07; UPDATE_PCELL; /* update photocell */ if (pulse & 1) { /* DCMA */ df_da = 0; /* clear disk addr */ df_done = 0; /* clear done */ df_sta = df_sta & ~DFS_ERR; /* clear errors */ int_req = int_req & ~INT_DF; /* clear int req */ } if (pulse & 6) { /* DMAR, DMAW */ df_da = df_da | AC; /* disk addr |= AC */ df_unit.FUNC = pulse & ~1; /* save function */ t = (df_da & DF_WMASK) - GET_POS (df_time); /* delta to new loc */ if (t < 0) /* wrap around? */ t = t + DF_NUMWD; sim_activate (&df_unit, t * df_time); /* schedule op */ AC = 0; /* clear AC */ } return AC; } /* Based on the hardware implementation. DEAL and DEAC work as follows: 6615 pulse 1 = clear df_sta<dex,mex> pulse 4 = df_sta = df_sta | AC<dex,mex> AC = AC | old_df_sta 6616 pulse 2 = clear AC, skip if address confirmed pulse 4 = df_sta = df_sta | AC<dex,mex> = 0 (nop) AC = AC | old_df_sta */ int32 df61 (int32 IR, int32 AC) { int32 old_df_sta = df_sta; int32 pulse = IR & 07; UPDATE_PCELL; /* update photocell */ if (pulse & 1) /* DCEA */ df_sta = df_sta & ~(DFS_DEX | DFS_MEX); /* clear dex, mex */ if (pulse & 2) /* DSAC */ AC = ((df_da & DF_WMASK) == GET_POS (df_time))? IOT_SKP: 0; if (pulse & 4) { df_sta = df_sta | (AC & (DFS_DEX | DFS_MEX)); /* DEAL */ AC = AC | old_df_sta; /* DEAC */ } return AC; } int32 df62 (int32 IR, int32 AC) { int32 pulse = IR & 07; UPDATE_PCELL; /* update photocell */ if (pulse & 1) { /* DFSE */ if ((df_sta & DFS_ERR) == 0) AC = AC | IOT_SKP; } if (pulse & 2) { /* DFSC */ if (pulse & 4) /* for DMAC */ AC = AC & ~07777; else if (df_done) AC = AC | IOT_SKP; } if (pulse & 4) /* DMAC */ AC = AC | df_da; return AC; } /* Unit service Note that for reads and writes, memory addresses wrap around in the current field. This code assumes the entire disk is buffered. */ t_stat df_svc (UNIT *uptr) { int32 pa, t, mex; uint32 da; int16 *fbuf = (int16 *) uptr->filebuf; UPDATE_PCELL; /* update photocell */ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ df_done = 1; int_req = int_req | INT_DF; /* update int req */ return IORETURN (df_stopioe, SCPE_UNATT); } mex = GET_MEX (df_sta); da = GET_DEX (df_sta) | df_da; /* form disk addr */ do { if (da >= uptr->capac) { /* nx disk addr? */ df_sta = df_sta | DFS_NXD; break; } M[DF_WC] = (M[DF_WC] + 1) & 07777; /* incr word count */ M[DF_MA] = (M[DF_MA] + 1) & 07777; /* incr mem addr */ pa = mex | M[DF_MA]; /* add extension */ if (uptr->FUNC == DF_READ) { /* read? */ if (MEM_ADDR_OK (pa)) M[pa] = fbuf[da]; /* if !nxm, read wd */ } else { /* write */ t = (da >> 14) & 07; /* check wr lock */ if ((df_wlk >> t) & 1) /* locked? set err */ df_sta = df_sta | DFS_WLS; else { /* not locked */ fbuf[da] = M[pa]; /* write word */ if (da >= uptr->hwmark) uptr->hwmark = da + 1; } } da = (da + 1) & 0377777; /* incr disk addr */ } while ((M[DF_WC] != 0) && (df_burst != 0)); /* brk if wc, no brst */ if ((M[DF_WC] != 0) && ((df_sta & DFS_ERR) == 0)) /* more to do? */ sim_activate (&df_unit, df_time); /* sched next */ else { if (uptr->FUNC != DF_READ) da = (da - 1) & 0377777; df_done = 1; /* done */ int_req = int_req | INT_DF; /* update int req */ } df_sta = (df_sta & ~DFS_DEX) | ((da >> (12 - DFS_V_DEX)) & DFS_DEX); df_da = da & 07777; /* separate disk addr */ return SCPE_OK; } /* Reset routine */ t_stat df_reset (DEVICE *dptr) { df_sta = df_da = 0; df_done = 1; int_req = int_req & ~INT_DF; /* clear interrupt */ sim_cancel (&df_unit); return SCPE_OK; } /* Bootstrap routine */ #define OS8_START 07750 #define OS8_LEN (sizeof (os8_rom) / sizeof (int16)) #define DM4_START 00200 #define DM4_LEN (sizeof (dm4_rom) / sizeof (int16)) static const uint16 os8_rom[] = { 07600, /* 7750, CLA CLL ; also word count */ 06603, /* 7751, DMAR ; also address */ 06622, /* 7752, DFSC ; done? */ 05352, /* 7753, JMP .-1 ; no */ 05752 /* 7754, JMP @.-2 ; enter boot */ }; static const uint16 dm4_rom[] = { 00200, 07600, /* 0200, CLA CLL */ 00201, 06603, /* 0201, DMAR ; read */ 00202, 06622, /* 0202, DFSC ; done? */ 00203, 05202, /* 0203, JMP .-1 ; no */ 00204, 05600, /* 0204, JMP @.-4 ; enter boot */ 07750, 07576, /* 7750, 7576 ; word count */ 07751, 07576 /* 7751, 7576 ; address */ }; t_stat df_boot (int32 unitno, DEVICE *dptr) { size_t i; if (sim_switches & SWMASK ('D')) { for (i = 0; i < DM4_LEN; i = i + 2) M[dm4_rom[i]] = dm4_rom[i + 1]; cpu_set_bootpc (DM4_START); } else { for (i = 0; i < OS8_LEN; i++) M[OS8_START + i] = os8_rom[i]; cpu_set_bootpc (OS8_START); } return SCPE_OK; } /* Attach routine */ t_stat df_attach (UNIT *uptr, CONST char *cptr) { uint32 p, sz; uint32 ds_bytes = DF_DKSIZE * sizeof (int16); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) { p = (sz + ds_bytes - 1) / ds_bytes; if (p >= DF_NUMDK) p = DF_NUMDK - 1; uptr->flags = (uptr->flags & ~UNIT_PLAT) | (p << UNIT_V_PLAT); } uptr->capac = UNIT_GETP (uptr->flags) * DF_DKSIZE; return attach_unit (uptr, cptr); } /* Change disk size */ t_stat df_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { if (val < 0) return SCPE_IERR; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; uptr->capac = UNIT_GETP (val) * DF_DKSIZE; uptr->flags = uptr->flags & ~UNIT_AUTO; return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 | /* pdp8_dt.c: PDP-8 DECtape simulator Copyright (c) 1993-2017, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. dt TC08/TU56 DECtape 15-Mar-17 RMS Fixed dt_seterr to clear successor states 17-Sep-13 RMS Changed to use central set_bootpc routine 23-Jun-06 RMS Fixed switch conflict in ATTACH 07-Jan-06 RMS Fixed unaligned register access bug (Doug Carman) 16-Aug-05 RMS Fixed C++ declaration and cast problems 25-Jan-04 RMS Revised for device debug support 09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR 18-Oct-03 RMS Fixed bugs in read all, tightened timing 25-Apr-03 RMS Revised for extended file support 14-Mar-03 RMS Fixed sizing interaction with save/restore 17-Oct-02 RMS Fixed bug in end of reel logic 04-Oct-02 RMS Added DIB, device number support 12-Sep-02 RMS Added support for 16b format 30-May-02 RMS Widened POS to 32b 06-Jan-02 RMS Changed enable/disable support 30-Nov-01 RMS Added read only unit, extended SET/SHOW support 24-Nov-01 RMS Changed POS, STATT, LASTT, FLG to arrays 29-Aug-01 RMS Added casts to PDP-18b packup routine 17-Jul-01 RMS Moved function prototype 11-May-01 RMS Fixed bug in reset 25-Apr-01 RMS Added device enable/disable support 18-Apr-01 RMS Changed to rewind tape before boot 19-Mar-01 RMS Changed bootstrap to support 4k disk monitor 15-Mar-01 RMS Added 129th word to PDP-8 format PDP-8 DECtapes are represented in memory by fixed length buffer of 16b words. Three file formats are supported: 18b/36b 256 words per block [256 x 18b] 16b 256 words per block [256 x 16b] 12b 129 words per block [129 x 12b] When a 16b or 18/36bb DECtape file is read in, it is converted to 12b format. DECtape motion is measured in 3b lines. Time between lines is 33.33us. Tape density is nominally 300 lines per inch. The format of a DECtape (as taken from the TD8E formatter) is: reverse end zone 8192 reverse end zone codes ~ 10 feet reverse buffer 200 interblock codes block 0 : block n forward buffer 200 interblock codes forward end zone 8192 forward end zone codes ~ 10 feet A block consists of five 18b header words, a tape-specific number of data words, and five 18b trailer words. All systems except the PDP-8 use a standard block length of 256 words; the PDP-8 uses a standard block length of 86 words (x 18b = 129 words x 12b). Because a DECtape file only contains data, the simulator cannot support write timing and mark track and can only do a limited implementation of read all and write all. Read all assumes that the tape has been conventionally written forward: header word 0 0 header word 1 block number (for forward reads) header words 2,3 0 header word 4 checksum (for reverse reads) : trailer word 4 checksum (for forward reads) trailer words 3,2 0 trailer word 1 block number (for reverse reads) trailer word 0 0 Write all writes only the data words and dumps the non-data words in the bit bucket. */ #include "pdp8_defs.h" #define DT_NUMDR 8 /* #drives */ #define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ #define UNIT_V_8FMT (UNIT_V_UF + 1) /* 12b format */ #define UNIT_V_11FMT (UNIT_V_UF + 2) /* 16b format */ #define UNIT_WLK (1 << UNIT_V_WLK) #define UNIT_8FMT (1 << UNIT_V_8FMT) #define UNIT_11FMT (1 << UNIT_V_11FMT) #define STATE u3 /* unit state */ #define LASTT u4 /* last time update */ #define WRITTEN u5 /* device buffer is dirty and needs flushing */ #define DT_WC 07754 /* word count */ #define DT_CA 07755 /* current addr */ #define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ /* System independent DECtape constants */ #define DT_LPERMC 6 /* lines per mark track */ #define DT_BLKWD 1 /* blk no word in h/t */ #define DT_CSMWD 4 /* checksum word in h/t */ #define DT_HTWRD 5 /* header/trailer words */ #define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ #define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ #define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ #define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ #define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ /* 16b, 18b, 36b DECtape constants */ #define D18_WSIZE 6 /* word size in lines */ #define D18_BSIZE 384 /* block size in 12b */ #define D18_TSIZE 578 /* tape size */ #define D18_LPERB (DT_HTLIN + (D18_BSIZE * DT_WSIZE) + DT_HTLIN) #define D18_FWDEZ (DT_EZLIN + (D18_LPERB * D18_TSIZE)) #define D18_CAPAC (D18_TSIZE * D18_BSIZE) /* tape capacity */ #define D18_NBSIZE ((D18_BSIZE * D8_WSIZE) / D18_WSIZE) #define D18_FILSIZ (D18_NBSIZE * D18_TSIZE * sizeof (int32)) #define D11_FILSIZ (D18_NBSIZE * D18_TSIZE * sizeof (int16)) /* 12b DECtape constants */ #define D8_WSIZE 4 /* word size in lines */ #define D8_BSIZE 129 /* block size in 12b */ #define D8_TSIZE 1474 /* tape size */ #define D8_LPERB (DT_HTLIN + (D8_BSIZE * DT_WSIZE) + DT_HTLIN) #define D8_FWDEZ (DT_EZLIN + (D8_LPERB * D8_TSIZE)) #define D8_CAPAC (D8_TSIZE * D8_BSIZE) /* tape capacity */ #define D8_FILSIZ (D8_CAPAC * sizeof (int16)) /* This controller */ #define DT_CAPAC D8_CAPAC /* default */ #define DT_WSIZE D8_WSIZE /* Calculated constants, per unit */ #define DTU_BSIZE(u) (((u)->flags & UNIT_8FMT)? D8_BSIZE: D18_BSIZE) #define DTU_TSIZE(u) (((u)->flags & UNIT_8FMT)? D8_TSIZE: D18_TSIZE) #define DTU_LPERB(u) (((u)->flags & UNIT_8FMT)? D8_LPERB: D18_LPERB) #define DTU_FWDEZ(u) (((u)->flags & UNIT_8FMT)? D8_FWDEZ: D18_FWDEZ) #define DTU_CAPAC(u) (((u)->flags & UNIT_8FMT)? D8_CAPAC: D18_CAPAC) #define DT_LIN2BL(p,u) (((p) - DT_EZLIN) / DTU_LPERB (u)) #define DT_LIN2OF(p,u) (((p) - DT_EZLIN) % DTU_LPERB (u)) #define DT_LIN2WD(p,u) ((DT_LIN2OF (p,u) - DT_HTLIN) / DT_WSIZE) #define DT_BLK2LN(p,u) (((p) * DTU_LPERB (u)) + DT_EZLIN) #define DT_QREZ(u) (((u)->pos) < DT_EZLIN) #define DT_QFEZ(u) (((u)->pos) >= ((uint32) DTU_FWDEZ (u))) #define DT_QEZ(u) (DT_QREZ (u) || DT_QFEZ (u)) /* Status register A */ #define DTA_V_UNIT 9 /* unit select */ #define DTA_M_UNIT 07 #define DTA_UNIT (DTA_M_UNIT << DTA_V_UNIT) #define DTA_V_MOT 7 /* motion */ #define DTA_M_MOT 03 #define DTA_V_MODE 6 /* mode */ #define DTA_V_FNC 3 /* function */ #define DTA_M_FNC 07 #define FNC_MOVE 00 /* move */ #define FNC_SRCH 01 /* search */ #define FNC_READ 02 /* read */ #define FNC_RALL 03 /* read all */ #define FNC_WRIT 04 /* write */ #define FNC_WALL 05 /* write all */ #define FNC_WMRK 06 /* write timing */ #define DTA_V_ENB 2 /* int enable */ #define DTA_V_CERF 1 /* clr error flag */ #define DTA_V_CDTF 0 /* clr DECtape flag */ #define DTA_FWDRV (1u << (DTA_V_MOT + 1)) #define DTA_STSTP (1u << DTA_V_MOT) #define DTA_MODE (1u << DTA_V_MODE) #define DTA_ENB (1u << DTA_V_ENB) #define DTA_CERF (1u << DTA_V_CERF) #define DTA_CDTF (1u << DTA_V_CDTF) #define DTA_RW (07777 & ~(DTA_CERF | DTA_CDTF)) #define DTA_GETUNIT(x) (((x) >> DTA_V_UNIT) & DTA_M_UNIT) #define DTA_GETMOT(x) (((x) >> DTA_V_MOT) & DTA_M_MOT) #define DTA_GETFNC(x) (((x) >> DTA_V_FNC) & DTA_M_FNC) /* Status register B */ #define DTB_V_ERF 11 /* error flag */ #define DTB_V_MRK 10 /* mark trk err */ #define DTB_V_END 9 /* end zone err */ #define DTB_V_SEL 8 /* select err */ #define DTB_V_PAR 7 /* parity err */ #define DTB_V_TIM 6 /* timing err */ #define DTB_V_MEX 3 /* memory extension */ #define DTB_M_MEX 07 #define DTB_MEX (DTB_M_MEX << DTB_V_MEX) #define DTB_V_DTF 0 /* DECtape flag */ #define DTB_ERF (1u << DTB_V_ERF) #define DTB_MRK (1u << DTB_V_MRK) #define DTB_END (1u << DTB_V_END) #define DTB_SEL (1u << DTB_V_SEL) #define DTB_PAR (1u << DTB_V_PAR) #define DTB_TIM (1u << DTB_V_TIM) #define DTB_DTF (1u << DTB_V_DTF) #define DTB_ALLERR (DTB_ERF | DTB_MRK | DTB_END | DTB_SEL | \ DTB_PAR | DTB_TIM) #define DTB_GETMEX(x) (((x) & DTB_MEX) << (12 - DTB_V_MEX)) /* DECtape state */ #define DTS_V_MOT 3 /* motion */ #define DTS_M_MOT 07 #define DTS_STOP 0 /* stopped */ #define DTS_DECF 2 /* decel, fwd */ #define DTS_DECR 3 /* decel, rev */ #define DTS_ACCF 4 /* accel, fwd */ #define DTS_ACCR 5 /* accel, rev */ #define DTS_ATSF 6 /* @speed, fwd */ #define DTS_ATSR 7 /* @speed, rev */ #define DTS_DIR 01 /* dir mask */ #define DTS_V_FNC 0 /* function */ #define DTS_M_FNC 07 #define DTS_OFR 7 /* "off reel" */ #define DTS_GETMOT(x) (((x) >> DTS_V_MOT) & DTS_M_MOT) #define DTS_GETFNC(x) (((x) >> DTS_V_FNC) & DTS_M_FNC) #define DTS_V_2ND 6 /* next state */ #define DTS_V_3RD (DTS_V_2ND + DTS_V_2ND) /* next next */ #define DTS_STA(y,z) (((y) << DTS_V_MOT) | ((z) << DTS_V_FNC)) #define DTS_SETSTA(y,z) uptr->STATE = DTS_STA (y, z) #define DTS_SET2ND(y,z) uptr->STATE = (uptr->STATE & 077) | \ ((DTS_STA (y, z)) << DTS_V_2ND) #define DTS_SET3RD(y,z) uptr->STATE = (uptr->STATE & 07777) | \ ((DTS_STA (y, z)) << DTS_V_3RD) #define DTS_NXTSTA(x) (x >> DTS_V_2ND) /* Operation substates */ #define DTO_WCO 1 /* wc overflow */ #define DTO_SOB 2 /* start of block */ /* Logging */ #define LOG_MS 001 /* move, search */ #define LOG_RW 002 /* read, write */ #define LOG_BL 004 /* block # lblk */ #define DT_UPDINT if ((dtsa & DTA_ENB) && (dtsb & (DTB_ERF | DTB_DTF))) \ int_req = int_req | INT_DTA; \ else int_req = int_req & ~INT_DTA; #define ABS(x) (((x) < 0)? (-(x)): (x)) extern uint16 M[]; extern int32 int_req; extern UNIT cpu_unit; int32 dtsa = 0; /* status A */ int32 dtsb = 0; /* status B */ int32 dt_ltime = 12; /* interline time */ int32 dt_dctime = 40000; /* decel time */ int32 dt_substate = 0; int32 dt_logblk = 0; int32 dt_stopoffr = 0; int32 dt76 (int32 IR, int32 AC); int32 dt77 (int32 IR, int32 AC); t_stat dt_svc (UNIT *uptr); t_stat dt_reset (DEVICE *dptr); t_stat dt_attach (UNIT *uptr, CONST char *cptr); void dt_flush (UNIT *uptr); t_stat dt_detach (UNIT *uptr); t_stat dt_boot (int32 unitno, DEVICE *dptr); void dt_deselect (int32 oldf); void dt_newsa (int32 newf); void dt_newfnc (UNIT *uptr, int32 newsta); t_bool dt_setpos (UNIT *uptr); void dt_schedez (UNIT *uptr, int32 dir); void dt_seterr (UNIT *uptr, int32 e); int32 dt_comobv (int32 val); int32 dt_csum (UNIT *uptr, int32 blk); int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos, int32 dir); /* DT data structures dt_dev DT device descriptor dt_unit DT unit list dt_reg DT register list dt_mod DT modifier list */ DIB dt_dib = { DEV_DTA, 2, { &dt76, &dt77 } }; UNIT dt_unit[] = { { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) } }; REG dt_reg[] = { { ORDATAD (DTSA, dtsa, 12, "status register A") }, { ORDATAD (DTSB, dtsb, 12, "status register B") }, { FLDATAD (INT, int_req, INT_V_DTA, "interrupt pending flag") }, { FLDATAD (ENB, dtsa, DTA_V_ENB, "interrupt enable flag") }, { FLDATAD (DTF, dtsb, DTB_V_DTF, "DECtape flag") }, { FLDATAD (ERF, dtsb, DTB_V_ERF, "error flag") }, { ORDATAD (WC, M[DT_WC], 12, "word count (memory location 7755)"), REG_FIT }, { ORDATAD (CA, M[DT_CA], 12, "current address (memory location 7754)"), REG_FIT }, { DRDATAD (LTIME, dt_ltime, 24, "time between lines"), REG_NZ | PV_LEFT }, { DRDATAD (DCTIME, dt_dctime, 24, "time to decelerate to a full stop"), REG_NZ | PV_LEFT }, { ORDATAD (SUBSTATE, dt_substate, 2, "read/write command substate") }, { DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN }, { URDATAD (POS, dt_unit[0].pos, 10, T_ADDR_W, 0, DT_NUMDR, PV_LEFT | REG_RO, "position, in lines, units 0 to 7") }, { URDATAD (STATT, dt_unit[0].STATE, 8, 18, 0, DT_NUMDR, REG_RO, "unit state, units 0 to 7") }, { URDATA (LASTT, dt_unit[0].LASTT, 10, 32, 0, DT_NUMDR, REG_HRO) }, { FLDATAD (STOP_OFFR, dt_stopoffr, 0, "stop on off-reel error") }, { ORDATA (DEVNUM, dt_dib.dev, 6), REG_HRO }, { NULL } }; MTAB dt_mod[] = { { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, { UNIT_8FMT + UNIT_11FMT, 0, "18b", NULL, NULL }, { UNIT_8FMT + UNIT_11FMT, UNIT_8FMT, "12b", NULL, NULL }, { UNIT_8FMT + UNIT_11FMT, UNIT_11FMT, "16b", NULL, NULL }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { 0 } }; DEBTAB dt_deb[] = { { "MOTION", LOG_MS }, { "DATA", LOG_RW }, { "BLOCK", LOG_BL }, { NULL, 0 } }; DEVICE dt_dev = { "DT", dt_unit, dt_reg, dt_mod, DT_NUMDR, 8, 24, 1, 8, 12, NULL, NULL, &dt_reset, &dt_boot, &dt_attach, &dt_detach, &dt_dib, DEV_DISABLE | DEV_DEBUG, 0, dt_deb, NULL, NULL }; /* IOT routines */ int32 dt76 (int32 IR, int32 AC) { int32 pulse = IR & 07; int32 old_dtsa = dtsa, fnc; UNIT *uptr; if (pulse & 01) /* DTRA */ AC = AC | dtsa; if (pulse & 06) { /* select */ if (pulse & 02) /* DTCA */ dtsa = 0; if (pulse & 04) { /* DTXA */ if ((AC & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR; if ((AC & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF; dtsa = dtsa ^ (AC & DTA_RW); AC = 0; /* clr AC */ } if ((old_dtsa ^ dtsa) & DTA_UNIT) dt_deselect (old_dtsa); uptr = dt_dev.units + DTA_GETUNIT (dtsa); /* get unit */ fnc = DTA_GETFNC (dtsa); /* get fnc */ if (((uptr->flags) & UNIT_DIS) || /* disabled? */ (fnc >= FNC_WMRK) || /* write mark? */ ((fnc == FNC_WALL) && (uptr->flags & UNIT_WPRT)) || ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WPRT))) dt_seterr (uptr, DTB_SEL); /* select err */ else dt_newsa (dtsa); DT_UPDINT; } return AC; } int32 dt77 (int32 IR, int32 AC) { int32 pulse = IR & 07; if ((pulse & 01) && (dtsb & (DTB_ERF |DTB_DTF))) /* DTSF */ AC = IOT_SKP | AC; if (pulse & 02) /* DTRB */ AC = AC | dtsb; if (pulse & 04) { /* DTLB */ dtsb = (dtsb & ~DTB_MEX) | (AC & DTB_MEX); AC = AC & ~07777; /* clear AC */ } return AC; } /* Unit deselect */ void dt_deselect (int32 oldf) { int32 old_unit = DTA_GETUNIT (oldf); UNIT *uptr = dt_dev.units + old_unit; int32 old_mot = DTS_GETMOT (uptr->STATE); if (old_mot >= DTS_ATSF) /* at speed? */ dt_newfnc (uptr, DTS_STA (old_mot, DTS_OFR)); else if (old_mot >= DTS_ACCF) /* accelerating? */ DTS_SET2ND (DTS_ATSF | (old_mot & DTS_DIR), DTS_OFR); return; } /* Command register change 1. If change in motion, stop to start - schedule acceleration - set function as next state 2. If change in motion, start to stop - if not already decelerating (could be reversing), schedule deceleration 3. If change in direction, - if not decelerating, schedule deceleration - set accelerating (other dir) as next state - set function as next next state 4. If not accelerating or at speed, - schedule acceleration - set function as next state 5. If not yet at speed, - set function as next state 6. If at speed, - set function as current state, schedule function */ void dt_newsa (int32 newf) { int32 new_unit, prev_mot, new_fnc; int32 prev_mving, new_mving, prev_dir, new_dir; UNIT *uptr; new_unit = DTA_GETUNIT (newf); /* new, old units */ uptr = dt_dev.units + new_unit; if ((uptr->flags & UNIT_ATT) == 0) { /* new unit attached? */ dt_seterr (uptr, DTB_SEL); /* no, error */ return; } prev_mot = DTS_GETMOT (uptr->STATE); /* previous motion */ prev_mving = prev_mot != DTS_STOP; /* previous moving? */ prev_dir = prev_mot & DTS_DIR; /* previous dir? */ new_mving = (newf & DTA_STSTP) != 0; /* new moving? */ new_dir = (newf & DTA_FWDRV) != 0; /* new dir? */ new_fnc = DTA_GETFNC (newf); /* new function? */ if ((prev_mving | new_mving) == 0) /* stop to stop */ return; if (new_mving & ~prev_mving) { /* start? */ if (dt_setpos (uptr)) /* update pos */ return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* schedule acc */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ return; } if (prev_mving & ~new_mving) { /* stop? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ if (dt_setpos (uptr)) /* update pos */ return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime); /* schedule decel */ } DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ return; } if (prev_dir ^ new_dir) { /* dir chg? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ if (dt_setpos (uptr)) /* update pos */ return; sim_cancel (uptr); /* stop current */ sim_activate (uptr, dt_dctime); /* schedule decel */ } DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ DTS_SET2ND (DTS_ACCF | new_dir, 0); /* next = accel */ DTS_SET3RD (DTS_ATSF | new_dir, new_fnc); /* next next = fnc */ return; } if (prev_mot < DTS_ACCF) { /* not accel/at speed? */ if (dt_setpos (uptr)) /* update pos */ return; sim_cancel (uptr); /* cancel cur */ sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ return; } if (prev_mot < DTS_ATSF) { /* not at speed? */ DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ return; } dt_newfnc (uptr, DTS_STA (DTS_ATSF | new_dir, new_fnc));/* state = fnc */ return; } /* Schedule new DECtape function This routine is only called if - the selected unit is attached - the selected unit is at speed (forward or backward) This routine - updates the selected unit's position - updates the selected unit's state - schedules the new operation */ void dt_newfnc (UNIT *uptr, int32 newsta) { int32 fnc, dir, blk, unum, relpos, newpos; uint32 oldpos; oldpos = uptr->pos; /* save old pos */ if (dt_setpos (uptr)) /* update pos */ return; uptr->STATE = newsta; /* update state */ fnc = DTS_GETFNC (uptr->STATE); /* set variables */ dir = DTS_GETMOT (uptr->STATE) & DTS_DIR; unum = (int32) (uptr - dt_dev.units); if (oldpos == uptr->pos) /* bump pos */ uptr->pos = uptr->pos + (dir? -1: 1); blk = DT_LIN2BL (uptr->pos, uptr); if (dir? DT_QREZ (uptr): DT_QFEZ (uptr)) { /* wrong ez? */ dt_seterr (uptr, DTB_END); /* set ez flag, stop */ return; } sim_cancel (uptr); /* cancel cur op */ dt_substate = DTO_SOB; /* substate = block start */ switch (fnc) { /* case function */ case DTS_OFR: /* off reel */ if (dir) /* rev? < start */ newpos = -1000; else newpos = DTU_FWDEZ (uptr) + DT_EZLIN + 1000; /* fwd? > end */ break; case FNC_MOVE: /* move */ dt_schedez (uptr, dir); /* sched end zone */ if (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>DT%d: moving %s\n", unum, (dir? "backward": "forward")); return; /* done */ case FNC_SRCH: /* search */ if (dir) newpos = DT_BLK2LN ((DT_QFEZ (uptr)? DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; else newpos = DT_BLK2LN ((DT_QREZ (uptr)? 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); if (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>DT%d: searching %s]\n", unum, (dir? "backward": "forward")); break; case FNC_WRIT: /* write */ case FNC_READ: /* read */ case FNC_RALL: /* read all */ case FNC_WALL: /* write all */ if (DT_QEZ (uptr)) { /* in "ok" end zone? */ if (dir) newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); break; } relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { dt_seterr (uptr, DTB_SEL); return; } if (dir) newpos = DT_BLK2LN (((relpos >= (DTU_LPERB (uptr) - DT_HTLIN))? blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; else newpos = DT_BLK2LN (((relpos < DT_HTLIN)? blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); break; default: dt_seterr (uptr, DTB_SEL); /* bad state */ return; } sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); return; } /* Update DECtape position DECtape motion is modeled as a constant velocity, with linear acceleration and deceleration. The motion equations are as follows: t = time since operation started tmax = time for operation (accel, decel only) v = at speed velocity in lines (= 1/dt_ltime) Then: at speed dist = t * v accel dist = (t^2 * v) / (2 * tmax) decel dist = (((2 * t * tmax) - t^2) * v) / (2 * tmax) This routine uses the relative (integer) time, rather than the absolute (floating point) time, to allow save and restore of the start times. */ t_bool dt_setpos (UNIT *uptr) { uint32 new_time, ut, ulin, udelt; int32 mot = DTS_GETMOT (uptr->STATE); int32 unum, delta; new_time = sim_grtime (); /* current time */ ut = new_time - uptr->LASTT; /* elapsed time */ if (ut == 0) /* no time gone? exit */ return FALSE; uptr->LASTT = new_time; /* update last time */ switch (mot & ~DTS_DIR) { /* case on motion */ case DTS_STOP: /* stop */ delta = 0; break; case DTS_DECF: /* slowing */ ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime; delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt); break; case DTS_ACCF: /* accelerating */ ulin = ut / (uint32) dt_ltime; udelt = (dt_dctime - (dt_dctime >> 2)) / dt_ltime; delta = (ulin * ulin) / (2 * udelt); break; case DTS_ATSF: /* at speed */ delta = ut / (uint32) dt_ltime; break; } if (mot & DTS_DIR) /* update pos */ uptr->pos = uptr->pos - delta; else uptr->pos = uptr->pos + delta; if (((int32) uptr->pos < 0) || ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { detach_unit (uptr); /* off reel? */ uptr->STATE = uptr->pos = 0; unum = (int32) (uptr - dt_dev.units); if (unum == DTA_GETUNIT (dtsa)) /* if selected, */ dt_seterr (uptr, DTB_SEL); /* error */ return TRUE; } return FALSE; } /* Unit service Unit must be attached, detach cancels operation */ t_stat dt_svc (UNIT *uptr) { int32 mot = DTS_GETMOT (uptr->STATE); int32 dir = mot & DTS_DIR; int32 fnc = DTS_GETFNC (uptr->STATE); int16 *fbuf = (int16 *) uptr->filebuf; int32 unum = uptr - dt_dev.units; int32 blk, wrd, ma, relpos, dat; uint32 ba; /* Motion cases Decelerating - if next state != stopped, must be accel reverse Accelerating - next state must be @speed, schedule function At speed - do functional processing */ switch (mot) { case DTS_DECF: case DTS_DECR: /* decelerating */ if (dt_setpos (uptr)) /* upd pos; off reel? */ return IORETURN (dt_stopoffr, STOP_DTOFF); uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ if (uptr->STATE) /* not stopped? */ sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* must be reversing */ return SCPE_OK; case DTS_ACCF: case DTS_ACCR: /* accelerating */ dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ return SCPE_OK; case DTS_ATSF: case DTS_ATSR: /* at speed */ break; /* check function */ default: /* other */ dt_seterr (uptr, DTB_SEL); /* state error */ return SCPE_OK; } /* Functional cases Move - must be at end zone Search - transfer block number, schedule next block Off reel - detach unit (it must be deselected) */ if (dt_setpos (uptr)) /* upd pos; off reel? */ return IORETURN (dt_stopoffr, STOP_DTOFF); if (DT_QEZ (uptr)) { /* in end zone? */ dt_seterr (uptr, DTB_END); /* end zone error */ return SCPE_OK; } blk = DT_LIN2BL (uptr->pos, uptr); /* get block # */ switch (fnc) { /* at speed, check fnc */ case FNC_MOVE: /* move */ dt_seterr (uptr, DTB_END); /* end zone error */ return SCPE_OK; case FNC_SRCH: /* search */ if (dtsb & DTB_DTF) { /* DTF set? */ dt_seterr (uptr, DTB_TIM); /* timing error */ return SCPE_OK; } sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */ M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr word cnt */ ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ if (MEM_ADDR_OK (ma)) /* store block # */ M[ma] = blk & 07777; if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) dtsb = dtsb | DTB_DTF; /* set DTF */ break; case DTS_OFR: /* off reel */ detach_unit (uptr); /* must be deselected */ uptr->STATE = uptr->pos = 0; /* no visible action */ break; /* Read has four subcases Start of block, not wc ovf - check that DTF is clear, otherwise normal Normal - increment MA, WC, copy word from tape to memory if read dir != write dir, bits must be scrambled if wc overflow, next state is wc overflow if end of block, possibly set DTF, next state is start of block Wc ovf, not start of block - if end of block, possibly set DTF, next state is start of block Wc ovf, start of block - if end of block reached, timing error, otherwise, continue to next word */ case FNC_READ: /* read */ wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ switch (dt_substate) { /* case on substate */ case DTO_SOB: /* start of block */ if (dtsb & DTB_DTF) { /* DTF set? */ dt_seterr (uptr, DTB_TIM); /* timing error */ return SCPE_OK; } if (DEBUG_PRI (dt_dev, LOG_RW) || (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) fprintf (sim_deb, ">>DT%d: reading block %d %s%s\n", unum, blk, (dir? "backward": "forward"), ((dtsa & DTA_MODE)? " continuous": " ")); dt_substate = 0; /* fall through */ case 0: /* normal read */ M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ M[DT_CA] = (M[DT_CA] + 1) & 07777; ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ dat = fbuf[ba]; /* get tape word */ if (dir) /* rev? comp obv */ dat = dt_comobv (dat); if (MEM_ADDR_OK (ma)) /* mem addr legal? */ M[ma] = dat; if (M[DT_WC] == 0) /* wc ovf? */ dt_substate = DTO_WCO; /* fall through */ case DTO_WCO: /* wc ovf, not sob */ if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ sim_activate (uptr, DT_WSIZE * dt_ltime); else { dt_substate = dt_substate | DTO_SOB; sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) dtsb = dtsb | DTB_DTF; /* set DTF */ } break; case DTO_WCO | DTO_SOB: /* next block */ if (wrd == (dir? 0: DTU_BSIZE (uptr))) /* end of block? */ dt_seterr (uptr, DTB_TIM); /* timing error */ else sim_activate (uptr, DT_WSIZE * dt_ltime); break; } break; /* Write has four subcases Start of block, not wc ovf - check that DTF is clear, set block direction Normal - increment MA, WC, copy word from memory to tape if wc overflow, next state is wc overflow if end of block, possibly set DTF, next state is start of block Wc ovf, not start of block - copy 0 to tape if end of block, possibly set DTF, next state is start of block Wc ovf, start of block - schedule end zone */ case FNC_WRIT: /* write */ wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ switch (dt_substate) { /* case on substate */ case DTO_SOB: /* start block */ if (dtsb & DTB_DTF) { /* DTF set? */ dt_seterr (uptr, DTB_TIM); /* timing error */ return SCPE_OK; } if (DEBUG_PRI (dt_dev, LOG_RW) || (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) fprintf (sim_deb, ">>DT%d: writing block %d %s%s\n", unum, blk, (dir? "backward": "forward"), ((dtsa & DTA_MODE)? " continuous": " ")); dt_substate = 0; /* fall through */ case 0: /* normal write */ M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ M[DT_CA] = (M[DT_CA] + 1) & 07777; /* fall through */ case DTO_WCO: /* wc ovflo */ ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ dat = dt_substate? 0: M[ma]; /* get word */ if (dir) /* rev? comp obv */ dat = dt_comobv (dat); fbuf[ba] = dat; /* write word */ uptr->WRITTEN = TRUE; if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; if (M[DT_WC] == 0) dt_substate = DTO_WCO; if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ sim_activate (uptr, DT_WSIZE * dt_ltime); else { dt_substate = dt_substate | DTO_SOB; sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) dtsb = dtsb | DTB_DTF; /* set DTF */ } break; case DTO_WCO | DTO_SOB: /* all done */ dt_schedez (uptr, dir); /* sched end zone */ break; } break; /* Read all has two subcases Not word count overflow - increment MA, WC, copy word from tape to memory Word count overflow - schedule end zone */ case FNC_RALL: switch (dt_substate) { /* case on substate */ case 0: case DTO_SOB: /* read in progress */ if (dtsb & DTB_DTF) { /* DTF set? */ dt_seterr (uptr, DTB_TIM); /* timing error */ return SCPE_OK; } relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ M[DT_CA] = (M[DT_CA] + 1) & 07777; ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { wrd = DT_LIN2WD (uptr->pos, uptr); ba = (blk * DTU_BSIZE (uptr)) + wrd; dat = fbuf[ba]; /* get tape word */ if (dir) /* rev? comp obv */ dat = dt_comobv (dat); } else dat = dt_gethdr (uptr, blk, relpos, dir); /* get hdr */ sim_activate (uptr, DT_WSIZE * dt_ltime); if (MEM_ADDR_OK (ma)) /* mem addr legal? */ M[ma] = dat; if (M[DT_WC] == 0) dt_substate = DTO_WCO; if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) dtsb = dtsb | DTB_DTF; /* set DTF */ break; case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ dt_schedez (uptr, dir); /* sched end zone */ break; } /* end case substate */ break; /* Write all has two subcases Not word count overflow - increment MA, WC, copy word from memory to tape Word count overflow - schedule end zone */ case FNC_WALL: switch (dt_substate) { /* case on substate */ case 0: case DTO_SOB: /* read in progress */ if (dtsb & DTB_DTF) { /* DTF set? */ dt_seterr (uptr, DTB_TIM); /* timing error */ return SCPE_OK; } relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ M[DT_CA] = (M[DT_CA] + 1) & 07777; ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { dat = M[ma]; /* get mem word */ if (dir) dat = dt_comobv (dat); wrd = DT_LIN2WD (uptr->pos, uptr); ba = (blk * DTU_BSIZE (uptr)) + wrd; fbuf[ba] = dat; /* write word */ if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } /* ignore hdr */ sim_activate (uptr, DT_WSIZE * dt_ltime); if (M[DT_WC] == 0) dt_substate = DTO_WCO; if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) dtsb = dtsb | DTB_DTF; /* set DTF */ break; case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ dt_schedez (uptr, dir); /* sched end zone */ break; } /* end case substate */ break; default: dt_seterr (uptr, DTB_SEL); /* impossible state */ break; } DT_UPDINT; /* update interrupts */ return SCPE_OK; } /* Reading the header is complicated, because 18b words are being parsed out 12b at a time. The sequence of word numbers is directionally sensitive Forward Reverse Word Word Content Word Word Content (abs) (rel) (abs) (rel) 137 8 fwd csm'00 6 6 rev csm'00 138 9 0000 5 5 0000 139 10 0000 4 4 0000 140 11 0000 3 3 0000 141 12 00'lo rev blk 2 2 00'lo fwd blk 142 13 hi rev blk 1 1 hi fwd blk 143 14 0000 0 0 0000 0 0 0000 143 14 0000 1 1 0000 142 13 0000 2 2 hi fwd blk 141 12 hi rev blk 3 3 lo fwd blk'00 140 11 lo rev blk'00 4 4 0000 139 10 0000 5 5 0000 138 9 0000 6 6 0000 137 8 0000 7 7 rev csm 136 7 00'fwd csm */ int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos, int32 dir) { if (relpos >= DT_HTLIN) relpos = relpos - (DT_WSIZE * DTU_BSIZE (uptr)); if (dir) { /* reverse */ switch (relpos / DT_WSIZE) { case 6: /* rev csm */ return 077; case 2: /* lo fwd blk */ return dt_comobv ((blk & 077) << 6); case 1: /* hi fwd blk */ return dt_comobv (blk >> 6); case 12: /* hi rev blk */ return (blk >> 6) & 07777; case 11: /* lo rev blk */ return ((blk & 077) << 6); case 7: /* fwd csum */ return (dt_comobv (dt_csum (uptr, blk)) << 6); default: /* others */ return 07777; } } else { /* forward */ switch (relpos / DT_WSIZE) { case 8: /* fwd csum */ return (dt_csum (uptr, blk) << 6); case 12: /* lo rev blk */ return dt_comobv ((blk & 077) << 6); case 13: /* hi rev blk */ return dt_comobv (blk >> 6); case 2: /* hi fwd blk */ return ((blk >> 6) & 07777); case 3: /* lo fwd blk */ return ((blk & 077) << 6); case 7: /* rev csum */ return 077; default: /* others */ break; } } return 0; } /* Utility routines */ /* Set error flag */ void dt_seterr (UNIT *uptr, int32 e) { int32 mot = DTS_GETMOT (uptr->STATE); dtsa = dtsa & ~DTA_STSTP; /* clear go */ dtsb = dtsb | DTB_ERF | e; /* set error flag */ if (mot >= DTS_ACCF) { /* ~stopped or stopping? */ sim_cancel (uptr); /* cancel activity */ if (dt_setpos (uptr)) /* update position */ return; sim_activate (uptr, dt_dctime); /* sched decel */ DTS_SETSTA (DTS_DECF | (mot & DTS_DIR), 0); /* state = decel */ } else DTS_SETSTA (mot, 0); /* clear 2nd, 3rd */ DT_UPDINT; return; } /* Schedule end zone */ void dt_schedez (UNIT *uptr, int32 dir) { int32 newpos; if (dir) /* rev? rev ez */ newpos = DT_EZLIN - DT_WSIZE; else newpos = DTU_FWDEZ (uptr) + DT_WSIZE; /* fwd? fwd ez */ sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); return; } /* Complement obverse routine */ int32 dt_comobv (int32 dat) { dat = dat ^ 07777; /* compl obverse */ dat = ((dat >> 9) & 07) | ((dat >> 3) & 070) | ((dat & 070) << 3) | ((dat & 07) << 9); return dat; } /* Checksum routine */ int32 dt_csum (UNIT *uptr, int32 blk) { int16 *fbuf = (int16 *) uptr->filebuf; int32 ba = blk * DTU_BSIZE (uptr); int32 i, csum, wrd; csum = 077; /* init csum */ for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ wrd = fbuf[ba + i] ^ 07777; /* get ~word */ csum = csum ^ (wrd >> 6) ^ wrd; } return (csum & 077); } /* Reset routine */ t_stat dt_reset (DEVICE *dptr) { int32 i, prev_mot; UNIT *uptr; for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */ uptr = dt_dev.units + i; if (sim_is_running) { /* CAF? */ prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ if (dt_setpos (uptr)) /* update pos */ continue; sim_cancel (uptr); sim_activate (uptr, dt_dctime); /* sched decel */ DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); } } else { sim_cancel (uptr); /* sim reset */ uptr->STATE = 0; uptr->LASTT = sim_grtime (); } } dtsa = dtsb = 0; /* clear status */ DT_UPDINT; /* reset interrupt */ return SCPE_OK; } /* Bootstrap routine This is actually the 4K disk monitor bootstrap, which also works with OS/8. The reverse is not true - the OS/8 bootstrap doesn't work with the disk monitor. */ #define BOOT_START 0200 #define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) static const uint16 boot_rom[] = { 07600, /* 200, CLA CLL */ 01216, /* TAD MVB ; move back */ 04210, /* JMS DO ; action */ 01217, /* TAD K7577 ; addr */ 03620, /* DCA I CA */ 01222, /* TAD RDF ; read fwd */ 04210, /* JMS DO ; action */ 05600, /* JMP I 200 ; enter boot */ 00000, /* DO, 0 */ 06766, /* DTCA!DTXA ; start tape */ 03621, /* DCA I WC ; clear wc */ 06771, /* DTSF ; wait */ 05213, /* JMP .-1 */ 05610, /* JMP I DO */ 00600, /* MVB, 0600 */ 07577, /* K7577, 7757 */ 07755, /* CA, 7755 */ 07754, /* WC, 7754 */ 00220 /* RF, 0220 */ }; t_stat dt_boot (int32 unitno, DEVICE *dptr) { size_t i; if (unitno) /* only unit 0 */ return SCPE_ARG; if (dt_dib.dev != DEV_DTA) /* only std devno */ return STOP_NOTSTD; dt_unit[unitno].pos = DT_EZLIN; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; cpu_set_bootpc (BOOT_START); return SCPE_OK; } /* Attach routine Determine 12b, 16b, or 18b/36b format Allocate buffer If 16b or 18b, read 16b or 18b format and convert to 12b in buffer If 12b, read data into buffer */ t_stat dt_attach (UNIT *uptr, CONST char *cptr) { uint32 pdp18b[D18_NBSIZE]; uint16 pdp11b[D18_NBSIZE], *fbuf; int32 i, k; int32 u = uptr - dt_dev.units; t_stat r; uint32 ba, sz; r = attach_unit (uptr, cptr); /* attach */ if (r != SCPE_OK) return r; /* fail? */ if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; if (sim_switches & SWMASK ('F')) /* att 18b? */ uptr->flags = uptr->flags & ~UNIT_8FMT; else if (sim_switches & SWMASK ('S')) /* att 16b? */ uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; else if (!(sim_switches & SWMASK ('A')) && /* autosize? */ (sz = sim_fsize (uptr->fileref))) { if (sz == D11_FILSIZ) uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; else if (sz > D8_FILSIZ) uptr->flags = uptr->flags & ~UNIT_8FMT; } } uptr->capac = DTU_CAPAC (uptr); /* set capacity */ uptr->filebuf = calloc (uptr->capac, sizeof (uint16)); if (uptr->filebuf == NULL) { /* can't alloc? */ detach_unit (uptr); return SCPE_MEM; } fbuf = (uint16 *) uptr->filebuf; /* file buffer */ sim_printf ("%s%d: ", sim_dname (&dt_dev), u); if (uptr->flags & UNIT_8FMT) sim_printf ("12b format"); else if (uptr->flags & UNIT_11FMT) sim_printf ("16b format"); else sim_printf ("18b/36b format"); sim_printf (", buffering file in memory\n"); uptr->io_flush = dt_flush; if (uptr->flags & UNIT_8FMT) /* 12b? */ uptr->hwmark = fxread (uptr->filebuf, sizeof (uint16), uptr->capac, uptr->fileref); else { /* 16b/18b */ for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ if (uptr->flags & UNIT_11FMT) { k = fxread (pdp11b, sizeof (uint16), D18_NBSIZE, uptr->fileref); for (i = 0; i < k; i++) pdp18b[i] = pdp11b[i]; } else k = fxread (pdp18b, sizeof (uint32), D18_NBSIZE, uptr->fileref); if (k == 0) break; for ( ; k < D18_NBSIZE; k++) pdp18b[k] = 0; for (k = 0; k < D18_NBSIZE; k = k + 2) { /* loop thru blk */ fbuf[ba] = (pdp18b[k] >> 6) & 07777; fbuf[ba + 1] = ((pdp18b[k] & 077) << 6) | ((pdp18b[k + 1] >> 12) & 077); fbuf[ba + 2] = pdp18b[k + 1] & 07777; ba = ba + 3; } /* end blk loop */ } /* end file loop */ uptr->hwmark = ba; } /* end else */ uptr->flags = uptr->flags | UNIT_BUF; /* set buf flag */ uptr->pos = DT_EZLIN; /* beyond leader */ uptr->LASTT = sim_grtime (); /* last pos update */ return SCPE_OK; } /* Detach routine Cancel in progress operation If 12b, write buffer to file If 16b or 18b, convert 12b buffer to 16b or 18b and write to file Deallocate buffer */ void dt_flush (UNIT* uptr) { uint32 pdp18b[D18_NBSIZE]; uint16 pdp11b[D18_NBSIZE], *fbuf; int32 i, k; uint32 ba; if (uptr->WRITTEN && uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ rewind (uptr->fileref); /* start of file */ fbuf = (uint16 *) uptr->filebuf; /* file buffer */ if (uptr->flags & UNIT_8FMT) /* PDP8? */ fxwrite (uptr->filebuf, sizeof (uint16), /* write file */ uptr->hwmark, uptr->fileref); else { /* 16b/18b */ for (ba = 0; ba < uptr->hwmark; ) { /* loop thru buf */ for (k = 0; k < D18_NBSIZE; k = k + 2) { pdp18b[k] = ((uint32) (fbuf[ba] & 07777) << 6) | ((uint32) (fbuf[ba + 1] >> 6) & 077); pdp18b[k + 1] = ((uint32) (fbuf[ba + 1] & 077) << 12) | ((uint32) (fbuf[ba + 2] & 07777)); ba = ba + 3; } /* end loop blk */ if (uptr->flags & UNIT_11FMT) { /* 16b? */ for (i = 0; i < D18_NBSIZE; i++) pdp11b[i] = pdp18b[i]; fxwrite (pdp11b, sizeof (uint16), D18_NBSIZE, uptr->fileref); } else fxwrite (pdp18b, sizeof (uint32), D18_NBSIZE, uptr->fileref); } /* end loop buf */ } /* end else */ if (ferror (uptr->fileref)) sim_perror ("I/O error"); } uptr->WRITTEN = FALSE; /* no longer dirty */ } t_stat dt_detach (UNIT* uptr) { int u = (int)(uptr - dt_dev.units); if (!(uptr->flags & UNIT_ATT)) /* attached? */ return SCPE_OK; if (sim_is_active (uptr)) { sim_cancel (uptr); if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) { dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF; DT_UPDINT; } uptr->STATE = uptr->pos = 0; } if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ sim_printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u); dt_flush (uptr); } /* end if hwmark */ free (uptr->filebuf); /* release buf */ uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */ uptr->filebuf = NULL; /* clear buf ptr */ uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; /* default fmt */ uptr->capac = DT_CAPAC; /* default size */ return detach_unit (uptr); } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 | /* pdp8_fpp.c: PDP-8 floating point processor (FPP8A) Copyright (c) 2007-2011, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. fpp FPP8A floating point processor 03-Jan-10 RMS Initialized variables statically, for VMS compiler 19-Apr-09 RHM FPICL does not clear all command and status reg bits modify fpp_reset to conform with FPP 27-Mar-09 RHM Fixed handling of Underflow fix (zero FAC on underflow) Implemented FPP division and multiplication algorithms FPP behavior on traps - FEXIT does not update APT Follow FPP settings for OPADD Correct detection of DP add/sub overflow Detect and handle add/sub overshift Single-step mode made consistent with FPP Write calculation results prior to traps 24-Mar-09 RMS Many fixes from Rick Murphy: Fix calculation of ATX shift amount Added missing () to read, write XR macros Fixed indirect address calculation Fixed == written as = in normalization Fixed off-by-one count bug in multiplication Removed extraneous ; in divide Fixed direction of compare in divide Fixed count direction bug in alignment Floating point formats: 00 01 02 03 04 05 06 07 08 09 10 11 +--+--+--+--+--+--+--+--+--+--+--+--+ | S| hi integer | : double precision +--+--+--+--+--+--+--+--+--+--+--+--+ | lo integer | +--+--+--+--+--+--+--+--+--+--+--+--+ 00 01 02 03 04 05 06 07 08 09 10 11 +--+--+--+--+--+--+--+--+--+--+--+--+ | S| exponent | : floating point +--+--+--+--+--+--+--+--+--+--+--+--+ | S| hi fraction | +--+--+--+--+--+--+--+--+--+--+--+--+ | lo fraction | +--+--+--+--+--+--+--+--+--+--+--+--+ 00 01 02 03 04 05 06 07 08 09 10 11 +--+--+--+--+--+--+--+--+--+--+--+--+ | S| exponent | : extended precision +--+--+--+--+--+--+--+--+--+--+--+--+ | S| hi fraction | +--+--+--+--+--+--+--+--+--+--+--+--+ | next fraction | +--+--+--+--+--+--+--+--+--+--+--+--+ | next fraction | +--+--+--+--+--+--+--+--+--+--+--+--+ | next fraction | +--+--+--+--+--+--+--+--+--+--+--+--+ | lo fraction | +--+--+--+--+--+--+--+--+--+--+--+--+ Exponents are 2's complement, as are fractions. Normalized numbers have the form: 0.0...0 0.<non-zero> 1.<non-zero> 1.1...0 Note that 1.0...0 is normalized but considered illegal, since it cannot be represented as a positive number. When a result is normalized, 1.0...0 is converted to 1.1...0 with exp+1. */ #include "pdp8_defs.h" extern int32 int_req; extern uint16 M[]; extern int32 stop_inst; extern UNIT cpu_unit; #define SEXT12(x) (((x) & 04000)? (x) | ~07777: (x) & 03777) /* Index registers are in memory */ #define fpp_read_xr(xr) fpp_read (fpp_xra + (xr)) #define fpp_write_xr(xr,d) fpp_write (fpp_xra + (xr), d) /* Command register */ #define FPC_DP 04000 /* integer double */ #define FPC_UNFX 02000 /* exit on fl undf */ #define FPC_FIXF 01000 /* lock mem field */ #define FPC_IE 00400 /* int enable */ #define FPC_V_FAST 4 /* startup bits */ #define FPC_M_FAST 017 #define FPC_LOCK 00010 /* lockout */ #define FPC_V_APTF 0 #define FPC_M_APTF 07 /* apta field */ #define FPC_STA (FPC_DP|FPC_LOCK) #define FPC_GETFAST(x) (((x) >> FPC_V_FAST) & FPC_M_FAST) #define FPC_GETAPTF(x) (((x) >> FPC_V_APTF) & FPC_M_APTF) /* Status register */ #define FPS_DP (FPC_DP) /* integer double */ #define FPS_TRPX 02000 /* trap exit */ #define FPS_HLTX 01000 /* halt exit */ #define FPS_DVZX 00400 /* div zero exit */ #define FPS_IOVX 00200 /* int ovf exit */ #define FPS_FOVX 00100 /* flt ovf exit */ #define FPS_UNF 00040 /* underflow */ #define FPS_XXXM 00020 /* FADDM/FMULM */ #define FPS_LOCK (FPC_LOCK) /* lockout */ #define FPS_EP 00004 /* ext prec */ #define FPS_PAUSE 00002 /* paused */ #define FPS_RUN 00001 /* running */ /* Floating point number: 3-6 words */ #define FPN_FRSIGN 04000 #define FPN_NFR_FP 2 /* std precision */ #define FPN_NFR_EP 5 /* ext precision */ #define FPN_NFR_MDS 6 /* mul/div precision */ #define EXACT (uint32)((fpp_sta & FPS_EP)? FPN_NFR_EP: FPN_NFR_FP) #define EXTEND ((uint32) FPN_NFR_EP) typedef struct { int32 exp; uint32 fr[FPN_NFR_MDS+1]; } FPN; uint32 fpp_apta = 0; /* APT pointer */ uint32 fpp_aptsvf = 0; /* APT saved field */ uint32 fpp_opa = 0; /* operand pointer */ uint32 fpp_fpc = 0; /* FP PC */ uint32 fpp_bra = 0; /* base reg pointer */ uint32 fpp_xra = 0; /* indx reg pointer */ uint32 fpp_cmd = 0; /* command */ uint32 fpp_sta = 0; /* status */ uint32 fpp_flag = 0; /* flag */ FPN fpp_ac; /* FAC */ uint32 fpp_ssf = 0; /* single-step flag */ uint32 fpp_last_lockbit = 0; /* last lockbit */ static FPN fpp_zero = { 0, { 0, 0, 0, 0, 0 } }; static FPN fpp_one = { 1, { 02000, 0, 0, 0, 0 } }; int32 fpp55 (int32 IR, int32 AC); int32 fpp56 (int32 IR, int32 AC); void fpp_load_apt (uint32 apta); void fpp_dump_apt (uint32 apta, uint32 sta); uint32 fpp_1wd_dir (uint32 ir); uint32 fpp_2wd_dir (uint32 ir); uint32 fpp_indir (uint32 ir); uint32 fpp_ad15 (uint32 hi); uint32 fpp_adxr (uint32 ir, uint32 base_ad); void fpp_add (FPN *a, FPN *b, uint32 sub); void fpp_mul (FPN *a, FPN *b); void fpp_div (FPN *a, FPN *b); t_bool fpp_imul (FPN *a, FPN *b); uint32 fpp_fr_add (uint32 *c, uint32 *a, uint32 *b, uint32 cnt); void fpp_fr_sub (uint32 *c, uint32 *a, uint32 *b, uint32 cnt); void fpp_fr_mul (uint32 *c, uint32 *a, uint32 *b, t_bool fix); t_bool fpp_fr_div (uint32 *c, uint32 *a, uint32 *b); uint32 fpp_fr_neg (uint32 *a, uint32 cnt); int32 fpp_fr_cmp (uint32 *a, uint32 *b, uint32 cnt); int32 fpp_fr_test (uint32 *a, uint32 v0, uint32 cnt); uint32 fpp_fr_abs (uint32 *a, uint32 *b, uint32 cnt); void fpp_fr_fill (uint32 *a, uint32 v, uint32 cnt); void fpp_fr_lshn (uint32 *a, uint32 sc, uint32 cnt); void fpp_fr_lsh12 (uint32 *a, uint32 cnt); void fpp_fr_lsh1 (uint32 *a, uint32 cnt); void fpp_fr_rsh1 (uint32 *a, uint32 sign, uint32 cnt); void fpp_fr_algn (uint32 *a, uint32 sc, uint32 cnt); t_bool fpp_cond_met (uint32 cond); t_bool fpp_norm (FPN *a, uint32 cnt); void fpp_round (FPN *a); t_bool fpp_test_xp (FPN *a); void fpp_copy (FPN *a, FPN *b); void fpp_zcopy (FPN *a, FPN *b); void fpp_read_op (uint32 ea, FPN *a); void fpp_write_op (uint32 ea, FPN *a); uint32 fpp_read (uint32 ea); void fpp_write (uint32 ea, uint32 val); uint32 apt_read (uint32 ea); void apt_write (uint32 ea, uint32 val); t_stat fpp_svc (UNIT *uptr); t_stat fpp_reset (DEVICE *dptr); /* FPP data structures fpp_dev FPP device descriptor fpp_unit FPP unit descriptor fpp_reg FPP register list */ DIB fpp_dib = { DEV_FPP, 2, { &fpp55, &fpp56 } }; UNIT fpp_unit = { UDATA (&fpp_svc, 0, 0) }; REG fpp_reg[] = { { ORDATAD (FPACE, fpp_ac.exp, 12, "floating accumulator") }, { ORDATAD (FPAC0, fpp_ac.fr[0], 12, "first mantissa") }, { ORDATAD (FPAC1, fpp_ac.fr[1], 12, "second mantissa") }, { ORDATAD (FPAC2, fpp_ac.fr[2], 12, "third mantissa") }, { ORDATAD (FPAC3, fpp_ac.fr[3], 12, "fourth mantissa") }, { ORDATAD (FPAC4, fpp_ac.fr[4], 12, "fifth mantissa") }, { ORDATAD (CMD, fpp_cmd, 12, "FPP command register") }, { ORDATAD (STA, fpp_sta, 12, "status register") }, { ORDATAD (APTA, fpp_apta, 15, "active parameter table (APT) pointer") }, { GRDATAD (APTSVF, fpp_aptsvf, 8, 3, 12, "APT field") }, { ORDATAD (FPC, fpp_fpc, 15, "floating program counter") }, { ORDATAD (BRA, fpp_bra, 15, "base register") }, { ORDATAD (XRA, fpp_xra, 15, "pointer to index register 0") }, { ORDATAD (OPA, fpp_opa, 15, "operand address register") }, { ORDATAD (SSF, fpp_ssf, 12, "single step flag") }, { ORDATAD (LASTLOCK, fpp_last_lockbit, 12, "lockout from FPCOM") }, { FLDATAD (FLAG, fpp_flag, 0, "done flag") }, { NULL } }; DEVICE fpp_dev = { "FPP", &fpp_unit, fpp_reg, NULL, 1, 10, 31, 1, 8, 8, NULL, NULL, &fpp_reset, NULL, NULL, NULL, &fpp_dib, DEV_DISABLE | DEV_DIS }; /* IOT routines */ int32 fpp55 (int32 IR, int32 AC) { switch (IR & 07) { /* decode IR<9:11> */ case 1: /* FPINT */ return (fpp_flag? IOT_SKP | AC: AC); /* skip on flag */ case 2: /* FPICL */ fpp_reset (&fpp_dev); /* reset device */ break; case 3: /* FPCOM */ if (!fpp_flag && !(fpp_sta & FPS_RUN)) { /* flag clr, !run? */ fpp_cmd = AC; /* load cmd */ fpp_last_lockbit = fpp_cmd & FPS_LOCK; /* remember lock state */ fpp_sta = (fpp_sta & ~FPC_STA) | /* copy flags */ (fpp_cmd & FPC_STA); /* to status */ } break; case 4: /* FPHLT */ if (fpp_sta & FPS_RUN) { /* running? */ if (fpp_sta & FPS_PAUSE) /* paused? */ fpp_fpc = (fpp_fpc - 1) & ADDRMASK; /* decr FPC */ fpp_sta &= ~FPS_PAUSE; /* no longer paused */ sim_cancel (&fpp_unit); /* stop execution */ fpp_dump_apt (fpp_apta, FPS_HLTX); /* dump APT */ fpp_ssf = 1; /* assume sstep */ } else if (!fpp_flag) fpp_ssf = 1; /* FPST sing steps */ if (fpp_sta & FPS_DVZX) /* fix diag timing */ fpp_sta |= FPS_HLTX; break; case 5: /* FPST */ if (!fpp_flag && !(fpp_sta & FPS_RUN)) { /* flag clr, !run? */ if (fpp_ssf) fpp_sta |= fpp_last_lockbit; fpp_sta &= ~FPS_HLTX; /* Clear halted */ fpp_apta = (FPC_GETAPTF (fpp_cmd) << 12) | AC; fpp_load_apt (fpp_apta); /* load APT */ fpp_opa = fpp_fpc; sim_activate (&fpp_unit, 0); /* start unit */ return IOT_SKP | AC; } if ((fpp_sta & (FPS_RUN|FPS_PAUSE)) == (FPS_RUN|FPS_PAUSE)) { fpp_sta &= ~FPS_PAUSE; /* continue */ sim_activate (&fpp_unit, 0); /* start unit */ return (IOT_SKP | AC); } break; case 6: /* FPRST */ return fpp_sta; case 7: /* FPIST */ if (fpp_flag) { /* if flag set */ uint32 old_sta = fpp_sta; fpp_flag = 0; /* clr flag, status */ fpp_sta &= ~(FPS_DP|FPS_EP|FPS_TRPX|FPS_DVZX|FPS_IOVX|FPS_FOVX|FPS_UNF); int_req &= ~INT_FPP; /* clr int req */ return IOT_SKP | old_sta; /* ret old status */ } break; default: return (stop_inst << IOT_V_REASON) | AC; } /* end switch */ return AC; } int32 fpp56 (int32 IR, int32 AC) { switch (IR & 07) { /* decode IR<9:11> */ case 7: /* FPEP */ if ((AC & 04000) && !(fpp_sta & FPS_RUN)) { /* if AC0, not run, */ fpp_sta = (fpp_sta | FPS_EP) & ~FPS_DP; /* set ep */ AC = 0; } break; default: return (stop_inst << IOT_V_REASON) | AC; } /* end switch */ return AC; } /* Service routine */ t_stat fpp_svc (UNIT *uptr) { FPN x; uint32 ir, op, op2, op3, ad, ea, wd; uint32 i; int32 sc; fpp_ac.exp = SEXT12 (fpp_ac.exp); /* sext AC exp */ do { /* repeat */ ir = fpp_read (fpp_fpc); /* get instr */ fpp_fpc = (fpp_fpc + 1) & ADDRMASK; /* incr FP PC */ op = (ir >> 7) & 037; /* get op+mode */ op2 = (ir >> 3) & 017; /* get subop */ op3 = ir & 07; /* get field/xr */ fpp_sta &= ~FPS_XXXM; /* not mem op */ switch (op) { /* case on op+mode */ case 000: /* operates */ switch (op2) { /* case on subop */ case 000: /* no-operands */ switch (op3) { /* case on subsubop */ case 0: /* FEXIT */ /* if already trapped, don't update APT, just update status */ if (fpp_sta & (FPS_DVZX|FPS_IOVX|FPS_FOVX|FPS_UNF)) fpp_sta |= FPS_HLTX; else fpp_dump_apt (fpp_apta, 0); break; case 1: /* FPAUSE */ fpp_sta |= FPS_PAUSE; break; case 2: /* FCLA */ fpp_copy (&fpp_ac, &fpp_zero); /* clear FAC */ break; case 3: /* FNEG */ fpp_fr_neg (fpp_ac.fr, EXACT); /* do exact length */ break; case 4: /* FNORM */ if (!(fpp_sta & FPS_DP)) { /* fp or ep only */ fpp_copy (&x, &fpp_ac); /* copy AC */ fpp_norm (&x, EXACT); /* do exact length */ fpp_copy (&fpp_ac, &x); /* copy back */ } break; case 5: /* STARTF */ if (fpp_sta & FPS_EP) { /* if ep, */ fpp_copy (&x, &fpp_ac); /* copy AC */ fpp_round (&x); /* round */ fpp_copy (&fpp_ac, &x); /* copy back */ } fpp_sta &= ~(FPS_DP|FPS_EP); break; case 6: /* STARTD */ fpp_sta = (fpp_sta | FPS_DP) & ~FPS_EP; break; case 7: /* JAC */ fpp_fpc = ((fpp_ac.fr[0] & 07) << 12) | fpp_ac.fr[1]; break; } break; case 001: /* ALN */ if (op3 != 0) { /* if xr, */ wd = fpp_read_xr (op3); /* use val */ fpp_opa = fpp_xra + op3; } else wd = 027; /* else 23 */ if (!(fpp_sta & FPS_DP)) { /* fp or ep? */ sc = (SEXT12(wd) - fpp_ac.exp) & 07777; /* alignment */ sc = SEXT12 (sc); fpp_ac.exp = SEXT12(wd); /* new exp */ } else sc = SEXT12 (wd); /* dp - simple cnt */ if (sc < 0) /* left? */ fpp_fr_lshn (fpp_ac.fr, -sc, EXACT); else fpp_fr_algn (fpp_ac.fr, sc, EXACT); if (fpp_fr_test (fpp_ac.fr, 0, EXACT) == 0) /* zero? */ fpp_ac.exp = 0; /* clean exp */ break; case 002: /* ATX */ if (fpp_sta & FPS_DP) /* dp? */ fpp_write_xr (op3, fpp_ac.fr[1]); /* xr<-FAC<12:23> */ else { fpp_copy (&x, &fpp_ac); /* copy AC */ sc = 027 - x.exp; /* shift amt */ if (sc < 0) /* left? */ fpp_fr_lshn (x.fr, -sc, EXACT); else fpp_fr_algn (x.fr, sc, EXACT); fpp_write_xr (op3, x.fr[1]); /* xr<-val<12:23> */ } break; case 003: /* XTA */ for (i = FPN_NFR_FP; i < FPN_NFR_EP; i++) x.fr[i] = 0; /* clear FOP2-4 */ x.fr[1] = fpp_read_xr (op3); /* get XR value */ x.fr[0] = (x.fr[1] & 04000)? 07777: 0; x.exp = 027; /* standard exp */ if (!(fpp_sta & FPS_DP)) { /* fp or ep? */ fpp_norm (&x, EXACT); /* normalize */ } fpp_copy (&fpp_ac, &x); /* result to AC */ if (fpp_sta & FPS_DP) /* dp skips exp */ fpp_ac.exp = x.exp; /* so force copy */ fpp_opa = fpp_xra + op3; break; case 004: /* NOP */ break; case 005: /* STARTE */ if (!(fpp_sta & FPS_EP)) { fpp_sta = (fpp_sta | FPS_EP) & ~FPS_DP; for (i = FPN_NFR_FP; i < FPN_NFR_EP; i++) fpp_ac.fr[i] = 0; /* clear FAC2-4 */ } break; case 010: /* LDX */ wd = fpp_ad15 (0); /* load XR immed */ fpp_write_xr (op3, wd); fpp_opa = fpp_xra + op3; break; case 011: /* ADDX */ wd = fpp_ad15 (0); wd = wd + fpp_read_xr (op3); /* add to XR immed */ fpp_write_xr (op3, wd); /* trims to 12b */ fpp_opa = fpp_xra + op3; break; default: return stop_inst; } /* end case subop */ break; case 001: /* FLDA */ ea = fpp_1wd_dir (ir); fpp_read_op (ea, &fpp_ac); break; case 002: ea = fpp_2wd_dir (ir); fpp_read_op (ea, &fpp_ac); if (fpp_sta & FPS_DP) fpp_opa = ea + 1; else fpp_opa = ea + 2; break; case 003: ea = fpp_indir (ir); fpp_read_op (ea, &fpp_ac); break; case 004: /* jumps and sets */ ad = fpp_ad15 (op3); /* get 15b address */ switch (op2) { /* case on subop */ case 000: case 001: case 002: case 003: /* cond jump */ case 004: case 005: case 006: case 007: if (fpp_cond_met (op2)) /* br if cond */ fpp_fpc = ad; break; case 010: /* SETX */ fpp_xra = ad; break; case 011: /* SETB */ fpp_bra = ad; break; case 012: /* JSA */ fpp_write (ad, 01030 + (fpp_fpc >> 12)); /* save return */ fpp_write (ad + 1, fpp_fpc); /* trims to 12b */ fpp_fpc = (ad + 2) & ADDRMASK; fpp_opa = fpp_fpc - 1; break; case 013: /* JSR */ fpp_write (fpp_bra + 1, 01030 + (fpp_fpc >> 12)); fpp_write (fpp_bra + 2, fpp_fpc); /* trims to 12b */ fpp_opa = fpp_fpc = ad; break; default: return stop_inst; } /* end case subop */ break; case 005: /* FADD */ ea = fpp_1wd_dir (ir); fpp_read_op (ea, &x); fpp_add (&fpp_ac, &x, 0); break; case 006: ea = fpp_2wd_dir (ir); fpp_read_op (ea, &x); fpp_add (&fpp_ac, &x, 0); break; case 007: ea = fpp_indir (ir); fpp_read_op (ea, &x); fpp_add (&fpp_ac, &x, 0); break; case 010: { /* JNX */ uint32 xrn = op2 & 07; ad = fpp_ad15 (op3); /* get 15b addr */ wd = fpp_read_xr (xrn); /* read xr */ if (op2 & 010) { /* inc? */ wd = (wd + 1) & 07777; fpp_write_xr (xrn, wd); /* ++xr */ } if (wd != 0) /* xr != 0? */ fpp_fpc = ad; /* jump */ break; } case 011: /* FSUB */ ea = fpp_1wd_dir (ir); fpp_read_op (ea, &x); fpp_add (&fpp_ac, &x, 1); break; case 012: ea = fpp_2wd_dir (ir); fpp_read_op (ea, &x); fpp_add (&fpp_ac, &x, 1); break; case 013: ea = fpp_indir (ir); fpp_read_op (ea, &x); fpp_add (&fpp_ac, &x, 1); break; case 014: /* TRAP3 */ case 020: /* TRAP4 */ fpp_opa = fpp_ad15 (op3); fpp_dump_apt (fpp_apta, FPS_TRPX); break; case 015: /* FDIV */ ea = fpp_1wd_dir (ir); fpp_read_op (ea, &x); fpp_div (&fpp_ac, &x); break; case 016: ea = fpp_2wd_dir (ir); fpp_read_op (ea, &x); fpp_div (&fpp_ac, &x); break; case 017: ea = fpp_indir (ir); fpp_read_op (ea, &x); fpp_div (&fpp_ac, &x); break; case 021: /* FMUL */ ea = fpp_1wd_dir (ir); fpp_read_op (ea, &x); fpp_mul (&fpp_ac, &x); break; case 022: ea = fpp_2wd_dir (ir); fpp_read_op (ea, &x); fpp_mul (&fpp_ac, &x); break; case 023: ea = fpp_indir (ir); fpp_read_op (ea, &x); fpp_mul (&fpp_ac, &x); break; case 024: /* LTR */ fpp_copy (&fpp_ac, (fpp_cond_met (op2 & 07)? &fpp_one: &fpp_zero)); break; case 025: /* FADDM */ fpp_sta |= FPS_XXXM; ea = fpp_1wd_dir (ir); fpp_read_op (ea, &x); fpp_add (&x, &fpp_ac, 0); fpp_write_op (ea, &x); /* store result */ break; case 026: fpp_sta |= FPS_XXXM; ea = fpp_2wd_dir (ir); fpp_read_op (ea, &x); fpp_add (&x, &fpp_ac, 0); fpp_write_op (ea, &x); /* store result */ break; case 027: fpp_sta |= FPS_XXXM; ea = fpp_indir (ir); fpp_read_op (ea, &x); fpp_add (&x, &fpp_ac, 0); fpp_write_op (ea, &x); /* store result */ break; case 030: /* IMUL/LEA */ ea = fpp_2wd_dir (ir); /* 2-word direct */ if (fpp_sta & FPS_DP) { /* dp? */ fpp_read_op (ea, &x); /* IMUL */ fpp_imul (&fpp_ac, &x); } else { /* LEA */ fpp_sta = (fpp_sta | FPS_DP) & ~FPS_EP; /* set dp */ fpp_ac.fr[0] = (ea >> 12) & 07; fpp_ac.fr[1] = ea & 07777; } break; case 031: /* FSTA */ ea = fpp_1wd_dir (ir); fpp_write_op (ea, &fpp_ac); break; case 032: ea = fpp_2wd_dir (ir); fpp_write_op (ea, &fpp_ac); break; case 033: ea = fpp_indir (ir); fpp_write_op (ea, &fpp_ac); break; case 034: /* IMULI/LEAI */ ea = fpp_indir (ir); /* 1-word indir */ if (fpp_sta & FPS_DP) { /* dp? */ fpp_read_op (ea, &x); /* IMUL */ fpp_imul (&fpp_ac, &x); } else { /* LEA */ fpp_sta = (fpp_sta | FPS_DP) & ~FPS_EP; /* set dp */ fpp_ac.fr[0] = (ea >> 12) & 07; fpp_ac.fr[1] = ea & 07777; fpp_opa = ea; } break; case 035: /* FMULM */ fpp_sta |= FPS_XXXM; ea = fpp_1wd_dir (ir); fpp_read_op (ea, &x); fpp_mul (&x, &fpp_ac); fpp_write_op (ea, &x); /* store result */ break; case 036: fpp_sta |= FPS_XXXM; ea = fpp_2wd_dir (ir); fpp_read_op (ea, &x); fpp_mul (&x, &fpp_ac); fpp_write_op (ea, &x); /* store result */ break; case 037: fpp_sta |= FPS_XXXM; ea = fpp_indir (ir); fpp_read_op (ea, &x); fpp_mul (&x, &fpp_ac); fpp_write_op (ea, &x); /* store result */ break; } /* end sw op+mode */ if (fpp_ssf) { fpp_dump_apt (fpp_apta, FPS_HLTX); /* dump APT */ fpp_ssf = 0; } if (sim_interval) sim_interval = sim_interval - 1; } while ((sim_interval > 0) && ((fpp_sta & (FPS_RUN|FPS_PAUSE|FPS_LOCK)) == (FPS_RUN|FPS_LOCK))); if ((fpp_sta & (FPS_RUN|FPS_PAUSE)) == FPS_RUN) sim_activate (uptr, 1); fpp_ac.exp &= 07777; /* mask AC exp */ return SCPE_OK; } /* Address decoding routines */ uint32 fpp_1wd_dir (uint32 ir) { uint32 ad; ad = fpp_bra + ((ir & 0177) * 3); /* base + 3*7b off */ if (fpp_sta & FPS_DP) /* dp? skip exp */ ad = ad + 1; ad = ad & ADDRMASK; if (fpp_sta & FPS_DP) fpp_opa = ad + 1; else fpp_opa = ad + 2; return ad; } uint32 fpp_2wd_dir (uint32 ir) { uint32 ad; ad = fpp_ad15 (ir); /* get 15b addr */ return fpp_adxr (ir, ad); /* do indexing */ } uint32 fpp_indir (uint32 ir) { uint32 ad, wd1, wd2; ad = fpp_bra + ((ir & 07) * 3); /* base + 3*3b off */ wd1 = fpp_read (ad + 1); /* bp+off points to */ wd2 = fpp_read (ad + 2); ad = ((wd1 & 07) << 12) | wd2; /* indirect ptr */ ad = fpp_adxr (ir, ad); /* do indexing */ if (fpp_sta & FPS_DP) fpp_opa = ad + 1; else fpp_opa = ad + 2; return ad; } uint32 fpp_ad15 (uint32 hi) { uint32 ad; ad = ((hi & 07) << 12) | fpp_read (fpp_fpc); /* 15b addr */ fpp_fpc = (fpp_fpc + 1) & ADDRMASK; /* incr FPC */ return ad; /* return addr */ } uint32 fpp_adxr (uint32 ir, uint32 base_ad) { uint32 xr, wd; xr = (ir >> 3) & 07; wd = fpp_read_xr (xr); /* get xr */ if (ir & 0100) { /* increment? */ wd = (wd + 1) & 07777; /* inc, rewrite */ fpp_write_xr (xr, wd); } if (xr != 0) { /* indexed? */ if (fpp_sta & FPS_EP) wd = wd * 6; /* scale by len */ else if (fpp_sta & FPS_DP) wd = wd * 2; else wd = wd * 3; return (base_ad + wd) & ADDRMASK; /* return index */ } else return base_ad & ADDRMASK; /* return addr */ } /* Computation routines */ /* Fraction/floating add */ void fpp_add (FPN *a, FPN *b, uint32 sub) { FPN x, y, z; uint32 c, ediff; fpp_zcopy (&x, a); /* copy opnds */ fpp_zcopy (&y, b); if (sub) /* subtract? */ fpp_fr_neg (y.fr, EXACT); /* neg B, exact */ if (fpp_sta & FPS_DP) { /* dp? */ uint32 cout = fpp_fr_add (z.fr, x.fr, y.fr, EXTEND);/* z = a + b */ uint32 zsign = z.fr[0] & FPN_FRSIGN; cout = (cout? 04000: 0); /* make sign bit */ /* overflow is indicated when signs are equal and overflow does not match the result sign bit */ fpp_copy (a, &z); /* result is z */ if (!((x.fr[0] ^ y.fr[0]) & FPN_FRSIGN) && (cout != zsign)) { fpp_copy (a, &z); /* copy out result */ fpp_dump_apt (fpp_apta, FPS_IOVX); /* int ovf? */ return; } } else { /* fp or ep */ if (fpp_fr_test (b->fr, 0, EXACT) == 0) /* B == 0? */ z = x; /* result is A */ else if (fpp_fr_test (a->fr, 0, EXACT) == 0) /* A == 0? */ z = y; /* result is B */ else { /* fp or ep */ if (x.exp < y.exp) { /* |a| < |b|? */ z = x; /* exchange ops */ x = y; y = z; } ediff = x.exp - y.exp; /* exp diff */ if (ediff <= (uint32) ((fpp_sta & FPS_EP)? 59: 24)) { /* any add? */ z.exp = x.exp; /* result exp */ if (ediff != 0) /* any align? */ fpp_fr_algn (y.fr, ediff, EXTEND); /* align, 60b */ c = fpp_fr_add (z.fr, x.fr, y.fr, EXTEND); /* add fractions */ if ((((x.fr[0] ^ y.fr[0]) & FPN_FRSIGN) == 0) && /* same signs? */ (c || /* carry out? */ ((~x.fr[0] & z.fr[0] & FPN_FRSIGN)))) { /* + to - change? */ fpp_fr_rsh1 (z.fr, c << 11, EXTEND); /* rsh, insert cout */ z.exp = z.exp + 1; /* incr exp */ } /* end same signs */ } /* end in range */ else z = x; /* ovrshift */ } /* end ops != 0 */ if (fpp_norm (&z, EXTEND)) /* norm, !exact? */ fpp_round (&z); /* round */ fpp_copy (a, &z); /* copy out */ fpp_test_xp (&z); /* ovf, unf? */ } /* end else */ return; } /* Fraction/floating multiply */ void fpp_mul (FPN *a, FPN *b) { FPN x, y, z; fpp_zcopy (&x, a); /* copy opnds */ fpp_zcopy (&y, b); if ((fpp_fr_test(y.fr, 0, EXACT-1) == 0) && (y.fr[EXACT-1] < 2)) { y.exp = 0; y.fr[EXACT-1] = 0; } if (fpp_sta & FPS_DP) /* dp? */ fpp_fr_mul (z.fr, x.fr, y.fr, TRUE); /* mult frac */ else { /* fp or ep */ fpp_norm (&x, EXACT); fpp_norm (&y, EXACT); z.exp = x.exp + y.exp; /* add exp */ fpp_fr_mul (z.fr, x.fr, y.fr, TRUE); /* mult frac */ if (fpp_norm (&z, EXTEND)) /* norm, !exact? */ fpp_round (&z); /* round */ fpp_copy (a, &z); if (z.exp > 2047) fpp_dump_apt (fpp_apta, FPS_FOVX); /* trap */ return; } fpp_copy (a, &z); /* result is z */ return; } /* Fraction/floating divide */ void fpp_div (FPN *a, FPN *b) { FPN x, y, z; if (fpp_fr_test (b->fr, 0, EXACT) == 0) { /* divisor 0? */ fpp_dump_apt (fpp_apta, FPS_DVZX); /* error */ return; } if (fpp_fr_test (a->fr, 0, EXACT) == 0) /* dividend 0? */ return; /* quotient is 0 */ fpp_zcopy (&x, a); /* copy opnds */ fpp_zcopy (&y, b); if (fpp_sta & FPS_DP) { /* dp? */ if (fpp_fr_div (z.fr, x.fr, y.fr)) { /* fr div, ovflo? */ fpp_dump_apt (fpp_apta, FPS_IOVX); /* error */ return; } fpp_copy (a, &z); /* result is z */ } else { /* fp or ep */ fpp_norm (&y, EXACT); /* norm divisor */ if (fpp_fr_test (x.fr, 04000, EXACT) == 0) { /* divd 1.000...? */ x.fr[0] = 06000; /* fix */ x.exp = x.exp + 1; } z.exp = x.exp - y.exp; /* calc exp */ if (fpp_fr_div (z.fr, x.fr, y.fr)) { /* fr div, ovflo? */ uint32 cin = (a->fr[0] ^ b->fr[0]) & FPN_FRSIGN; fpp_fr_rsh1 (z.fr, cin, EXTEND); /* rsh, insert sign */ z.exp = z.exp + 1; /* incr exp */ } if (fpp_norm (&z, EXTEND)) /* norm, !exact? */ fpp_round (&z); /* round */ fpp_copy (a, &z); if (z.exp > 2048) { /* underflow? */ if (fpp_cmd & FPC_UNFX) { /* trap? */ fpp_dump_apt (fpp_apta, FPS_UNF); return; } } } return; } /* Integer multiply - returns true if overflow */ t_bool fpp_imul (FPN *a, FPN *b) { uint32 sext; FPN x, y, z; fpp_zcopy (&x, a); /* copy args */ fpp_zcopy (&y, b); fpp_fr_mul (z.fr, x.fr, y.fr, FALSE); /* mult fracs */ a->fr[0] = z.fr[1]; /* low 24b */ a->fr[1] = z.fr[2]; if ((a->fr[0] == 0) && (a->fr[1] == 0)) /* fpp zeroes exp */ a->exp = 0; /* even in dp mode */ sext = (z.fr[2] & FPN_FRSIGN)? 07777: 0; if (((z.fr[0] | z.fr[1] | sext) != 0) && /* hi 25b == 0 */ ((z.fr[0] & z.fr[1] & sext) != 07777)) { /* or 777777774? */ fpp_dump_apt (fpp_apta, FPS_IOVX); return TRUE; } return FALSE; } /* Auxiliary floating point routines */ t_bool fpp_cond_met (uint32 cond) { switch (cond) { case 0: return (fpp_fr_test (fpp_ac.fr, 0, EXACT) == 0); case 1: return (fpp_fr_test (fpp_ac.fr, 0, EXACT) >= 0); case 2: return (fpp_fr_test (fpp_ac.fr, 0, EXACT) <= 0); case 3: return 1; case 4: return (fpp_fr_test (fpp_ac.fr, 0, EXACT) != 0); case 5: return (fpp_fr_test (fpp_ac.fr, 0, EXACT) < 0); case 6: return (fpp_fr_test (fpp_ac.fr, 0, EXACT) > 0); case 7: return (fpp_ac.exp > 027); } return 0; } /* Normalization - returns TRUE if rounding possible, FALSE if exact */ t_bool fpp_norm (FPN *a, uint32 cnt) { if (fpp_fr_test (a->fr, 0, cnt) == 0) { /* zero? */ a->exp = 0; /* clean exp */ return FALSE; /* don't round */ } while (((a->fr[0] == 0) && !(a->fr[1] & 04000)) || /* lead 13b same? */ ((a->fr[0] == 07777) && (a->fr[1] & 04000))) { fpp_fr_lsh12 (a->fr, cnt); /* move word */ a->exp = a->exp - 12; } while (((a->fr[0] ^ (a->fr[0] << 1)) & FPN_FRSIGN) == 0) { /* until norm */ fpp_fr_lsh1 (a->fr, cnt); /* shift 1b */ a->exp = a->exp - 1; } if (fpp_fr_test (a->fr, 04000, EXACT) == 0) { /* 4000...0000? */ a->fr[0] = 06000; /* chg to 6000... */ a->exp = a->exp + 1; /* with exp+1 */ return FALSE; /* don't round */ } return TRUE; } /* Exact fp number copy */ void fpp_copy (FPN *a, FPN *b) { uint32 i; if (!(fpp_sta & FPS_DP)) a->exp = b->exp; for (i = 0; i < EXACT; i++) a->fr[i] = b->fr[i]; return; } /* Zero extended fp number copy (60b) */ void fpp_zcopy (FPN *a, FPN *b) { uint32 i; a->exp = b->exp; for (i = 0; i < FPN_NFR_EP; i++) { if ((i < FPN_NFR_FP) || (fpp_sta & FPS_EP)) a->fr[i] = b->fr[i]; else a->fr[i] = 0; } a->fr[i++] = 0; a->fr[i] = 0; return; } /* Test exp for overflow or underflow, returns TRUE on trap */ t_bool fpp_test_xp (FPN *a) { if (a->exp > 2047) { /* overflow? */ fpp_dump_apt (fpp_apta, FPS_FOVX); /* trap */ return TRUE; } if (a->exp < -2048) { /* underflow? */ if (fpp_cmd & FPC_UNFX) { /* trap? */ fpp_dump_apt (fpp_apta, FPS_UNF); return TRUE; } fpp_copy (a, &fpp_zero); /* flush to 0 */ } return FALSE; } /* Round dp/fp value */ void fpp_round (FPN *a) { int32 i; uint32 cin, afr0_sign; if (fpp_sta & FPS_EP) /* ep? */ return; /* don't round */ afr0_sign = a->fr[0] & FPN_FRSIGN; /* save input sign */ cin = afr0_sign? 03777: 04000; for (i = FPN_NFR_FP; i >= 0; i--) { /* 3 words */ a->fr[i] = a->fr[i] + cin; /* add in carry */ cin = (a->fr[i] >> 12) & 1; a->fr[i] = a->fr[i] & 07777; } if (!(fpp_sta & FPS_DP) && /* fp? */ (afr0_sign ^ (a->fr[0] & FPN_FRSIGN))) { /* sign change? */ fpp_fr_rsh1 (a->fr, afr0_sign, EXACT); /* rsh, insert sign */ a->exp = a->exp + 1; } return; } /* N-precision integer routines */ /* Fraction add/sub */ uint32 fpp_fr_add (uint32 *c, uint32 *a, uint32 *b, uint32 cnt) { uint32 i, cin; for (i = cnt, cin = 0; i > 0; i--) { c[i - 1] = a[i - 1] + b[i - 1] + cin; cin = (c[i - 1] >> 12) & 1; c[i - 1] = c[i - 1] & 07777; } return cin; } void fpp_fr_sub (uint32 *c, uint32 *a, uint32 *b, uint32 cnt) { uint32 i, cin; for (i = cnt, cin = 0; i > 0; i--) { c[i - 1] = a[i - 1] - b[i - 1] - cin; cin = (c[i - 1] >> 12) & 1; c[i - 1] = c[i - 1] & 07777; } return; } /* Fraction multiply - always develop 60b, multiply is either 24b*24b or 60b*60b This is a signed multiply. The shift in for signed multiply is technically ALU_N XOR ALU_V. This can be simplified as follows: a-sign c-sign result-sign cout overflow N XOR V = shift in 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 0 0 1 1 0 0 1 0 0 1 0 1 0 0 1 1 1 0 1 1 1 1 1 1 1 0 1 If a-sign == c-sign, shift-in = a-sign If a-sign != c-sign, shift-in = result-sign */ void fpp_fr_mul (uint32 *c, uint32 *a, uint32 *b, t_bool fix) { uint32 i, cnt, lo, wc, fill, b_sign; b_sign = b[0] & FPN_FRSIGN; /* remember b's sign */ fpp_fr_fill (c, 0, FPN_NFR_MDS); /* clr answer */ if (fpp_sta & FPS_EP) /* ep? */ lo = FPN_NFR_EP; /* low order mpyr word */ else lo = FPN_NFR_FP; /* low order mpyr word */ if (fix) fpp_fr_algn (a, 12, FPN_NFR_MDS + 1); /* fill left with sign */ wc = 2; /* 3 words at start */ fill = 0; cnt = lo * 12; /* total steps */ for (i = 0; i < cnt; i++) { if ((i % 12) == 0) { wc++; /* do another word */ lo--; /* and next mpyr word */ fpp_fr_algn (c, 24, wc + 1); c[wc] = 0; c[0] = c[1] = fill; /* propagate sign */ } if (b[lo] & FPN_FRSIGN) /* mpyr bit set? */ fpp_fr_add(c, a, c, wc); fill = ((c[0] & FPN_FRSIGN) ? 07777 : 0); /* remember sign */ fpp_fr_lsh1 (c, wc); /* shift the result */ fpp_fr_lsh1 (b + lo, 1); /* shift mpcd */ } if (!fix) /* imul shifts result */ fpp_fr_rsh1 (c, c[0] & FPN_FRSIGN, EXACT + 1); /* result is 1 wd right */ if (b_sign) { /* if mpyr was negative */ if (fix) fpp_fr_lsh12 (a, FPN_NFR_MDS+1); /* restore a */ fpp_fr_sub (c, c, a, EXACT); /* adjust result */ fpp_fr_sub (c, c, a, EXACT); } return; } /* Fraction divide */ t_bool fpp_fr_div (uint32 *c, uint32 *a, uint32 *b) { uint32 i, old_c, lo, cnt, sign, b_sign, addsub, limit; /* Number of words processed by each divide step */ static uint32 limits[7] = {6, 6, 5, 4, 3, 3, 2}; fpp_fr_fill (c, 0, FPN_NFR_MDS); /* clr answer */ sign = (a[0] ^ b[0]) & FPN_FRSIGN; /* sign of result */ b_sign = (b[0] & FPN_FRSIGN); if (a[0] & FPN_FRSIGN) /* |a| */ fpp_fr_neg (a, EXACT); if (fpp_sta & FPS_EP) /* ep? 6 words */ lo = FPN_NFR_EP-1; else lo = FPN_NFR_FP-1; /* fp, dp? 3 words */ cnt = (lo + 1) * 12; addsub = 04000; /* setup first op */ for (i = 0; i < cnt; i++) { /* loop */ limit = limits[i / 12]; /* how many wds this time */ fpp_fr_lsh1 (c, FPN_NFR_MDS); /* shift quotient */ if (addsub ^ b_sign) /* diff signs, subtr */ fpp_fr_sub (a, a, b, limit); /* divd - divr */ else fpp_fr_add (a, a, b, limit); /* restore */ if (!(a[0] & FPN_FRSIGN)) { c[lo] |= 1; /* set quo bit */ addsub = 04000; /* sign for nxt loop */ } else addsub = 0; fpp_fr_lsh1 (a, limit); /* shift dividend */ } old_c = c[0]; /* save ho quo */ if (sign) /* expect neg ans? */ fpp_fr_neg (c, EXTEND); /* -quo */ if (old_c & FPN_FRSIGN) /* sign set before */ return TRUE; /* neg? */ return FALSE; } /* Negate - 24b or 60b */ uint32 fpp_fr_neg (uint32 *a, uint32 cnt) { uint32 i, cin; for (i = cnt, cin = 1; i > 0; i--) { a[i - 1] = (~a[i - 1] + cin) & 07777; cin = (cin != 0 && a[i - 1] == 0); } return cin; } /* Test (compare to x'0...0) - 24b or 60b */ int32 fpp_fr_test (uint32 *a, uint32 v0, uint32 cnt) { uint32 i; if (a[0] != v0) return (a[0] & FPN_FRSIGN)? -1: +1; for (i = 1; i < cnt; i++) { if (a[i] != 0) return (a[0] & FPN_FRSIGN)? -1: +1; } return 0; } /* Fraction compare - 24b or 60b */ int32 fpp_fr_cmp (uint32 *a, uint32 *b, uint32 cnt) { uint32 i; if ((a[0] ^ b[0]) & FPN_FRSIGN) return (b[0] & FPN_FRSIGN)? +1: -1; for (i = 0; i < cnt; i++) { if (a[i] > b[i]) return (b[0] & FPN_FRSIGN)? +1: -1; if (a[i] < b[i]) return (b[0] & FPN_FRSIGN)? -1: +1; } return 0; } /* Fraction fill */ void fpp_fr_fill (uint32 *a, uint32 v, uint32 cnt) { uint32 i; for (i = 0; i < cnt; i++) a[i] = v; return; } /* Left shift n (unsigned) */ void fpp_fr_lshn (uint32 *a, uint32 sc, uint32 cnt) { uint32 i; if (sc >= (cnt * 12)) { /* out of range? */ fpp_fr_fill (a, 0, cnt); return; } while (sc >= 12) { /* word shift? */ fpp_fr_lsh12 (a, cnt); sc = sc - 12; } if (sc == 0) /* any more? */ return; for (i = 1; i < cnt; i++) /* bit shift */ a[i - 1] = ((a[i - 1] << sc) | (a[i] >> (12 - sc))) & 07777; a[cnt - 1] = (a[cnt - 1] << sc) & 07777; return; } /* Left shift 12b (unsigned) */ void fpp_fr_lsh12 (uint32 *a, uint32 cnt) { uint32 i; for (i = 1; i < cnt; i++) a[i - 1] = a[i]; a[cnt - 1] = 0; return; } /* Left shift 1b (unsigned) */ void fpp_fr_lsh1 (uint32 *a, uint32 cnt) { uint32 i; for (i = 1; i < cnt; i++) a[i - 1] = ((a[i - 1] << 1) | (a[i] >> 11)) & 07777; a[cnt - 1] = (a[cnt - 1] << 1) & 07777; return; } /* Right shift 1b, with shift in */ void fpp_fr_rsh1 (uint32 *a, uint32 sign, uint32 cnt) { uint32 i; for (i = cnt - 1; i > 0; i--) a[i] = ((a[i] >> 1) | (a[i - 1] << 11)) & 07777; a[0] = (a[0] >> 1) | sign; return; } /* Right shift n (signed) */ void fpp_fr_algn (uint32 *a, uint32 sc, uint32 cnt) { uint32 i, sign; sign = (a[0] & FPN_FRSIGN)? 07777: 0; if (sc >= (cnt * 12)) { /* out of range? */ fpp_fr_fill (a, sign, cnt); return; } while (sc >= 12) { for (i = cnt - 1; i > 0; i--) a[i] = a[i - 1]; a[0] = sign; sc = sc - 12; } if (sc == 0) return; for (i = cnt - 1; i > 0; i--) a[i] = ((a[i] >> sc) | (a[i - 1] << (12 - sc))) & 07777; a[0] = ((a[0] >> sc) | (sign << (12 - sc))) & 07777; return; } /* Read/write routines */ void fpp_read_op (uint32 ea, FPN *a) { uint32 i; if (!(fpp_sta & FPS_DP)) { a->exp = fpp_read (ea++); a->exp = SEXT12 (a->exp); } for (i = 0; i < EXACT; i++) a->fr[i] = fpp_read (ea + i); return; } void fpp_write_op (uint32 ea, FPN *a) { uint32 i; fpp_opa = ea + 2; if (!(fpp_sta & FPS_DP)) fpp_write (ea++, a->exp); for (i = 0; i < EXACT; i++) fpp_write (ea + i, a->fr[i]); return; } uint32 fpp_read (uint32 ea) { ea = ea & ADDRMASK; if (fpp_cmd & FPC_FIXF) ea = fpp_aptsvf | (ea & 07777); return M[ea]; } void fpp_write (uint32 ea, uint32 val) { ea = ea & ADDRMASK; if (fpp_cmd & FPC_FIXF) ea = fpp_aptsvf | (ea & 07777); if (MEM_ADDR_OK (ea)) M[ea] = val & 07777; return; } uint32 apt_read (uint32 ea) { ea = ea & ADDRMASK; return M[ea]; } void apt_write (uint32 ea, uint32 val) { ea = ea & ADDRMASK; if (MEM_ADDR_OK (ea)) M[ea] = val & 07777; return; } /* Utility routines */ void fpp_load_apt (uint32 ad) { uint32 wd0, i; wd0 = apt_read (ad++); fpp_fpc = ((wd0 & 07) << 12) | apt_read (ad++); if (FPC_GETFAST (fpp_cmd) != 017) { fpp_xra = ((wd0 & 00070) << 9) | apt_read (ad++); fpp_bra = ((wd0 & 00700) << 6) | apt_read (ad++); fpp_opa = ((wd0 & 07000) << 3) | apt_read (ad++); fpp_ac.exp = apt_read (ad++); for (i = 0; i < EXACT; i++) fpp_ac.fr[i] = apt_read (ad++); } fpp_aptsvf = (ad - 1) & 070000; fpp_sta |= FPS_RUN; return; } void fpp_dump_apt (uint32 ad, uint32 sta) { uint32 wd0, i; wd0 = (fpp_fpc >> 12) & 07; if (FPC_GETFAST (fpp_cmd) != 017) wd0 = wd0 | ((fpp_opa >> 3) & 07000) | ((fpp_bra >> 6) & 00700) | ((fpp_xra >> 9) & 00070); apt_write (ad++, wd0); apt_write (ad++, fpp_fpc); if (FPC_GETFAST (fpp_cmd) != 017) { apt_write (ad++, fpp_xra); apt_write (ad++, fpp_bra); apt_write (ad++, fpp_opa); apt_write (ad++, fpp_ac.exp); for (i = 0; i < EXACT; i++) apt_write (ad++, fpp_ac.fr[i]); } fpp_sta = (fpp_sta | sta) & ~FPS_RUN; fpp_flag = 1; if (fpp_cmd & FPC_IE) int_req |= INT_FPP; return; } /* Reset routine */ t_stat fpp_reset (DEVICE *dptr) { sim_cancel (&fpp_unit); fpp_flag = 0; fpp_last_lockbit = 0; int_req &= ~INT_FPP; if (sim_switches & SWMASK ('P')) { fpp_apta = 0; fpp_aptsvf = 0; fpp_fpc = 0; fpp_bra = 0; fpp_xra = 0; fpp_opa = 0; fpp_ac = fpp_zero; fpp_ssf = 0; fpp_sta = 0; fpp_cmd = 0; } else { fpp_sta &= ~(FPS_DP|FPS_EP|FPS_TRPX|FPS_DVZX|FPS_IOVX|FPS_FOVX|FPS_UNF); fpp_cmd &= (FPC_DP|FPC_UNFX|FPC_IE); } return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | /* pdp8_lp.c: PDP-8 line printer simulator Copyright (c) 1993-2016, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. lpt LP8E line printer 16-Dec-16 DJG Added IOT 6660 to allow WPS WS78 3.4 to print 19-Jan-07 RMS Added UNIT_TEXT 25-Apr-03 RMS Revised for extended file support 04-Oct-02 RMS Added DIB, enable/disable, device number support 30-May-02 RMS Widened POS to 32b */ #include "pdp8_defs.h" extern int32 int_req, int_enable, dev_done, stop_inst; int32 lpt_err = 0; /* error flag */ int32 lpt_stopioe = 0; /* stop on error */ int32 lpt (int32 IR, int32 AC); t_stat lpt_svc (UNIT *uptr); t_stat lpt_reset (DEVICE *dptr); t_stat lpt_attach (UNIT *uptr, CONST char *cptr); t_stat lpt_detach (UNIT *uptr); /* LPT data structures lpt_dev LPT device descriptor lpt_unit LPT unit descriptor lpt_reg LPT register list */ DIB lpt_dib = { DEV_LPT, 1, { &lpt } }; UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 0), SERIAL_OUT_WAIT }; REG lpt_reg[] = { { ORDATAD (BUF, lpt_unit.buf, 8,"last data item processed") }, { FLDATAD (ERR, lpt_err, 0, "error status flag") }, { FLDATAD (DONE, dev_done, INT_V_LPT, "device done flag") }, { FLDATAD (ENABLE, int_enable, INT_V_LPT, "interrupt enable flag") }, { FLDATAD (INT, int_req, INT_V_LPT, "interrupt pending flag") }, { DRDATAD (POS, lpt_unit.pos, T_ADDR_W, "position in the output file"), PV_LEFT }, { DRDATAD (TIME, lpt_unit.wait, 24, "time from I/O initiation to interrupt"), PV_LEFT }, { FLDATAD (STOP_IOE, lpt_stopioe, 0, "stop on I/O error") }, { ORDATA (DEVNUM, lpt_dib.dev, 6), REG_HRO }, { NULL } }; MTAB lpt_mod[] = { { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { 0 } }; DEVICE lpt_dev = { "LPT", &lpt_unit, lpt_reg, lpt_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &lpt_reset, NULL, &lpt_attach, &lpt_detach, &lpt_dib, DEV_DISABLE }; /* IOT routine */ int32 lpt (int32 IR, int32 AC) { switch (IR & 07) { /* decode IR<9:11> */ case 0: /* PKSTF */ dev_done = dev_done | INT_LPT; /* set flag */ int_req = INT_UPDATE; /* update interrupts */ return AC; case 1: /* PSKF */ return (dev_done & INT_LPT)? IOT_SKP + AC: AC; case 2: /* PCLF */ dev_done = dev_done & ~INT_LPT; /* clear flag */ int_req = int_req & ~INT_LPT; /* clear int req */ return AC; case 3: /* PSKE */ return (lpt_err)? IOT_SKP + AC: AC; case 6: /* PCLF!PSTB */ dev_done = dev_done & ~INT_LPT; /* clear flag */ int_req = int_req & ~INT_LPT; /* clear int req */ case 4: /* PSTB */ lpt_unit.buf = AC & 0177; /* load buffer */ if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) || (lpt_unit.buf == 012)) { sim_activate (&lpt_unit, lpt_unit.wait); return AC; } return (lpt_svc (&lpt_unit) << IOT_V_REASON) + AC; case 5: /* PSIE */ int_enable = int_enable | INT_LPT; /* set enable */ int_req = INT_UPDATE; /* update interrupts */ return AC; case 7: /* PCIE */ int_enable = int_enable & ~INT_LPT; /* clear enable */ int_req = int_req & ~INT_LPT; /* clear int req */ return AC; default: return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ } /* Unit service */ t_stat lpt_svc (UNIT *uptr) { dev_done = dev_done | INT_LPT; /* set done */ int_req = INT_UPDATE; /* update interrupts */ if ((uptr->flags & UNIT_ATT) == 0) { lpt_err = 1; return IORETURN (lpt_stopioe, SCPE_UNATT); } fputc (uptr->buf, uptr->fileref); /* print char */ uptr->pos = ftell (uptr->fileref); if (ferror (uptr->fileref)) { /* error? */ sim_perror ("LPT I/O error"); clearerr (uptr->fileref); return SCPE_IOERR; } return SCPE_OK; } /* Reset routine */ t_stat lpt_reset (DEVICE *dptr) { lpt_unit.buf = 0; dev_done = dev_done & ~INT_LPT; /* clear done, int */ int_req = int_req & ~INT_LPT; int_enable = int_enable | INT_LPT; /* set enable */ lpt_err = (lpt_unit.flags & UNIT_ATT) == 0; sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; } /* Attach routine */ t_stat lpt_attach (UNIT *uptr, CONST char *cptr) { t_stat reason; reason = attach_unit (uptr, cptr); lpt_err = (lpt_unit.flags & UNIT_ATT) == 0; return reason; } /* Detach routine */ t_stat lpt_detach (UNIT *uptr) { lpt_err = 1; return detach_unit (uptr); } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 | /* pdp8_mt.c: PDP-8 magnetic tape simulator Copyright (c) 1993-2011, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. mt TM8E/TU10 magtape 16-Feb-06 RMS Added tape capacity checking 16-Aug-05 RMS Fixed C++ declaration and cast problems 18-Mar-05 RMS Added attached test to detach routine 25-Apr-03 RMS Revised for extended file support 29-Mar-03 RMS Added multiformat support 04-Mar-03 RMS Fixed bug in SKTR 01-Mar-03 RMS Fixed interrupt handling Revised for magtape library 30-Oct-02 RMS Revised BOT handling, added error record handling 04-Oct-02 RMS Added DIBs, device number support 30-Aug-02 RMS Revamped error handling 28-Aug-02 RMS Added end of medium support 30-May-02 RMS Widened POS to 32b 22-Apr-02 RMS Added maximum record length test 06-Jan-02 RMS Changed enable/disable support 30-Nov-01 RMS Added read only unit, extended SET/SHOW support 24-Nov-01 RMS Changed UST, POS, FLG to arrays 25-Apr-01 RMS Added device enable/disable support 04-Oct-98 RMS V2.4 magtape format 22-Jan-97 RMS V2.3 magtape format 01-Jan-96 RMS Rewritten from TM8-E Maintenance Manual Magnetic tapes are represented as a series of variable records of the form: 32b byte count byte 0 byte 1 : byte n-2 byte n-1 32b byte count If the byte count is odd, the record is padded with an extra byte of junk. File marks are represented by a byte count of 0. */ #include "pdp8_defs.h" #include "sim_tape.h" #define MT_NUMDR 8 /* #drives */ #define USTAT u3 /* unit status */ #define MT_MAXFR (1 << 16) /* max record lnt */ #define WC_SIZE (1 << 12) /* max word count */ #define WC_MASK (WC_SIZE - 1) /* Command/unit - mt_cu */ #define CU_V_UNIT 9 /* unit */ #define CU_M_UNIT 07 #define CU_PARITY 00400 /* parity select */ #define CU_IEE 00200 /* error int enable */ #define CU_IED 00100 /* done int enable */ #define CU_V_EMA 3 /* ext mem address */ #define CU_M_EMA 07 #define CU_EMA (CU_M_EMA << CU_V_EMA) #define CU_DTY 00002 /* drive type */ #define CU_UNPAK 00001 /* 6b vs 8b mode */ #define GET_UNIT(x) (((x) >> CU_V_UNIT) & CU_M_UNIT) #define GET_EMA(x) (((x) & CU_EMA) << (12 - CU_V_EMA)) /* Function - mt_fn */ #define FN_V_FNC 9 /* function */ #define FN_M_FNC 07 #define FN_UNLOAD 00 #define FN_REWIND 01 #define FN_READ 02 #define FN_CMPARE 03 #define FN_WRITE 04 #define FN_WREOF 05 #define FN_SPACEF 06 #define FN_SPACER 07 #define FN_ERASE 00400 /* erase */ #define FN_CRC 00200 /* read CRC */ #define FN_GO 00100 /* go */ #define FN_INC 00040 /* incr mode */ #define FN_RMASK 07700 /* readable bits */ #define GET_FNC(x) (((x) >> FN_V_FNC) & FN_M_FNC) /* Status - stored in mt_sta or (*) uptr->USTAT */ #define STA_ERR (04000 << 12) /* error */ #define STA_REW (02000 << 12) /* *rewinding */ #define STA_BOT (01000 << 12) /* *start of tape */ #define STA_REM (00400 << 12) /* *offline */ #define STA_PAR (00200 << 12) /* parity error */ #define STA_EOF (00100 << 12) /* *end of file */ #define STA_RLE (00040 << 12) /* rec lnt error */ #define STA_DLT (00020 << 12) /* data late */ #define STA_EOT (00010 << 12) /* *end of tape */ #define STA_WLK (00004 << 12) /* *write locked */ #define STA_CPE (00002 << 12) /* compare error */ #define STA_ILL (00001 << 12) /* illegal */ #define STA_9TK 00040 /* 9 track */ /* #define STA_BAD 00020 *//* bad tape?? */ #define STA_INC 00010 /* increment error */ #define STA_LAT 00004 /* lateral par error */ #define STA_CRC 00002 /* CRC error */ #define STA_LON 00001 /* long par error */ #define STA_CLR (FN_RMASK | 00020) /* always clear */ #define STA_DYN (STA_REW | STA_BOT | STA_REM | STA_EOF | \ STA_EOT | STA_WLK) /* kept in USTAT */ extern uint16 M[]; extern int32 int_req, stop_inst; extern UNIT cpu_unit; int32 mt_cu = 0; /* command/unit */ int32 mt_fn = 0; /* function */ int32 mt_ca = 0; /* current address */ int32 mt_wc = 0; /* word count */ int32 mt_sta = 0; /* status register */ int32 mt_db = 0; /* data buffer */ int32 mt_done = 0; /* mag tape flag */ int32 mt_time = 10; /* record latency */ int32 mt_stopioe = 1; /* stop on error */ uint8 *mtxb = NULL; /* transfer buffer */ int32 mt70 (int32 IR, int32 AC); int32 mt71 (int32 IR, int32 AC); int32 mt72 (int32 IR, int32 AC); t_stat mt_svc (UNIT *uptr); t_stat mt_reset (DEVICE *dptr); t_stat mt_attach (UNIT *uptr, CONST char *cptr); t_stat mt_detach (UNIT *uptr); int32 mt_updcsta (UNIT *uptr); int32 mt_ixma (int32 xma); t_stat mt_map_err (UNIT *uptr, t_stat st); t_stat mt_vlock (UNIT *uptr, int32 val, CONST char *cptr, void *desc); UNIT *mt_busy (void); void mt_set_done (void); /* MT data structures mt_dev MT device descriptor mt_unit MT unit list mt_reg MT register list mt_mod MT modifier list */ DIB mt_dib = { DEV_MT, 3, { &mt70, &mt71, &mt72 } }; UNIT mt_unit[] = { { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } }; REG mt_reg[] = { { ORDATAD (CMD, mt_cu, 12, "command") }, { ORDATAD (FNC, mt_fn, 12, "function") }, { ORDATAD (CA, mt_ca, 12, "memory address") }, { ORDATAD (WC, mt_wc, 12, "word count") }, { ORDATAD (DB, mt_db, 12, "data buffer") }, { GRDATAD (STA, mt_sta, 8, 12, 12, "status buffer") }, { ORDATAD (STA2, mt_sta, 6, "secondary status") }, { FLDATAD (DONE, mt_done, 0, "device done flag") }, { FLDATAD (INT, int_req, INT_V_MT, "interrupt pending flag") }, { FLDATAD (STOP_IOE, mt_stopioe, 0, "stop on I/O error") }, { DRDATAD (TIME, mt_time, 24, "record delay"), PV_LEFT }, { URDATAD (UST, mt_unit[0].USTAT, 8, 16, 0, MT_NUMDR, 0, "unit status, units 0 to 7") }, { URDATAD (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, MT_NUMDR, PV_LEFT | REG_RO, "position, units 0 to 7") }, { FLDATA (DEVNUM, mt_dib.dev, 6), REG_HRO }, { NULL } }; MTAB mt_mod[] = { { MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mt_vlock }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mt_vlock }, { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, { MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY", &sim_tape_set_capac, &sim_tape_show_capac, NULL }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { 0 } }; DEVICE mt_dev = { "MT", mt_unit, mt_reg, mt_mod, MT_NUMDR, 10, 31, 1, 8, 8, NULL, NULL, &mt_reset, NULL, &mt_attach, &mt_detach, &mt_dib, DEV_DISABLE | DEV_TAPE }; /* IOT routines */ int32 mt70 (int32 IR, int32 AC) { int32 f; UNIT *uptr; uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */ switch (IR & 07) { /* decode IR<9:11> */ case 1: /* LWCR */ mt_wc = AC; /* load word count */ return 0; case 2: /* CWCR */ mt_wc = 0; /* clear word count */ return AC; case 3: /* LCAR */ mt_ca = AC; /* load mem address */ return 0; case 4: /* CCAR */ mt_ca = 0; /* clear mem address */ return AC; case 5: /* LCMR */ if (mt_busy ()) /* busy? illegal op */ mt_sta = mt_sta | STA_ILL | STA_ERR; mt_cu = AC; /* load command reg */ mt_updcsta (mt_dev.units + GET_UNIT (mt_cu)); return 0; case 6: /* LFGR */ if (mt_busy ()) /* busy? illegal op */ mt_sta = mt_sta | STA_ILL | STA_ERR; mt_fn = AC; /* load function */ if ((mt_fn & FN_GO) == 0) { /* go set? */ mt_updcsta (uptr); /* update status */ return 0; } f = GET_FNC (mt_fn); /* get function */ if (((uptr->flags & UNIT_ATT) == 0) || sim_is_active (uptr) || (((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr)) || (((f == FN_SPACER) || (f == FN_REWIND)) && sim_tape_bot (uptr))) { mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal op error */ mt_set_done (); /* set done */ mt_updcsta (uptr); /* update status */ return 0; } uptr->USTAT = uptr->USTAT & STA_WLK; /* clear status */ if (f == FN_UNLOAD) { /* unload? */ detach_unit (uptr); /* set offline */ uptr->USTAT = STA_REW | STA_REM; /* rewinding, off */ mt_set_done (); /* set done */ } else if (f == FN_REWIND) { /* rewind */ uptr->USTAT = uptr->USTAT | STA_REW; /* rewinding */ mt_set_done (); /* set done */ } else mt_done = 0; /* clear done */ mt_updcsta (uptr); /* update status */ sim_activate (uptr, mt_time); /* start io */ return 0; case 7: /* LDBR */ if (mt_busy ()) /* busy? illegal op */ mt_sta = mt_sta | STA_ILL | STA_ERR; mt_db = AC; /* load buffer */ mt_set_done (); /* set done */ mt_updcsta (uptr); /* update status */ return 0; } /* end switch */ return (stop_inst << IOT_V_REASON) + AC; /* ill inst */ } int32 mt71 (int32 IR, int32 AC) { UNIT *uptr; uptr = mt_dev.units + GET_UNIT (mt_cu); switch (IR & 07) { /* decode IR<9:11> */ case 1: /* RWCR */ return mt_wc; /* read word count */ case 2: /* CLT */ mt_reset (&mt_dev); /* reset everything */ return AC; case 3: /* RCAR */ return mt_ca; /* read mem address */ case 4: /* RMSR */ return ((mt_updcsta (uptr) >> 12) & 07777); /* read status */ case 5: /* RCMR */ return mt_cu; /* read command */ case 6: /* RFSR */ return (((mt_fn & FN_RMASK) | (mt_updcsta (uptr) & ~FN_RMASK)) & 07777); /* read function */ case 7: /* RDBR */ return mt_db; /* read data buffer */ } return (stop_inst << IOT_V_REASON) + AC; /* ill inst */ } int32 mt72 (int32 IR, int32 AC) { UNIT *uptr; uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */ switch (IR & 07) { /* decode IR<9:11> */ case 1: /* SKEF */ return (mt_sta & STA_ERR)? IOT_SKP + AC: AC; case 2: /* SKCB */ return (!mt_busy ())? IOT_SKP + AC: AC; case 3: /* SKJD */ return mt_done? IOT_SKP + AC: AC; case 4: /* SKTR */ return (!sim_is_active (uptr) && (uptr->flags & UNIT_ATT))? IOT_SKP + AC: AC; case 5: /* CLF */ if (!sim_is_active (uptr)) mt_reset (&mt_dev); /* if TUR, zap */ else { /* just ctrl zap */ mt_sta = 0; /* clear status */ mt_done = 0; /* clear done */ mt_updcsta (uptr); /* update status */ } return AC; } /* end switch */ return (stop_inst << IOT_V_REASON) + AC; /* ill inst */ } /* Unit service If rewind done, reposition to start of tape, set status else, do operation, set done, interrupt */ t_stat mt_svc (UNIT *uptr) { int32 f, i, p, u, wc, xma; t_mtrlnt tbc, cbc; t_bool passed_eot; uint16 c, c1, c2; t_stat st, r = SCPE_OK; u = (int32) (uptr - mt_dev.units); /* get unit number */ f = GET_FNC (mt_fn); /* get command */ xma = GET_EMA (mt_cu) + mt_ca; /* get mem addr */ wc = WC_SIZE - mt_wc; /* get wc */ if (uptr->USTAT & STA_REW) { /* rewind? */ sim_tape_rewind (uptr); /* update position */ if (uptr->flags & UNIT_ATT) /* still on line? */ uptr->USTAT = (uptr->USTAT & STA_WLK) | STA_BOT; else uptr->USTAT = STA_REM; if (u == GET_UNIT (mt_cu)) { /* selected? */ mt_set_done (); /* set done */ mt_updcsta (uptr); /* update status */ } return SCPE_OK; } if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */ uptr->USTAT = STA_REM; /* unit off line */ mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */ mt_set_done (); /* set done */ mt_updcsta (uptr); /* update status */ return IORETURN (mt_stopioe, SCPE_UNATT); } passed_eot = sim_tape_eot (uptr); /* passed eot? */ switch (f) { /* case on function */ case FN_READ: /* read */ case FN_CMPARE: /* read/compare */ st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */ if (st == MTSE_RECE) /* rec in err? */ mt_sta = mt_sta | STA_PAR | STA_ERR; else if (st != MTSE_OK) { /* other error? */ r = mt_map_err (uptr, st); /* map error */ mt_sta = mt_sta | STA_RLE | STA_ERR; /* err, eof/eom, tmk */ break; } cbc = (mt_cu & CU_UNPAK)? wc: wc * 2; /* expected bc */ if (tbc != cbc) /* wrong size? */ mt_sta = mt_sta | STA_RLE | STA_ERR; if (tbc < cbc) { /* record small? */ cbc = tbc; /* use smaller */ wc = (mt_cu & CU_UNPAK)? cbc: (cbc + 1) / 2; } for (i = p = 0; i < wc; i++) { /* copy buffer */ xma = mt_ixma (xma); /* increment xma */ mt_wc = (mt_wc + 1) & 07777; /* incr word cnt */ if (mt_cu & CU_UNPAK) c = mtxb[p++]; else { c1 = mtxb[p++] & 077; c2 = mtxb[p++] & 077; c = (c1 << 6) | c2; } if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c; else if ((f == FN_CMPARE) && (M[xma] != c)) { mt_sta = mt_sta | STA_CPE | STA_ERR; break; } } break; case FN_WRITE: /* write */ tbc = (mt_cu & CU_UNPAK)? wc: wc * 2; for (i = p = 0; i < wc; i++) { /* copy buf to tape */ xma = mt_ixma (xma); /* incr mem addr */ if (mt_cu & CU_UNPAK) mtxb[p++] = M[xma] & 0377; else { mtxb[p++] = (M[xma] >> 6) & 077; mtxb[p++] = M[xma] & 077; } } if ((st = sim_tape_wrrecf (uptr, mtxb, tbc))) { /* write rec, err? */ r = mt_map_err (uptr, st); /* map error */ xma = GET_EMA (mt_cu) + mt_ca; /* restore xma */ } else mt_wc = 0; /* ok, clear wc */ break; case FN_WREOF: if ((st = sim_tape_wrtmk (uptr))) /* write tmk, err? */ r = mt_map_err (uptr, st); /* map error */ break; case FN_SPACEF: /* space forward */ do { mt_wc = (mt_wc + 1) & 07777; /* incr wc */ if ((st = sim_tape_sprecf (uptr, &tbc))) { /* space rec fwd, err? */ r = mt_map_err (uptr, st); /* map error */ break; /* stop */ } } while ((mt_wc != 0) && (passed_eot || !sim_tape_eot (uptr))); break; case FN_SPACER: /* space reverse */ do { mt_wc = (mt_wc + 1) & 07777; /* incr wc */ if ((st = sim_tape_sprecr (uptr, &tbc))) { /* space rec rev, err? */ r = mt_map_err (uptr, st); /* map error */ break; /* stop */ } } while (mt_wc != 0); break; } /* end case */ if (!passed_eot && sim_tape_eot (uptr)) /* just passed EOT? */ uptr->USTAT = uptr->USTAT | STA_EOT; mt_cu = (mt_cu & ~CU_EMA) | ((xma >> (12 - CU_V_EMA)) & CU_EMA); mt_ca = xma & 07777; /* update mem addr */ mt_set_done (); /* set done */ mt_updcsta (uptr); /* update status */ return r; } /* Update controller status */ int32 mt_updcsta (UNIT *uptr) { mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN); if (((mt_sta & STA_ERR) && (mt_cu & CU_IEE)) || (mt_done && (mt_cu & CU_IED))) int_req = int_req | INT_MT; else int_req = int_req & ~INT_MT; return mt_sta; } /* Test if controller busy */ UNIT *mt_busy (void) { int32 u; UNIT *uptr; for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ uptr = mt_dev.units + u; if (sim_is_active (uptr) && ((uptr->USTAT & STA_REW) == 0)) return uptr; } return NULL; } /* Increment extended memory address */ int32 mt_ixma (int32 xma) /* incr extended ma */ { int32 v; v = ((xma + 1) & 07777) | (xma & 070000); /* wrapped incr */ if (mt_fn & FN_INC) { /* increment mode? */ if (xma == 077777) /* at limit? error */ mt_sta = mt_sta | STA_INC | STA_ERR; else v = xma + 1; /* else 15b incr */ } return v; } /* Set done */ void mt_set_done (void) { mt_done = 1; /* set done */ mt_fn = mt_fn & ~(FN_CRC | FN_GO | FN_INC); /* clear func<4:6> */ return; } /* Map tape error status */ t_stat mt_map_err (UNIT *uptr, t_stat st) { switch (st) { case MTSE_FMT: /* illegal fmt */ case MTSE_UNATT: /* unattached */ mt_sta = mt_sta | STA_ILL | STA_ERR; case MTSE_OK: /* no error */ return SCPE_IERR; /* never get here! */ case MTSE_TMK: /* end of file */ uptr->USTAT = uptr->USTAT | STA_EOF; /* set EOF */ mt_sta = mt_sta | STA_ERR; break; case MTSE_IOERR: /* IO error */ mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ if (mt_stopioe) return SCPE_IOERR; break; case MTSE_INVRL: /* invalid rec lnt */ mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ return SCPE_MTRLNT; case MTSE_RECE: /* record in error */ case MTSE_EOM: /* end of medium */ mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ break; case MTSE_BOT: /* reverse into BOT */ uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */ mt_sta = mt_sta | STA_ERR; break; case MTSE_WRP: /* write protect */ mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */ break; } return SCPE_OK; } /* Reset routine */ t_stat mt_reset (DEVICE *dptr) { int32 u; UNIT *uptr; mt_cu = mt_fn = mt_wc = mt_ca = mt_db = mt_sta = mt_done = 0; int_req = int_req & ~INT_MT; /* clear interrupt */ for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ uptr = mt_dev.units + u; sim_cancel (uptr); /* cancel activity */ sim_tape_reset (uptr); /* reset tape */ if (uptr->flags & UNIT_ATT) uptr->USTAT = (sim_tape_bot (uptr)? STA_BOT: 0) | (sim_tape_wrp (uptr)? STA_WLK: 0); else uptr->USTAT = STA_REM; } if (mtxb == NULL) mtxb = (uint8 *) calloc (MT_MAXFR, sizeof (uint8)); if (mtxb == NULL) return SCPE_MEM; return SCPE_OK; } /* Attach routine */ t_stat mt_attach (UNIT *uptr, CONST char *cptr) { t_stat r; int32 u = uptr - mt_dev.units; /* get unit number */ r = sim_tape_attach (uptr, cptr); if (r != SCPE_OK) return r; uptr->USTAT = STA_BOT | (sim_tape_wrp (uptr)? STA_WLK: 0); if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); return r; } /* Detach routine */ t_stat mt_detach (UNIT* uptr) { int32 u = uptr - mt_dev.units; /* get unit number */ if (!(uptr->flags & UNIT_ATT)) /* check for attached */ return SCPE_OK; if (!sim_is_active (uptr)) uptr->USTAT = STA_REM; if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); return sim_tape_detach (uptr); } /* Write lock/enable routine */ t_stat mt_vlock (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int32 u = uptr - mt_dev.units; /* get unit number */ if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr))) uptr->USTAT = uptr->USTAT | STA_WLK; else uptr->USTAT = uptr->USTAT & ~STA_WLK; if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | /* pdp8_pt.c: PDP-8 paper tape reader/punch simulator Copyright (c) 1993-2017, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. ptr,ptp PC8E paper tape reader/punch 13-Mar-17 RMS Annotated fall through in switch 17-Mar-13 RMS Modified to use central set_bootpc routine 25-Apr-03 RMS Revised for extended file support 04-Oct-02 RMS Added DIBs 30-May-02 RMS Widened POS to 32b 30-Nov-01 RMS Added read only unit support 30-Mar-98 RMS Added RIM loader as PTR bootstrap */ #include "pdp8_defs.h" extern int32 int_req, int_enable, dev_done, stop_inst; int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ int32 ptr (int32 IR, int32 AC); int32 ptp (int32 IR, int32 AC); t_stat ptr_svc (UNIT *uptr); t_stat ptp_svc (UNIT *uptr); t_stat ptr_reset (DEVICE *dptr); t_stat ptp_reset (DEVICE *dptr); t_stat ptr_boot (int32 unitno, DEVICE *dptr); /* PTR data structures ptr_dev PTR device descriptor ptr_unit PTR unit descriptor ptr_reg PTR register list */ DIB ptr_dib = { DEV_PTR, 1, { &ptr } }; UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), SERIAL_IN_WAIT }; REG ptr_reg[] = { { ORDATAD (BUF, ptr_unit.buf, 8, "last data item processed") }, { FLDATAD (DONE, dev_done, INT_V_PTR, "device done flag") }, { FLDATAD (ENABLE, int_enable, INT_V_PTR, "interrupt enable flag") }, { FLDATAD (INT, int_req, INT_V_PTR, "interrupt pending flag") }, { DRDATAD (POS, ptr_unit.pos, T_ADDR_W, "position in the input file"), PV_LEFT }, { DRDATAD (TIME, ptr_unit.wait, 24, "time from I/O initiation to interrupt"), PV_LEFT }, { FLDATAD (STOP_IOE, ptr_stopioe, 0, "stop on I/O error") }, { NULL } }; MTAB ptr_mod[] = { { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, { 0 } }; DEVICE ptr_dev = { "PTR", &ptr_unit, ptr_reg, ptr_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &ptr_reset, &ptr_boot, NULL, NULL, &ptr_dib, 0 }; /* PTP data structures ptp_dev PTP device descriptor ptp_unit PTP unit descriptor ptp_reg PTP register list */ DIB ptp_dib = { DEV_PTP, 1, { &ptp } }; UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; REG ptp_reg[] = { { ORDATAD (BUF, ptp_unit.buf, 8, "last data item processed") }, { FLDATAD (DONE, dev_done, INT_V_PTP, "device done flag") }, { FLDATAD (ENABLE, int_enable, INT_V_PTP, "interrupt enable flag") }, { FLDATAD (INT, int_req, INT_V_PTP, "interrupt pending flag") }, { DRDATAD (POS, ptp_unit.pos, T_ADDR_W, "position in the output file"), PV_LEFT }, { DRDATAD (TIME, ptp_unit.wait, 24, "time from I/O initiation to interrupt"), PV_LEFT }, { FLDATAD (STOP_IOE, ptp_stopioe, 0, "stop on I/O error") }, { NULL } }; MTAB ptp_mod[] = { { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, { 0 } }; DEVICE ptp_dev = { "PTP", &ptp_unit, ptp_reg, ptp_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &ptp_reset, NULL, NULL, NULL, &ptp_dib, 0 }; /* Paper tape reader: IOT routine */ int32 ptr (int32 IR, int32 AC) { switch (IR & 07) { /* decode IR<9:11> */ case 0: /* RPE */ int_enable = int_enable | (INT_PTR+INT_PTP); /* set enable */ int_req = INT_UPDATE; /* update interrupts */ return AC; case 1: /* RSF */ return (dev_done & INT_PTR)? IOT_SKP + AC: AC; case 6: /* RFC!RRB */ sim_activate (&ptr_unit, ptr_unit.wait); /* activate */ /* fall through */ case 2: /* RRB */ dev_done = dev_done & ~INT_PTR; /* clear flag */ int_req = int_req & ~INT_PTR; /* clear int req */ return (AC | ptr_unit.buf); /* or data to AC */ case 4: /* RFC */ sim_activate (&ptr_unit, ptr_unit.wait); dev_done = dev_done & ~INT_PTR; /* clear flag */ int_req = int_req & ~INT_PTR; /* clear int req */ return AC; default: return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ } /* Unit service */ t_stat ptr_svc (UNIT *uptr) { int32 temp; if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (ptr_stopioe, SCPE_UNATT); if ((temp = getc (ptr_unit.fileref)) == EOF) { if (feof (ptr_unit.fileref)) { if (ptr_stopioe) sim_printf ("PTR end of file\n"); else return SCPE_OK; } else sim_perror ("PTR I/O error"); clearerr (ptr_unit.fileref); return SCPE_IOERR; } dev_done = dev_done | INT_PTR; /* set done */ int_req = INT_UPDATE; /* update interrupts */ ptr_unit.buf = temp & 0377; ptr_unit.pos = ptr_unit.pos + 1; return SCPE_OK; } /* Reset routine */ t_stat ptr_reset (DEVICE *dptr) { ptr_unit.buf = 0; dev_done = dev_done & ~INT_PTR; /* clear done, int */ int_req = int_req & ~INT_PTR; int_enable = int_enable | INT_PTR; /* set enable */ sim_cancel (&ptr_unit); /* deactivate unit */ return SCPE_OK; } /* Paper tape punch: IOT routine */ int32 ptp (int32 IR, int32 AC) { switch (IR & 07) { /* decode IR<9:11> */ case 0: /* PCE */ int_enable = int_enable & ~(INT_PTR+INT_PTP); /* clear enables */ int_req = INT_UPDATE; /* update interrupts */ return AC; case 1: /* PSF */ return (dev_done & INT_PTP)? IOT_SKP + AC: AC; case 2: /* PCF */ dev_done = dev_done & ~INT_PTP; /* clear flag */ int_req = int_req & ~INT_PTP; /* clear int req */ return AC; case 6: /* PLS */ dev_done = dev_done & ~INT_PTP; /* clear flag */ int_req = int_req & ~INT_PTP; /* clear int req */ case 4: /* PPC */ ptp_unit.buf = AC & 0377; /* load punch buf */ sim_activate (&ptp_unit, ptp_unit.wait); /* activate unit */ return AC; default: return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ } /* Unit service */ t_stat ptp_svc (UNIT *uptr) { dev_done = dev_done | INT_PTP; /* set done */ int_req = INT_UPDATE; /* update interrupts */ if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (ptp_stopioe, SCPE_UNATT); if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { sim_perror ("PTP I/O error"); clearerr (ptp_unit.fileref); return SCPE_IOERR; } ptp_unit.pos = ptp_unit.pos + 1; return SCPE_OK; } /* Reset routine */ t_stat ptp_reset (DEVICE *dptr) { ptp_unit.buf = 0; dev_done = dev_done & ~INT_PTP; /* clear done, int */ int_req = int_req & ~INT_PTP; int_enable = int_enable | INT_PTP; /* set enable */ sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; } /* Bootstrap routine */ #define BOOT_START 07756 #define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) static const uint16 boot_rom[] = { 06014, /* 7756, RFC */ 06011, /* 7757, LOOP, RSF */ 05357, /* JMP .-1 */ 06016, /* RFC RRB */ 07106, /* CLL RTL*/ 07006, /* RTL */ 07510, /* SPA*/ 05374, /* JMP 7774 */ 07006, /* RTL */ 06011, /* RSF */ 05367, /* JMP .-1 */ 06016, /* RFC RRB */ 07420, /* SNL */ 03776, /* DCA I 7776 */ 03376, /* 7774, DCA 7776 */ 05357, /* JMP 7757 */ 00000, /* 7776, 0 */ 05301 /* 7777, JMP 7701 */ }; t_stat ptr_boot (int32 unitno, DEVICE *dptr) { size_t i; extern uint16 M[]; if (ptr_dib.dev != DEV_PTR) /* only std devno */ return STOP_NOTSTD; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; cpu_set_bootpc (BOOT_START); return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 | /* pdp8_rf.c: RF08 fixed head disk simulator Copyright (c) 1993-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. rf RF08 fixed head disk 17-Sep-13 RMS Changed to use central set_bootpc routine 03-Sep-13 RMS Added explicit void * cast 15-May-06 RMS Fixed bug in autosize attach (Dave Gesswein) 07-Jan-06 RMS Fixed unaligned register access bug (Doug Carman) 04-Jan-04 RMS Changed sim_fsize calling sequence 26-Oct-03 RMS Cleaned up buffer copy code 26-Jul-03 RMS Fixed bug in set size routine 14-Mar-03 RMS Fixed variable platter interaction with save/restore 03-Mar-03 RMS Fixed autosizing 02-Feb-03 RMS Added variable platter and autosizing support 04-Oct-02 RMS Added DIB, device number support 28-Nov-01 RMS Added RL8A support 25-Apr-01 RMS Added device enable/disable support 19-Mar-01 RMS Added disk monitor bootstrap, fixed IOT decoding 15-Feb-01 RMS Fixed 3 cycle data break sequence 14-Apr-99 RMS Changed t_addr to unsigned 30-Mar-98 RMS Fixed bug in RF bootstrap The RF08 is a head-per-track disk. It uses the three cycle data break facility. To minimize overhead, the entire RF08 is buffered in memory. Two timing parameters are provided: rf_time Interword timing, must be non-zero rf_burst Burst mode, if 0, DMA occurs cycle by cycle; otherwise, DMA occurs in a burst */ #include "pdp8_defs.h" #include <math.h> #define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ #define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */ #define UNIT_M_PLAT 03 #define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1) #define UNIT_AUTO (1 << UNIT_V_AUTO) #define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) /* Constants */ #define RF_NUMWD 2048 /* words/track */ #define RF_NUMTR 128 /* tracks/disk */ #define RF_DKSIZE (RF_NUMTR * RF_NUMWD) /* words/disk */ #define RF_NUMDK 4 /* disks/controller */ #define RF_WC 07750 /* word count */ #define RF_MA 07751 /* mem address */ #define RF_WMASK (RF_NUMWD - 1) /* word mask */ /* Parameters in the unit descriptor */ #define FUNC u4 /* function */ #define RF_READ 2 /* read */ #define RF_WRITE 4 /* write */ /* Status register */ #define RFS_PCA 04000 /* photocell status */ #define RFS_DRE 02000 /* data req enable */ #define RFS_WLS 01000 /* write lock status */ #define RFS_EIE 00400 /* error int enable */ #define RFS_PIE 00200 /* photocell int enb */ #define RFS_CIE 00100 /* done int enable */ #define RFS_MEX 00070 /* memory extension */ #define RFS_DRL 00004 /* data late error */ #define RFS_NXD 00002 /* non-existent disk */ #define RFS_PER 00001 /* parity error */ #define RFS_ERR (RFS_WLS + RFS_DRL + RFS_NXD + RFS_PER) #define RFS_V_MEX 3 #define GET_MEX(x) (((x) & RFS_MEX) << (12 - RFS_V_MEX)) #define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ ((double) RF_NUMWD))) #define UPDATE_PCELL if (GET_POS(rf_time) < 6) rf_sta = rf_sta | RFS_PCA; \ else rf_sta = rf_sta & ~RFS_PCA #define RF_INT_UPDATE if ((rf_done && (rf_sta & RFS_CIE)) || \ ((rf_sta & RFS_ERR) && (rf_sta & RFS_EIE)) || \ ((rf_sta & RFS_PCA) && (rf_sta & RFS_PIE))) \ int_req = int_req | INT_RF; \ else int_req = int_req & ~INT_RF extern uint16 M[]; extern int32 int_req, stop_inst; extern UNIT cpu_unit; int32 rf_sta = 0; /* status register */ int32 rf_da = 0; /* disk address */ int32 rf_done = 0; /* done flag */ int32 rf_wlk = 0; /* write lock */ int32 rf_time = 10; /* inter-word time */ int32 rf_burst = 1; /* burst mode flag */ int32 rf_stopioe = 1; /* stop on error */ int32 rf60 (int32 IR, int32 AC); int32 rf61 (int32 IR, int32 AC); int32 rf62 (int32 IR, int32 AC); int32 rf64 (int32 IR, int32 AC); t_stat rf_svc (UNIT *uptr); t_stat pcell_svc (UNIT *uptr); t_stat rf_reset (DEVICE *dptr); t_stat rf_boot (int32 unitno, DEVICE *dptr); t_stat rf_attach (UNIT *uptr, CONST char *cptr); t_stat rf_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc); /* RF08 data structures rf_dev RF device descriptor rf_unit RF unit descriptor pcell_unit photocell timing unit (orphan) rf_reg RF register list */ DIB rf_dib = { DEV_RF, 5, { &rf60, &rf61, &rf62, NULL, &rf64 } }; UNIT rf_unit = { UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+ UNIT_BUFABLE+UNIT_MUSTBUF, RF_DKSIZE) }; UNIT pcell_unit = { UDATA (&pcell_svc, 0, 0) }; REG rf_reg[] = { { ORDATAD (STA, rf_sta, 12, "status") }, { ORDATAD (DA, rf_da, 20, "low order disk address") }, { ORDATAD (WC, M[RF_WC], 12, "word count (in memory)"), REG_FIT }, { ORDATAD (MA, M[RF_MA], 12, "memory address (in memory)"), REG_FIT }, { FLDATAD (DONE, rf_done, 0, "device done flag") }, { FLDATAD (INT, int_req, INT_V_RF, "interrupt pending flag") }, { ORDATAD (WLK, rf_wlk, 32, "write lock switches") }, { DRDATAD (TIME, rf_time, 24, "rotational delay, per word"), REG_NZ + PV_LEFT }, { FLDATAD (BURST, rf_burst, 0, "burst flag") }, { FLDATAD (STOP_IOE, rf_stopioe, 0, "stop on I/O error") }, { DRDATA (CAPAC, rf_unit.capac, 21), REG_HRO }, { ORDATA (DEVNUM, rf_dib.dev, 6), REG_HRO }, { NULL } }; MTAB rf_mod[] = { { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size }, { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size }, { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size }, { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size }, { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { 0 } }; DEVICE rf_dev = { "RF", &rf_unit, rf_reg, rf_mod, 1, 8, 20, 1, 8, 12, NULL, NULL, &rf_reset, &rf_boot, &rf_attach, NULL, &rf_dib, DEV_DISABLE | DEV_DIS }; /* IOT routines */ int32 rf60 (int32 IR, int32 AC) { int32 t; int32 pulse = IR & 07; UPDATE_PCELL; /* update photocell */ if (pulse & 1) { /* DCMA */ rf_da = rf_da & ~07777; /* clear DAR<8:19> */ rf_done = 0; /* clear done */ rf_sta = rf_sta & ~RFS_ERR; /* clear errors */ RF_INT_UPDATE; /* update int req */ } if (pulse & 6) { /* DMAR, DMAW */ rf_da = rf_da | AC; /* DAR<8:19> |= AC */ rf_unit.FUNC = pulse & ~1; /* save function */ t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new loc */ if (t < 0) /* wrap around? */ t = t + RF_NUMWD; sim_activate (&rf_unit, t * rf_time); /* schedule op */ AC = 0; /* clear AC */ } return AC; } int32 rf61 (int32 IR, int32 AC) { int32 pulse = IR & 07; UPDATE_PCELL; /* update photocell */ switch (pulse) { /* decode IR<9:11> */ case 1: /* DCIM */ rf_sta = rf_sta & 07007; /* clear STA<3:8> */ int_req = int_req & ~INT_RF; /* clear int req */ sim_cancel (&pcell_unit); /* cancel photocell */ return AC; case 2: /* DSAC */ return ((rf_da & RF_WMASK) == GET_POS (rf_time))? IOT_SKP: 0; case 5: /* DIML */ rf_sta = (rf_sta & 07007) | (AC & 0770); /* STA<3:8> <- AC */ if (rf_sta & RFS_PIE) /* photocell int? */ sim_activate (&pcell_unit, (RF_NUMWD - GET_POS (rf_time)) * rf_time); else sim_cancel (&pcell_unit); RF_INT_UPDATE; /* update int req */ return 0; /* clear AC */ case 6: /* DIMA */ return rf_sta; /* AC <- STA<0:11> */ } return AC; } int32 rf62 (int32 IR, int32 AC) { int32 pulse = IR & 07; UPDATE_PCELL; /* update photocell */ if (pulse & 1) { /* DFSE */ if (rf_sta & RFS_ERR) AC = AC | IOT_SKP; } if (pulse & 2) { /* DFSC */ if (pulse & 4) /* for DMAC */ AC = AC & ~07777; else if (rf_done) AC = AC | IOT_SKP; } if (pulse & 4) /* DMAC */ AC = AC | (rf_da & 07777); return AC; } int32 rf64 (int32 IR, int32 AC) { int32 pulse = IR & 07; UPDATE_PCELL; /* update photocell */ switch (pulse) { /* decode IR<9:11> */ case 1: /* DCXA */ rf_da = rf_da & 07777; /* clear DAR<0:7> */ break; case 3: /* DXAL */ rf_da = rf_da & 07777; /* clear DAR<0:7> */ case 2: /* DXAL w/o clear */ rf_da = rf_da | ((AC & 0377) << 12); /* DAR<0:7> |= AC */ AC = 0; /* clear AC */ break; case 5: /* DXAC */ AC = 0; /* clear AC */ case 4: /* DXAC w/o clear */ AC = AC | ((rf_da >> 12) & 0377); /* AC |= DAR<0:7> */ break; default: AC = (stop_inst << IOT_V_REASON) + AC; break; } /* end switch */ if ((uint32) rf_da >= rf_unit.capac) rf_sta = rf_sta | RFS_NXD; else rf_sta = rf_sta & ~RFS_NXD; RF_INT_UPDATE; return AC; } /* Unit service Note that for reads and writes, memory addresses wrap around in the current field. This code assumes the entire disk is buffered. */ t_stat rf_svc (UNIT *uptr) { int32 pa, t, mex; int16 *fbuf = (int16 *) uptr->filebuf; UPDATE_PCELL; /* update photocell */ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ rf_sta = rf_sta | RFS_NXD; rf_done = 1; RF_INT_UPDATE; /* update int req */ return IORETURN (rf_stopioe, SCPE_UNATT); } mex = GET_MEX (rf_sta); do { if ((uint32) rf_da >= rf_unit.capac) { /* disk overflow? */ rf_sta = rf_sta | RFS_NXD; break; } M[RF_WC] = (M[RF_WC] + 1) & 07777; /* incr word count */ M[RF_MA] = (M[RF_MA] + 1) & 07777; /* incr mem addr */ pa = mex | M[RF_MA]; /* add extension */ if (uptr->FUNC == RF_READ) { /* read? */ if (MEM_ADDR_OK (pa)) /* if !nxm */ M[pa] = fbuf[rf_da]; /* read word */ } else { /* write */ t = ((rf_da >> 15) & 030) | ((rf_da >> 14) & 07); if ((rf_wlk >> t) & 1) /* write locked? */ rf_sta = rf_sta | RFS_WLS; else { /* not locked */ fbuf[rf_da] = M[pa]; /* write word */ if (((uint32) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1; } } rf_da = (rf_da + 1) & 03777777; /* incr disk addr */ } while ((M[RF_WC] != 0) && (rf_burst != 0)); /* brk if wc, no brst */ if ((M[RF_WC] != 0) && ((rf_sta & RFS_ERR) == 0)) /* more to do? */ sim_activate (&rf_unit, rf_time); /* sched next */ else { rf_done = 1; /* done */ RF_INT_UPDATE; /* update int req */ } return SCPE_OK; } /* Photocell unit service */ t_stat pcell_svc (UNIT *uptr) { rf_sta = rf_sta | RFS_PCA; /* set photocell */ if (rf_sta & RFS_PIE) { /* int enable? */ sim_activate (&pcell_unit, RF_NUMWD * rf_time); int_req = int_req | INT_RF; } return SCPE_OK; } /* Reset routine */ t_stat rf_reset (DEVICE *dptr) { rf_sta = rf_da = 0; rf_done = 1; int_req = int_req & ~INT_RF; /* clear interrupt */ sim_cancel (&rf_unit); sim_cancel (&pcell_unit); return SCPE_OK; } /* Bootstrap routine */ #define OS8_START 07750 #define OS8_LEN (sizeof (os8_rom) / sizeof (int16)) #define DM4_START 00200 #define DM4_LEN (sizeof (dm4_rom) / sizeof (int16)) static const uint16 os8_rom[] = { 07600, /* 7750, CLA CLL ; also word count */ 06603, /* 7751, DMAR ; also address */ 06622, /* 7752, DFSC ; done? */ 05352, /* 7753, JMP .-1 ; no */ 05752 /* 7754, JMP @.-2 ; enter boot */ }; static const uint16 dm4_rom[] = { 00200, 07600, /* 0200, CLA CLL */ 00201, 06603, /* 0201, DMAR ; read */ 00202, 06622, /* 0202, DFSC ; done? */ 00203, 05202, /* 0203, JMP .-1 ; no */ 00204, 05600, /* 0204, JMP @.-4 ; enter boot */ 07750, 07576, /* 7750, 7576 ; word count */ 07751, 07576 /* 7751, 7576 ; address */ }; t_stat rf_boot (int32 unitno, DEVICE *dptr) { size_t i; if (rf_dib.dev != DEV_RF) /* only std devno */ return STOP_NOTSTD; if (sim_switches & SWMASK ('D')) { for (i = 0; i < DM4_LEN; i = i + 2) M[dm4_rom[i]] = dm4_rom[i + 1]; cpu_set_bootpc (DM4_START); } else { for (i = 0; i < OS8_LEN; i++) M[OS8_START + i] = os8_rom[i]; cpu_set_bootpc (OS8_START); } return SCPE_OK; } /* Attach routine */ t_stat rf_attach (UNIT *uptr, CONST char *cptr) { uint32 sz, p; uint32 ds_bytes = RF_DKSIZE * sizeof (int16); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) { p = (sz + ds_bytes - 1) / ds_bytes; if (p >= RF_NUMDK) p = RF_NUMDK - 1; uptr->flags = (uptr->flags & ~UNIT_PLAT) | (p << UNIT_V_PLAT); } uptr->capac = UNIT_GETP (uptr->flags) * RF_DKSIZE; return attach_unit (uptr, cptr); } /* Change disk size */ t_stat rf_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { if (val < 0) return SCPE_IERR; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; uptr->capac = UNIT_GETP (val) * RF_DKSIZE; uptr->flags = uptr->flags & ~UNIT_AUTO; return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 | /* pdp8_rk.c: RK8E cartridge disk simulator Copyright (c) 1993-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. rk RK8E/RK05 cartridge disk 17-Sep-13 RMS Changed to use central set_bootpc routine 18-Mar-13 RMS Raised RK_MIN so that RKLFMT will work (Mark Pizzolato) 25-Apr-03 RMS Revised for extended file support 04-Oct-02 RMS Added DIB, device number support 06-Jan-02 RMS Changed enable/disable support 30-Nov-01 RMS Added read only unit, extended SET/SHOW support 24-Nov-01 RMS Converted FLG to array, made register names consistent 25-Apr-01 RMS Added device enable/disable support 29-Jun-96 RMS Added unit enable/disable support */ #include "pdp8_defs.h" /* Constants */ #define RK_NUMSC 16 /* sectors/surface */ #define RK_NUMSF 2 /* surfaces/cylinder */ #define RK_NUMCY 203 /* cylinders/drive */ #define RK_NUMWD 256 /* words/sector */ #define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD) /* words/drive */ #define RK_NUMDR 4 /* drives/controller */ #define RK_M_NUMDR 03 /* Flags in the unit flags word */ #define UNIT_V_HWLK (UNIT_V_UF + 0) /* hwre write lock */ #define UNIT_V_SWLK (UNIT_V_UF + 1) /* swre write lock */ #define UNIT_HWLK (1 << UNIT_V_HWLK) #define UNIT_SWLK (1 << UNIT_V_SWLK) #define UNIT_WPRT (UNIT_HWLK|UNIT_SWLK|UNIT_RO) /* write protect */ /* Parameters in the unit descriptor */ #define CYL u3 /* current cylinder */ #define FUNC u4 /* function */ /* Status register */ #define RKS_DONE 04000 /* transfer done */ #define RKS_HMOV 02000 /* heads moving */ #define RKS_SKFL 00400 /* drive seek fail */ #define RKS_NRDY 00200 /* drive not ready */ #define RKS_BUSY 00100 /* control busy error */ #define RKS_TMO 00040 /* timeout error */ #define RKS_WLK 00020 /* write lock error */ #define RKS_CRC 00010 /* CRC error */ #define RKS_DLT 00004 /* data late error */ #define RKS_STAT 00002 /* drive status error */ #define RKS_CYL 00001 /* cyl address error */ #define RKS_ERR (RKS_BUSY+RKS_TMO+RKS_WLK+RKS_CRC+RKS_DLT+RKS_STAT+RKS_CYL) /* Command register */ #define RKC_M_FUNC 07 /* function */ #define RKC_READ 0 #define RKC_RALL 1 #define RKC_WLK 2 #define RKC_SEEK 3 #define RKC_WRITE 4 #define RKC_WALL 5 #define RKC_V_FUNC 9 #define RKC_IE 00400 /* interrupt enable */ #define RKC_SKDN 00200 /* set done on seek done */ #define RKC_HALF 00100 /* 128W sector */ #define RKC_MEX 00070 /* memory extension */ #define RKC_V_MEX 3 #define RKC_M_DRV 03 /* drive select */ #define RKC_V_DRV 1 #define RKC_CYHI 00001 /* high cylinder addr */ #define GET_FUNC(x) (((x) >> RKC_V_FUNC) & RKC_M_FUNC) #define GET_DRIVE(x) (((x) >> RKC_V_DRV) & RKC_M_DRV) #define GET_MEX(x) (((x) & RKC_MEX) << (12 - RKC_V_MEX)) /* Disk address */ #define RKD_V_SECT 0 /* sector */ #define RKD_M_SECT 017 #define RKD_V_SUR 4 /* surface */ #define RKD_M_SUR 01 #define RKD_V_CYL 5 /* cylinder */ #define RKD_M_CYL 0177 #define GET_CYL(x,y) ((((x) & RKC_CYHI) << (12-RKD_V_CYL)) | \ (((y) >> RKD_V_CYL) & RKD_M_CYL)) #define GET_DA(x,y) ((((x) & RKC_CYHI) << 12) | y) /* Reset commands */ #define RKX_CLS 0 /* clear status */ #define RKX_CLC 1 /* clear control */ #define RKX_CLD 2 /* clear drive */ #define RKX_CLSA 3 /* clear status alt */ #define RK_INT_UPDATE if (((rk_sta & (RKS_DONE + RKS_ERR)) != 0) && \ ((rk_cmd & RKC_IE) != 0)) \ int_req = int_req | INT_RK; \ else int_req = int_req & ~INT_RK #define RK_MIN 50 #define MAX(x,y) (((x) > (y))? (x): (y)) extern uint16 M[]; extern int32 int_req, stop_inst; extern UNIT cpu_unit; int32 rk_busy = 0; /* controller busy */ int32 rk_sta = 0; /* status register */ int32 rk_cmd = 0; /* command register */ int32 rk_da = 0; /* disk address */ int32 rk_ma = 0; /* memory address */ int32 rk_swait = 10, rk_rwait = 10; /* seek, rotate wait */ int32 rk_stopioe = 1; /* stop on error */ int32 rk (int32 IR, int32 AC); t_stat rk_svc (UNIT *uptr); t_stat rk_reset (DEVICE *dptr); t_stat rk_boot (int32 unitno, DEVICE *dptr); void rk_go (int32 function, int32 cylinder); /* RK-8E data structures rk_dev RK device descriptor rk_unit RK unit list rk_reg RK register list rk_mod RK modifiers list */ DIB rk_dib = { DEV_RK, 1, { &rk } }; UNIT rk_unit[] = { { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ UNIT_ROABLE, RK_SIZE) }, { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ UNIT_ROABLE, RK_SIZE) }, { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ UNIT_ROABLE, RK_SIZE) }, { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ UNIT_ROABLE, RK_SIZE) } }; REG rk_reg[] = { { ORDATAD (RKSTA, rk_sta, 12, "status") }, { ORDATAD (RKCMD, rk_cmd, 12, "disk command") }, { ORDATAD (RKDA, rk_da, 12, "disk address") }, { ORDATAD (RKMA, rk_ma, 12, "current memory address") }, { FLDATAD (BUSY, rk_busy, 0, "control busy flag") }, { FLDATAD (INT, int_req, INT_V_RK, "interrupt pending flag") }, { DRDATAD (STIME, rk_swait, 24, "seek time, per cylinder"), PV_LEFT }, { DRDATAD (RTIME, rk_rwait, 24, "rotational delay"), PV_LEFT }, { FLDATAD (STOP_IOE, rk_stopioe, 0, "stop on I/O error") }, { ORDATA (DEVNUM, rk_dib.dev, 6), REG_HRO }, { NULL } }; MTAB rk_mod[] = { { UNIT_HWLK, 0, "write enabled", "WRITEENABLED", NULL }, { UNIT_HWLK, UNIT_HWLK, "write locked", "LOCKED", NULL }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { 0 } }; DEVICE rk_dev = { "RK", rk_unit, rk_reg, rk_mod, RK_NUMDR, 8, 24, 1, 8, 12, NULL, NULL, &rk_reset, &rk_boot, NULL, NULL, &rk_dib, DEV_DISABLE }; /* IOT routine */ int32 rk (int32 IR, int32 AC) { int32 i; UNIT *uptr; switch (IR & 07) { /* decode IR<9:11> */ case 0: /* unused */ return (stop_inst << IOT_V_REASON) + AC; case 1: /* DSKP */ return (rk_sta & (RKS_DONE + RKS_ERR))? /* skip on done, err */ IOT_SKP + AC: AC; case 2: /* DCLR */ rk_sta = 0; /* clear status */ switch (AC & 03) { /* decode AC<10:11> */ case RKX_CLS: /* clear status */ if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; case RKX_CLSA: /* clear status alt */ break; case RKX_CLC: /* clear control */ rk_cmd = rk_busy = 0; /* clear registers */ rk_ma = rk_da = 0; for (i = 0; i < RK_NUMDR; i++) sim_cancel (&rk_unit[i]); break; case RKX_CLD: /* reset drive */ if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; else rk_go (RKC_SEEK, 0); /* seek to 0 */ break; } /* end switch AC */ break; case 3: /* DLAG */ if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; else { rk_da = AC; /* load disk addr */ rk_go (GET_FUNC (rk_cmd), GET_CYL (rk_cmd, rk_da)); } break; case 4: /* DLCA */ if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; else rk_ma = AC; /* load curr addr */ break; case 5: /* DRST */ uptr = rk_dev.units + GET_DRIVE (rk_cmd); /* selected unit */ rk_sta = rk_sta & ~(RKS_HMOV + RKS_NRDY); /* clear dynamic */ if ((uptr->flags & UNIT_ATT) == 0) rk_sta = rk_sta | RKS_NRDY; if (sim_is_active (uptr)) rk_sta = rk_sta | RKS_HMOV; return rk_sta; case 6: /* DLDC */ if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; else { rk_cmd = AC; /* load command */ rk_sta = 0; /* clear status */ } break; case 7: /* DMAN */ break; } /* end case pulse */ RK_INT_UPDATE; /* update int req */ return 0; /* clear AC */ } /* Initiate new function Called with function, cylinder, to allow recalibrate as well as load and go to be processed by this routine. Assumes that the controller is idle, and that updating of interrupt request will be done by the caller. */ void rk_go (int32 func, int32 cyl) { int32 t; UNIT *uptr; if (func == RKC_RALL) /* all? use standard */ func = RKC_READ; if (func == RKC_WALL) func = RKC_WRITE; uptr = rk_dev.units + GET_DRIVE (rk_cmd); /* selected unit */ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ rk_sta = rk_sta | RKS_DONE | RKS_NRDY | RKS_STAT; return; } if (sim_is_active (uptr) || (cyl >= RK_NUMCY)) { /* busy or bad cyl? */ rk_sta = rk_sta | RKS_DONE | RKS_STAT; return; } if ((func == RKC_WRITE) && (uptr->flags & UNIT_WPRT)) { rk_sta = rk_sta | RKS_DONE | RKS_WLK; /* write and locked? */ return; } if (func == RKC_WLK) { /* write lock? */ uptr->flags = uptr->flags | UNIT_SWLK; rk_sta = rk_sta | RKS_DONE; return; } t = abs (cyl - uptr->CYL) * rk_swait; /* seek time */ if (func == RKC_SEEK) { /* seek? */ sim_activate (uptr, MAX (RK_MIN, t)); /* schedule */ rk_sta = rk_sta | RKS_DONE; /* set done */ } else { sim_activate (uptr, t + rk_rwait); /* schedule */ rk_busy = 1; /* set busy */ } uptr->FUNC = func; /* save func */ uptr->CYL = cyl; /* put on cylinder */ return; } /* Unit service If seek, complete seek command Else complete data transfer command The unit control block contains the function and cylinder address for the current command. Note that memory addresses wrap around in the current field. */ static uint16 fill[RK_NUMWD/2] = { 0 }; t_stat rk_svc (UNIT *uptr) { int32 err, wc, wc1, awc, swc, pa, da; UNIT *seluptr; if (uptr->FUNC == RKC_SEEK) { /* seek? */ seluptr = rk_dev.units + GET_DRIVE (rk_cmd); /* see if selected */ if ((uptr == seluptr) && ((rk_cmd & RKC_SKDN) != 0)) { rk_sta = rk_sta | RKS_DONE; RK_INT_UPDATE; } return SCPE_OK; } if ((uptr->flags & UNIT_ATT) == 0) { /* not att? abort */ rk_sta = rk_sta | RKS_DONE | RKS_NRDY | RKS_STAT; rk_busy = 0; RK_INT_UPDATE; return IORETURN (rk_stopioe, SCPE_UNATT); } if ((uptr->FUNC == RKC_WRITE) && (uptr->flags & UNIT_WPRT)) { rk_sta = rk_sta | RKS_DONE | RKS_WLK; /* write and locked? */ rk_busy = 0; RK_INT_UPDATE; return SCPE_OK; } pa = GET_MEX (rk_cmd) | rk_ma; /* phys address */ da = GET_DA (rk_cmd, rk_da) * RK_NUMWD * sizeof (int16);/* disk address */ swc = wc = (rk_cmd & RKC_HALF)? RK_NUMWD / 2: RK_NUMWD; /* get transfer size */ if ((wc1 = ((rk_ma + wc) - 010000)) > 0) /* if wrap, limit */ wc = wc - wc1; err = fseek (uptr->fileref, da, SEEK_SET); /* locate sector */ if ((uptr->FUNC == RKC_READ) && (err == 0) && MEM_ADDR_OK (pa)) { /* read? */ awc = fxread (&M[pa], sizeof (int16), wc, uptr->fileref); for ( ; awc < wc; awc++) /* fill if eof */ M[pa + awc] = 0; err = ferror (uptr->fileref); if ((wc1 > 0) && (err == 0)) { /* field wraparound? */ pa = pa & 070000; /* wrap phys addr */ awc = fxread (&M[pa], sizeof (int16), wc1, uptr->fileref); for ( ; awc < wc1; awc++) /* fill if eof */ M[pa + awc] = 0; err = ferror (uptr->fileref); } } if ((uptr->FUNC == RKC_WRITE) && (err == 0)) { /* write? */ fxwrite (&M[pa], sizeof (int16), wc, uptr->fileref); err = ferror (uptr->fileref); if ((wc1 > 0) && (err == 0)) { /* field wraparound? */ pa = pa & 070000; /* wrap phys addr */ fxwrite (&M[pa], sizeof (int16), wc1, uptr->fileref); err = ferror (uptr->fileref); } if ((rk_cmd & RKC_HALF) && (err == 0)) { /* fill half sector */ fxwrite (fill, sizeof (int16), RK_NUMWD/2, uptr->fileref); err = ferror (uptr->fileref); } } rk_ma = (rk_ma + swc) & 07777; /* incr mem addr reg */ rk_sta = rk_sta | RKS_DONE; /* set done */ rk_busy = 0; RK_INT_UPDATE; if (err != 0) { sim_perror ("RK I/O error"); clearerr (uptr->fileref); return SCPE_IOERR; } return SCPE_OK; } /* Reset routine */ t_stat rk_reset (DEVICE *dptr) { int32 i; UNIT *uptr; rk_cmd = rk_ma = rk_da = rk_sta = rk_busy = 0; int_req = int_req & ~INT_RK; /* clear interrupt */ for (i = 0; i < RK_NUMDR; i++) { /* stop all units */ uptr = rk_dev.units + i; sim_cancel (uptr); uptr->flags = uptr->flags & ~UNIT_SWLK; uptr->CYL = uptr->FUNC = 0; } return SCPE_OK; } /* Bootstrap routine */ #define BOOT_START 023 #define BOOT_UNIT 032 #define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) static const uint16 boot_rom[] = { 06007, /* 23, CAF */ 06744, /* 24, DLCA ; addr = 0 */ 01032, /* 25, TAD UNIT ; unit no */ 06746, /* 26, DLDC ; command, unit */ 06743, /* 27, DLAG ; disk addr, go */ 01032, /* 30, TAD UNIT ; unit no, for OS */ 05031, /* 31, JMP . */ 00000 /* UNIT, 0 ; in bits <9:10> */ }; t_stat rk_boot (int32 unitno, DEVICE *dptr) { size_t i; if (rk_dib.dev != DEV_RK) /* only std devno */ return STOP_NOTSTD; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; M[BOOT_UNIT] = (unitno & RK_M_NUMDR) << 1; cpu_set_bootpc (BOOT_START); return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 | /* pdp8_rl.c: RL8A cartridge disk simulator Copyright (c) 1993-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. rl RL8A cartridge disk 17-Sep-13 RMS Changed to use central set_bootpc routine 25-Oct-05 RMS Fixed IOT 61 decode bug (David Gesswein) 16-Aug-05 RMS Fixed C++ declaration and cast problems 04-Jan-04 RMS Changed attach routine to use sim_fsize 25-Apr-03 RMS Revised for extended file support 04-Oct-02 RMS Added DIB, device number support 06-Jan-02 RMS Changed enable/disable support 30-Nov-01 RMS Cloned from RL11 The RL8A is a four drive cartridge disk subsystem. An RL01 drive consists of 256 cylinders, each with 2 surfaces containing 40 sectors of 256 bytes. An RL02 drive has 512 cylinders. The RL8A controller has several serious complications. - Seeking is relative to the current disk address; this requires keeping accurate track of the current cylinder. - The RL8A will not switch heads or cross cylinders during transfers. - The RL8A operates in 8b and 12b mode, like the RX8E; in 12b mode, it packs 2 12b words into 3 bytes, creating a 170 "word" sector with one wasted byte. Multi-sector transfers in 12b mode don't work. */ #include "pdp8_defs.h" /* Constants */ #define RL_NUMBY 256 /* 8b bytes/sector */ #define RL_NUMSC 40 /* sectors/surface */ #define RL_NUMSF 2 /* surfaces/cylinder */ #define RL_NUMCY 256 /* cylinders/drive */ #define RL_NUMDR 4 /* drives/controller */ #define RL_MAXFR (1 << 12) /* max transfer */ #define RL01_SIZE (RL_NUMCY*RL_NUMSF*RL_NUMSC*RL_NUMBY) /* words/drive */ #define RL02_SIZE (RL01_SIZE * 2) /* words/drive */ #define RL_BBMAP 014 /* sector for bblk map */ #define RL_BBID 0123 /* ID for bblk map */ /* Flags in the unit flags word */ #define UNIT_V_WLK (UNIT_V_UF + 0) /* write lock */ #define UNIT_V_RL02 (UNIT_V_UF + 1) /* RL01 vs RL02 */ #define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize enable */ #define UNIT_V_DUMMY (UNIT_V_UF + 3) /* dummy flag */ #define UNIT_DUMMY (1u << UNIT_V_DUMMY) #define UNIT_WLK (1u << UNIT_V_WLK) #define UNIT_RL02 (1u << UNIT_V_RL02) #define UNIT_AUTO (1u << UNIT_V_AUTO) #define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ /* Parameters in the unit descriptor */ #define TRK u3 /* current cylinder */ #define STAT u4 /* status */ /* RLDS, NI = not implemented, * = kept in STAT, ^ = kept in TRK */ #define RLDS_LOAD 0 /* no cartridge */ #define RLDS_LOCK 5 /* lock on */ #define RLDS_BHO 0000010 /* brushes home NI */ #define RLDS_HDO 0000020 /* heads out NI */ #define RLDS_CVO 0000040 /* cover open NI */ #define RLDS_HD 0000100 /* head select ^ */ #define RLDS_RL02 0000200 /* RL02 */ #define RLDS_DSE 0000400 /* drv sel err NI */ #define RLDS_VCK 0001000 /* vol check * */ #define RLDS_WGE 0002000 /* wr gate err * */ #define RLDS_SPE 0004000 /* spin err * */ #define RLDS_STO 0010000 /* seek time out NI */ #define RLDS_WLK 0020000 /* wr locked */ #define RLDS_HCE 0040000 /* hd curr err NI */ #define RLDS_WDE 0100000 /* wr data err NI */ #define RLDS_ATT (RLDS_HDO+RLDS_BHO+RLDS_LOCK) /* att status */ #define RLDS_UNATT (RLDS_CVO+RLDS_LOAD) /* unatt status */ #define RLDS_ERR (RLDS_WDE+RLDS_HCE+RLDS_STO+RLDS_SPE+RLDS_WGE+ \ RLDS_VCK+RLDS_DSE) /* errors bits */ /* RLCSA, seek = offset/rw = address (also uptr->TRK) */ #define RLCSA_DIR 04000 /* direction */ #define RLCSA_HD 02000 /* head select */ #define RLCSA_CYL 00777 /* cyl offset */ #define GET_CYL(x) ((x) & RLCSA_CYL) #define GET_TRK(x) ((((x) & RLCSA_CYL) * RL_NUMSF) + \ (((x) & RLCSA_HD)? 1: 0)) #define GET_DA(x) ((GET_TRK(x) * RL_NUMSC) + rlsa) /* RLCSB, function/unit select */ #define RLCSB_V_FUNC 0 /* function */ #define RLCSB_M_FUNC 07 #define RLCSB_MNT 0 #define RLCSB_CLRD 1 #define RLCSB_GSTA 2 #define RLCSB_SEEK 3 #define RLCSB_RHDR 4 #define RLCSB_WRITE 5 #define RLCSB_READ 6 #define RLCSB_RNOHDR 7 #define RLCSB_V_MEX 3 /* memory extension */ #define RLCSB_M_MEX 07 #define RLCSB_V_DRIVE 6 /* drive */ #define RLCSB_M_DRIVE 03 #define RLCSB_V_IE 8 /* int enable */ #define RLCSB_IE (1u << RLCSB_V_IE) #define RLCSB_8B 01000 /* 12b/8b */ #define RCLS_MNT 02000 /* maint NI */ #define RLCSB_RW 0001777 /* read/write */ #define GET_FUNC(x) (((x) >> RLCSB_V_FUNC) & RLCSB_M_FUNC) #define GET_MEX(x) (((x) >> RLCSB_V_MEX) & RLCSB_M_MEX) #define GET_DRIVE(x) (((x) >> RLCSB_V_DRIVE) & RLCSB_M_DRIVE) /* RLSA, disk sector */ #define RLSA_V_SECT 6 /* sector */ #define RLSA_M_SECT 077 #define GET_SECT(x) (((x) >> RLSA_V_SECT) & RLSA_M_SECT) /* RLER, error register */ #define RLER_DRDY 00001 /* drive ready */ #define RLER_DRE 00002 /* drive error */ #define RLER_HDE 01000 /* header error */ #define RLER_INCMP 02000 /* incomplete */ #define RLER_ICRC 04000 /* CRC error */ #define RLER_MASK 07003 /* RLSI, silo register, used only in read header */ #define RLSI_V_TRK 6 /* track */ extern uint16 M[]; extern int32 int_req; extern UNIT cpu_unit; uint8 *rlxb = NULL; /* xfer buffer */ int32 rlcsa = 0; /* control/status A */ int32 rlcsb = 0; /* control/status B */ int32 rlma = 0; /* memory address */ int32 rlwc = 0; /* word count */ int32 rlsa = 0; /* sector address */ int32 rler = 0; /* error register */ int32 rlsi = 0, rlsi1 = 0, rlsi2 = 0; /* silo queue */ int32 rl_lft = 0; /* silo left/right */ int32 rl_done = 0; /* done flag */ int32 rl_erf = 0; /* error flag */ int32 rl_swait = 10; /* seek wait */ int32 rl_rwait = 10; /* rotate wait */ int32 rl_stopioe = 1; /* stop on error */ int32 rl60 (int32 IR, int32 AC); int32 rl61 (int32 IR, int32 AC); t_stat rl_svc (UNIT *uptr); t_stat rl_reset (DEVICE *dptr); void rl_set_done (int32 error); t_stat rl_boot (int32 unitno, DEVICE *dptr); t_stat rl_attach (UNIT *uptr, CONST char *cptr); t_stat rl_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat rl_set_bad (UNIT *uptr, int32 val, CONST char *cptr, void *desc); /* RL8A data structures rl_dev RL device descriptor rl_unit RL unit list rl_reg RL register list rl_mod RL modifier list */ DIB rl_dib = { DEV_RL, 2, { &rl60, &rl61 } }; UNIT rl_unit[] = { { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ UNIT_ROABLE, RL01_SIZE) }, { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ UNIT_ROABLE, RL01_SIZE) }, { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ UNIT_ROABLE, RL01_SIZE) }, { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ UNIT_ROABLE, RL01_SIZE) } }; REG rl_reg[] = { { ORDATAD (RLCSA, rlcsa, 12, "control/status A") }, { ORDATAD (RLCSB, rlcsb, 12, "control/status B") }, { ORDATAD (RLMA, rlma, 12, "memory address") }, { ORDATAD (RLWC, rlwc, 12, "word count") }, { ORDATAD (RLSA, rlsa, 6, "sector address") }, { ORDATAD (RLER, rler, 12, "error flags") }, { ORDATAD (RLSI, rlsi, 16, "silo top word") }, { ORDATAD (RLSI1, rlsi1, 16, "silo second word") }, { ORDATAD (RLSI2, rlsi2, 16, "silo third word") }, { FLDATAD (RLSIL, rl_lft, 0, "silo read left/right flag") }, { FLDATAD (INT, int_req, INT_V_RL, "interrupt request") }, { FLDATAD (DONE, rl_done, INT_V_RL, "done flag") }, { FLDATA (IE, rlcsb, RLCSB_V_IE) }, { FLDATAD (ERR, rl_erf, 0, "composite error flag") }, { DRDATAD (STIME, rl_swait, 24, "seek time, per cylinder"), PV_LEFT }, { DRDATAD (RTIME, rl_rwait, 24, "rotational delay"), PV_LEFT }, { URDATA (CAPAC, rl_unit[0].capac, 10, T_ADDR_W, 0, RL_NUMDR, PV_LEFT + REG_HRO) }, { FLDATAD (STOP_IOE, rl_stopioe, 0, "stop on I/O error") }, { ORDATA (DEVNUM, rl_dib.dev, 6), REG_HRO }, { NULL } }; MTAB rl_mod[] = { { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, { UNIT_DUMMY, 0, NULL, "BADBLOCK", &rl_set_bad }, { (UNIT_RL02+UNIT_ATT), UNIT_ATT, "RL01", NULL, NULL }, { (UNIT_RL02+UNIT_ATT), (UNIT_RL02+UNIT_ATT), "RL02", NULL, NULL }, { (UNIT_AUTO+UNIT_RL02+UNIT_ATT), 0, "RL01", NULL, NULL }, { (UNIT_AUTO+UNIT_RL02+UNIT_ATT), UNIT_RL02, "RL02", NULL, NULL }, { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, { (UNIT_AUTO+UNIT_RL02), 0, NULL, "RL01", &rl_set_size }, { (UNIT_AUTO+UNIT_RL02), UNIT_RL02, NULL, "RL02", &rl_set_size }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { 0 } }; DEVICE rl_dev = { "RL", rl_unit, rl_reg, rl_mod, RL_NUMDR, 8, 24, 1, 8, 8, NULL, NULL, &rl_reset, &rl_boot, &rl_attach, NULL, &rl_dib, DEV_DISABLE | DEV_DIS }; /* IOT routines */ int32 rl60 (int32 IR, int32 AC) { int32 curr, offs, newc, maxc; UNIT *uptr; switch (IR & 07) { /* case IR<9:11> */ case 0: /* RLDC */ rl_reset (&rl_dev); /* reset device */ break; case 1: /* RLSD */ if (rl_done) /* skip if done */ AC = IOT_SKP; else AC = 0; rl_done = 0; /* clear done */ int_req = int_req & ~INT_RL; /* clear intr */ return AC; case 2: /* RLMA */ rlma = AC; break; case 3: /* RLCA */ rlcsa = AC; break; case 4: /* RLCB */ rlcsb = AC; rl_done = 0; /* clear done */ rler = rl_erf = 0; /* clear errors */ int_req = int_req & ~INT_RL; /* clear intr */ rl_lft = 0; /* clear silo ptr */ uptr = rl_dev.units + GET_DRIVE (rlcsb); /* select unit */ switch (GET_FUNC (rlcsb)) { /* case on func */ case RLCSB_CLRD: /* clear drive */ uptr->STAT = uptr->STAT & ~RLDS_ERR; /* clear errors */ case RLCSB_MNT: /* mnt */ rl_set_done (0); break; case RLCSB_SEEK: /* seek */ curr = GET_CYL (uptr->TRK); /* current cylinder */ offs = GET_CYL (rlcsa); /* offset */ if (rlcsa & RLCSA_DIR) { /* in or out? */ newc = curr + offs; /* out */ maxc = (uptr->flags & UNIT_RL02)? RL_NUMCY * 2: RL_NUMCY; if (newc >= maxc) newc = maxc - 1; } else { newc = curr - offs; /* in */ if (newc < 0) newc = 0; } uptr->TRK = newc | (rlcsa & RLCSA_HD); sim_activate (uptr, rl_swait * abs (newc - curr)); break; default: /* data transfer */ sim_activate (uptr, rl_swait); /* activate unit */ break; } /* end switch func */ break; case 5: /* RLSA */ rlsa = GET_SECT (AC); break; case 6: /* spare */ return 0; case 7: /* RLWC */ rlwc = AC; break; } /* end switch pulse */ return 0; /* clear AC */ } int32 rl61 (int32 IR, int32 AC) { int32 dat; UNIT *uptr; switch (IR & 07) { /* case IR<9:11> */ case 0: /* RRER */ uptr = rl_dev.units + GET_DRIVE (rlcsb); /* select unit */ if (!sim_is_active (uptr) && /* update drdy */ (uptr->flags & UNIT_ATT)) rler = rler | RLER_DRDY; else rler = rler & ~RLER_DRDY; dat = rler & RLER_MASK; break; case 1: /* RRWC */ dat = rlwc; break; case 2: /* RRCA */ dat = rlcsa; break; case 3: /* RRCB */ dat = rlcsb; break; case 4: /* RRSA */ dat = (rlsa << RLSA_V_SECT) & 07777; break; case 5: /* RRSI */ if (rl_lft) { /* silo left? */ dat = (rlsi >> 8) & 0377; /* get left 8b */ rlsi = rlsi1; /* ripple */ rlsi1 = rlsi2; } else dat = rlsi & 0377; /* get right 8b */ rl_lft = rl_lft ^ 1; /* change side */ break; case 6: /* spare */ return AC; case 7: /* RLSE */ if (rl_erf) /* skip if err */ dat = IOT_SKP | AC; else dat = AC; rl_erf = 0; break; } /* end switch pulse */ return dat; } /* Service unit timeout If seek in progress, complete seek command Else complete data transfer command The unit control block contains the function and cylinder for the current command. */ t_stat rl_svc (UNIT *uptr) { int32 err, wc, maxc; int32 i, j, func, da, bc, wbc; uint32 ma; func = GET_FUNC (rlcsb); /* get function */ if (func == RLCSB_GSTA) { /* get status? */ rlsi = uptr->STAT | ((uptr->TRK & RLCSA_HD)? RLDS_HD: 0) | ((uptr->flags & UNIT_ATT)? RLDS_ATT: RLDS_UNATT); if (uptr->flags & UNIT_RL02) rlsi = rlsi | RLDS_RL02; if (uptr->flags & UNIT_WPRT) rlsi = rlsi | RLDS_WLK; rlsi2 = rlsi1 = rlsi; rl_set_done (0); /* done */ return SCPE_OK; } if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ uptr->STAT = uptr->STAT | RLDS_SPE; /* spin error */ rl_set_done (RLER_INCMP); /* flag error */ return IORETURN (rl_stopioe, SCPE_UNATT); } if ((func == RLCSB_WRITE) && (uptr->flags & UNIT_WPRT)) { uptr->STAT = uptr->STAT | RLDS_WGE; /* write and locked */ rl_set_done (RLER_DRE); /* flag error */ return SCPE_OK; } if (func == RLCSB_SEEK) { /* seek? */ rl_set_done (0); /* done */ return SCPE_OK; } if (func == RLCSB_RHDR) { /* read header? */ rlsi = (GET_TRK (uptr->TRK) << RLSI_V_TRK) | rlsa; rlsi1 = rlsi2 = 0; rl_set_done (0); /* done */ return SCPE_OK; } if (((func != RLCSB_RNOHDR) && (GET_CYL (uptr->TRK) != GET_CYL (rlcsa))) || (rlsa >= RL_NUMSC)) { /* bad cyl or sector? */ rl_set_done (RLER_HDE | RLER_INCMP); /* flag error */ return SCPE_OK; } ma = (GET_MEX (rlcsb) << 12) | rlma; /* get mem addr */ da = GET_DA (rlcsa) * RL_NUMBY; /* get disk addr */ wc = 010000 - rlwc; /* get true wc */ if (rlcsb & RLCSB_8B) { /* 8b mode? */ bc = wc; /* bytes to xfr */ maxc = (RL_NUMSC - rlsa) * RL_NUMBY; /* max transfer */ if (bc > maxc) /* trk ovrun? limit */ wc = bc = maxc; } else { bc = ((wc * 3) + 1) / 2; /* 12b mode */ if (bc > RL_NUMBY) { /* > 1 sector */ bc = RL_NUMBY; /* cap xfer */ wc = (RL_NUMBY * 2) / 3; } } err = fseek (uptr->fileref, da, SEEK_SET); if ((func >= RLCSB_READ) && (err == 0) && /* read (no hdr)? */ MEM_ADDR_OK (ma)) { /* valid bank? */ i = fxread (rlxb, sizeof (int8), bc, uptr->fileref); err = ferror (uptr->fileref); for ( ; i < bc; i++) /* fill buffer */ rlxb[i] = 0; for (i = j = 0; i < wc; i++) { /* store buffer */ if (rlcsb & RLCSB_8B) /* 8b mode? */ M[ma] = rlxb[i] & 0377; /* store */ else if (i & 1) { /* odd wd 12b? */ M[ma] = ((rlxb[j + 1] >> 4) & 017) | (((uint16) rlxb[j + 2]) << 4); j = j + 3; } else M[ma] = rlxb[j] | /* even wd 12b */ ((((uint16) rlxb[j + 1]) & 017) << 8); ma = (ma & 070000) + ((ma + 1) & 07777); } /* end for */ } /* end if wr */ if ((func == RLCSB_WRITE) && (err == 0)) { /* write? */ for (i = j = 0; i < wc; i++) { /* fetch buffer */ if (rlcsb & RLCSB_8B) /* 8b mode? */ rlxb[i] = M[ma] & 0377; /* fetch */ else if (i & 1) { /* odd wd 12b? */ rlxb[j + 1] = rlxb[j + 1] | ((M[ma] & 017) << 4); rlxb[j + 2] = ((M[ma] >> 4) & 0377); j = j + 3; } else { /* even wd 12b */ rlxb[j] = M[ma] & 0377; rlxb[j + 1] = (M[ma] >> 8) & 017; } ma = (ma & 070000) + ((ma + 1) & 07777); } /* end for */ wbc = (bc + (RL_NUMBY - 1)) & ~(RL_NUMBY - 1); /* clr to */ for (i = bc; i < wbc; i++) /* end of blk */ rlxb[i] = 0; fxwrite (rlxb, sizeof (int8), wbc, uptr->fileref); err = ferror (uptr->fileref); } /* end write */ rlwc = (rlwc + wc) & 07777; /* final word count */ if (rlwc != 0) /* completed? */ rler = rler | RLER_INCMP; rlma = (rlma + wc) & 07777; /* final word addr */ rlsa = rlsa + ((bc + (RL_NUMBY - 1)) / RL_NUMBY); rl_set_done (0); if (err != 0) { /* error? */ sim_perror ("RL I/O error"); clearerr (uptr->fileref); return SCPE_IOERR; } return SCPE_OK; } /* Set done and possibly errors */ void rl_set_done (int32 status) { rl_done = 1; rler = rler | status; if (rler) rl_erf = 1; if (rlcsb & RLCSB_IE) int_req = int_req | INT_RL; else int_req = int_req & ~INT_RL; return; } /* Device reset Note that the RL8A does NOT recalibrate its drives on RESET */ t_stat rl_reset (DEVICE *dptr) { int32 i; UNIT *uptr; rlcsa = rlcsb = rlsa = rler = 0; rlma = rlwc = 0; rlsi = rlsi1 = rlsi2 = 0; rl_lft = 0; rl_done = 0; rl_erf = 0; int_req = int_req & ~INT_RL; for (i = 0; i < RL_NUMDR; i++) { uptr = rl_dev.units + i; sim_cancel (uptr); uptr->STAT = 0; } if (rlxb == NULL) rlxb = (uint8 *) calloc (RL_MAXFR, sizeof (uint8)); if (rlxb == NULL) return SCPE_MEM; return SCPE_OK; } /* Attach routine */ t_stat rl_attach (UNIT *uptr, CONST char *cptr) { uint32 p; t_stat r; uptr->capac = (uptr->flags & UNIT_RL02)? RL02_SIZE: RL01_SIZE; r = attach_unit (uptr, cptr); /* attach unit */ if (r != SCPE_OK) /* error? */ return r; uptr->TRK = 0; /* cyl 0 */ uptr->STAT = RLDS_VCK; /* new volume */ if ((p = sim_fsize (uptr->fileref)) == 0) { /* new disk image? */ if (uptr->flags & UNIT_RO) return SCPE_OK; return rl_set_bad (uptr, 0, NULL, NULL); } if ((uptr->flags & UNIT_AUTO) == 0) /* autosize? */ return r; if (p > (RL01_SIZE * sizeof (int16))) { uptr->flags = uptr->flags | UNIT_RL02; uptr->capac = RL02_SIZE; } else { uptr->flags = uptr->flags & ~UNIT_RL02; uptr->capac = RL01_SIZE; } return SCPE_OK; } /* Set size routine */ t_stat rl_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { if (uptr->flags & UNIT_ATT) return SCPE_ALATT; uptr->capac = (val & UNIT_RL02)? RL02_SIZE: RL01_SIZE; return SCPE_OK; } /* Factory bad block table creation routine This routine writes the OS/8 specific bad block map in track 0, sector 014 (RL_BBMAP): words 0 magic number = 0123 (RL_BBID) words 1-n block numbers : words n+1 end of table = 0 Inputs: uptr = pointer to unit val = ignored Outputs: sta = status code */ t_stat rl_set_bad (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int32 i, da = RL_BBMAP * RL_NUMBY; if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; if (uptr->flags & UNIT_RO) return SCPE_RO; if (!get_yn ("Create bad block table? [N]", FALSE)) return SCPE_OK; if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR; rlxb[0] = RL_BBID; for (i = 1; i < RL_NUMBY; i++) rlxb[i] = 0; fxwrite (rlxb, sizeof (uint8), RL_NUMBY, uptr->fileref); if (ferror (uptr->fileref)) return SCPE_IOERR; return SCPE_OK; } /* Bootstrap */ #define BOOT_START 1 /* start */ #define BOOT_UNIT 02006 /* unit number */ #define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) static const uint16 boot_rom[] = { 06600, /* BT, RLDC ; reset */ 07201, /* 02, CLA IAC ; clr drv = 1 */ 04027, /* 03, JMS GO ; do io */ 01004, /* 04, TAD 4 ; rd hdr fnc */ 04027, /* 05, JMS GO ; do io */ 06615, /* 06, RRSI ; rd hdr lo */ 07002, /* 07, BSW ; swap */ 07012, /* 10, RTR ; lo cyl to L */ 06615, /* 11, RRSI ; rd hdr hi */ 00025, /* 12, AND 25 ; mask = 377 */ 07004, /* 13, RTL ; get cyl */ 06603, /* 14, RLCA ; set addr */ 07325, /* 15, CLA STL IAC RAL ; seek = 3 */ 04027, /* 16, JMS GO ; do io */ 07332, /* 17, CLA STL RTR ; dir in = 2000 */ 06605, /* 20, RLSA ; sector */ 01026, /* 21, TAD (-200) ; one sector */ 06607, /* 22, RLWC ; word cnt */ 07327, /* 23, CLA STL IAC RTL ; read = 6*/ 04027, /* 24, JMS GO ; do io */ 00377, /* 25, JMP 377 ; start */ 07600, /* 26, -200 ; word cnt */ 00000, /* GO, 0 ; subr */ 06604, /* 30, RLCB ; load fnc */ 06601, /* 31, RLSD ; wait */ 05031, /* 32, JMP .-1 ; */ 06617, /* 33, RLSE ; error? */ 05427, /* 34, JMP I GO ; no, ok */ 05001 /* 35, JMP BT ; restart */ }; t_stat rl_boot (int32 unitno, DEVICE *dptr) { size_t i; if (unitno) /* only unit 0 */ return SCPE_ARG; if (rl_dib.dev != DEV_RL) /* only std devno */ return STOP_NOTSTD; rl_unit[unitno].TRK = 0; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; cpu_set_bootpc (BOOT_START); return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 | /* pdp8_rx.c: RX8E/RX01, RX28/RX02 floppy disk simulator Copyright (c) 1993-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. rx RX8E/RX01, RX28/RX02 floppy disk 17-Sep-13 RMS Changed to use central set_bootpc routine 03-Sep-13 RMS Added explicit void * cast 15-May-06 RMS Fixed bug in autosize attach (Dave Gesswein) 04-Jan-04 RMS Changed sim_fsize calling sequence 05-Nov-03 RMS Fixed bug in RX28 read status (Charles Dickman) 26-Oct-03 RMS Cleaned up buffer copy code, fixed double density write 25-Apr-03 RMS Revised for extended file support 14-Mar-03 RMS Fixed variable size interaction with save/restore 03-Mar-03 RMS Fixed autosizing 08-Oct-02 RMS Added DIB, device number support Fixed reset to work with disabled device 15-Sep-02 RMS Added RX28/RX02 support 06-Jan-02 RMS Changed enable/disable support 30-Nov-01 RMS Added read only unit, extended SET/SHOW support 24-Nov-01 RMS Converted FLG to array 17-Jul-01 RMS Fixed warning from VC++ 6 26-Apr-01 RMS Added device enable/disable support 13-Apr-01 RMS Revised for register arrays 14-Apr-99 RMS Changed t_addr to unsigned 15-Aug-96 RMS Fixed bug in LCD An RX01 diskette consists of 77 tracks, each with 26 sectors of 128B. An RX02 diskette consists of 77 tracks, each with 26 sectors of 128B (single density) or 256B (double density). Tracks are numbered 0-76, sectors 1-26. The RX8E (RX28) can store data in 8b mode or 12b mode. In 8b mode, the controller reads or writes 128 bytes (128B or 256B) per sector. In 12b mode, it reads or writes 64 (64 or 128) 12b words per sector. The 12b words are bit packed into the first 96 (192) bytes of the sector; the last 32 (64) bytes are zeroed on writes. */ #include "pdp8_defs.h" #define RX_NUMTR 77 /* tracks/disk */ #define RX_M_TRACK 0377 #define RX_NUMSC 26 /* sectors/track */ #define RX_M_SECTOR 0177 /* cf Jones!! */ #define RX_NUMBY 128 /* bytes/sector */ #define RX2_NUMBY 256 #define RX_NUMWD (RX_NUMBY / 2) /* words/sector */ #define RX2_NUMWD (RX2_NUMBY / 2) #define RX_SIZE (RX_NUMTR * RX_NUMSC * RX_NUMBY) /* bytes/disk */ #define RX2_SIZE (RX_NUMTR * RX_NUMSC * RX2_NUMBY) #define RX_NUMDR 2 /* drives/controller */ #define RX_M_NUMDR 01 #define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ #define UNIT_V_DEN (UNIT_V_UF + 1) /* double density */ #define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */ #define UNIT_WLK (1u << UNIT_V_WLK) #define UNIT_DEN (1u << UNIT_V_DEN) #define UNIT_AUTO (1u << UNIT_V_AUTO) #define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ #define IDLE 0 /* idle state */ #define CMD8 1 /* 8b cmd, ho next */ #define RWDS 2 /* rw, sect next */ #define RWDT 3 /* rw, track next */ #define RWXFR 4 /* rw, transfer */ #define FILL 5 /* fill buffer */ #define EMPTY 6 /* empty buffer */ #define SDCNF 7 /* set dens, conf next */ #define SDXFR 8 /* set dens, transfer */ #define CMD_COMPLETE 9 /* set done next */ #define INIT_COMPLETE 10 /* init compl next */ #define RXCS_V_FUNC 1 /* function */ #define RXCS_M_FUNC 7 #define RXCS_FILL 0 /* fill buffer */ #define RXCS_EMPTY 1 /* empty buffer */ #define RXCS_WRITE 2 /* write sector */ #define RXCS_READ 3 /* read sector */ #define RXCS_SDEN 4 /* set density (RX28) */ #define RXCS_RXES 5 /* read status */ #define RXCS_WRDEL 6 /* write del data */ #define RXCS_ECODE 7 /* read error code */ #define RXCS_DRV 0020 /* drive */ #define RXCS_MODE 0100 /* mode */ #define RXCS_MAINT 0200 /* maintenance */ #define RXCS_DEN 0400 /* density (RX28) */ #define RXCS_GETFNC(x) (((x) >> RXCS_V_FUNC) & RXCS_M_FUNC) #define RXES_CRC 0001 /* CRC error NI */ #define RXES_ID 0004 /* init done */ #define RXES_RX02 0010 /* RX02 (RX28) */ #define RXES_DERR 0020 /* density err (RX28) */ #define RXES_DEN 0040 /* density (RX28) */ #define RXES_DD 0100 /* deleted data */ #define RXES_DRDY 0200 /* drive ready */ #define TRACK u3 /* current track */ #define READ_RXDBR ((rx_csr & RXCS_MODE)? AC | (rx_dbr & 0377): rx_dbr) #define CALC_DA(t,s,b) (((t) * RX_NUMSC) + ((s) - 1)) * b extern int32 int_req, int_enable, dev_done; int32 rx_28 = 0; /* controller type */ int32 rx_tr = 0; /* xfer ready flag */ int32 rx_err = 0; /* error flag */ int32 rx_csr = 0; /* control/status */ int32 rx_dbr = 0; /* data buffer */ int32 rx_esr = 0; /* error status */ int32 rx_ecode = 0; /* error code */ int32 rx_track = 0; /* desired track */ int32 rx_sector = 0; /* desired sector */ int32 rx_state = IDLE; /* controller state */ int32 rx_cwait = 100; /* command time */ int32 rx_swait = 10; /* seek, per track */ int32 rx_xwait = 1; /* tr set time */ int32 rx_stopioe = 0; /* stop on error */ uint8 rx_buf[RX2_NUMBY] = { 0 }; /* sector buffer */ int32 rx_bptr = 0; /* buffer pointer */ int32 rx (int32 IR, int32 AC); t_stat rx_svc (UNIT *uptr); t_stat rx_reset (DEVICE *dptr); t_stat rx_boot (int32 unitno, DEVICE *dptr); t_stat rx_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat rx_attach (UNIT *uptr, CONST char *cptr); void rx_cmd (void); void rx_done (int32 esr_flags, int32 new_ecode); t_stat rx_settype (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat rx_showtype (FILE *st, UNIT *uptr, int32 val, CONST void *desc); /* RX8E data structures rx_dev RX device descriptor rx_unit RX unit list rx_reg RX register list rx_mod RX modifier list */ DIB rx_dib = { DEV_RX, 1, { &rx } }; UNIT rx_unit[] = { { UDATA (&rx_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF+ UNIT_ROABLE, RX_SIZE) }, { UDATA (&rx_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF+ UNIT_ROABLE, RX_SIZE) } }; REG rx_reg[] = { { ORDATAD (RXCS, rx_csr, 12, "status") }, { ORDATAD (RXDB, rx_dbr, 12, "data buffer") }, { ORDATAD (RXES, rx_esr, 12, "error status") }, { ORDATA (RXERR, rx_ecode, 8) }, { ORDATAD (RXTA, rx_track, 8, "current track") }, { ORDATAD (RXSA, rx_sector, 8, "current sector") }, { DRDATAD (STAPTR, rx_state, 4, "controller state"), REG_RO }, { DRDATAD (BUFPTR, rx_bptr, 8, "buffer pointer") }, { FLDATAD (TR, rx_tr, 0, "transfer ready flag") }, { FLDATAD (ERR, rx_err, 0, "error flag") }, { FLDATAD (DONE, dev_done, INT_V_RX, "done flag") }, { FLDATAD (ENABLE, int_enable, INT_V_RX, "interrupt enable flag") }, { FLDATAD (INT, int_req, INT_V_RX, "interrupt pending flag") }, { DRDATAD (CTIME, rx_cwait, 24, "command completion time"), PV_LEFT }, { DRDATAD (STIME, rx_swait, 24, "seek time per track"), PV_LEFT }, { DRDATAD (XTIME, rx_xwait, 24, "transfer ready delay"), PV_LEFT }, { FLDATAD (STOP_IOE, rx_stopioe, 0, "stop on I/O error") }, { BRDATAD (SBUF, rx_buf, 8, 8, RX2_NUMBY, "sector buffer array") }, { FLDATA (RX28, rx_28, 0), REG_HRO }, { URDATA (CAPAC, rx_unit[0].capac, 10, T_ADDR_W, 0, RX_NUMDR, REG_HRO | PV_LEFT) }, { ORDATA (DEVNUM, rx_dib.dev, 6), REG_HRO }, { NULL } }; MTAB rx_mod[] = { { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, { MTAB_XTD | MTAB_VDV, 1, NULL, "RX28", &rx_settype, NULL, NULL }, { MTAB_XTD | MTAB_VDV, 0, NULL, "RX8E", &rx_settype, NULL, NULL }, { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, NULL, &rx_showtype, NULL }, { (UNIT_DEN+UNIT_ATT), UNIT_ATT, "single density", NULL, NULL }, { (UNIT_DEN+UNIT_ATT), (UNIT_DEN+UNIT_ATT), "double density", NULL, NULL }, { (UNIT_AUTO+UNIT_DEN+UNIT_ATT), 0, "single density", NULL, NULL }, { (UNIT_AUTO+UNIT_DEN+UNIT_ATT), UNIT_DEN, "double density", NULL, NULL }, { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, { (UNIT_AUTO+UNIT_DEN), 0, NULL, "SINGLE", &rx_set_size }, { (UNIT_AUTO+UNIT_DEN), UNIT_DEN, NULL, "DOUBLE", &rx_set_size }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { 0 } }; DEVICE rx_dev = { "RX", rx_unit, rx_reg, rx_mod, RX_NUMDR, 8, 20, 1, 8, 8, NULL, NULL, &rx_reset, &rx_boot, &rx_attach, NULL, &rx_dib, DEV_DISABLE }; /* IOT routine */ int32 rx (int32 IR, int32 AC) { int32 drv = ((rx_csr & RXCS_DRV)? 1: 0); /* get drive number */ switch (IR & 07) { /* decode IR<9:11> */ case 0: /* unused */ break; case 1: /* LCD */ if (rx_state != IDLE) /* ignore if busy */ return AC; dev_done = dev_done & ~INT_RX; /* clear done, int */ int_req = int_req & ~INT_RX; rx_tr = rx_err = 0; /* clear flags */ rx_bptr = 0; /* clear buf pointer */ if (rx_28 && (AC & RXCS_MODE)) { /* RX28 8b mode? */ rx_dbr = rx_csr = AC & 0377; /* save 8b */ rx_tr = 1; /* xfer is ready */ rx_state = CMD8; /* wait for part 2 */ } else { rx_dbr = rx_csr = AC; /* save new command */ rx_cmd (); /* issue command */ } return 0; /* clear AC */ case 2: /* XDR */ switch (rx_state & 017) { /* case on state */ case EMPTY: /* emptying buffer */ sim_activate (&rx_unit[drv], rx_xwait); /* sched xfer */ return READ_RXDBR; /* return data reg */ case CMD8: /* waiting for cmd */ rx_dbr = AC & 0377; rx_csr = (rx_csr & 0377) | ((AC & 017) << 8); rx_cmd (); break; case RWDS:case RWDT:case FILL:case SDCNF: /* waiting for data */ rx_dbr = AC; /* save data */ sim_activate (&rx_unit[drv], rx_xwait); /* schedule */ break; default: /* default */ return READ_RXDBR; /* return data reg */ } break; case 3: /* STR */ if (rx_tr != 0) { rx_tr = 0; return IOT_SKP + AC; } break; case 4: /* SER */ if (rx_err != 0) { rx_err = 0; return IOT_SKP + AC; } break; case 5: /* SDN */ if ((dev_done & INT_RX) != 0) { dev_done = dev_done & ~INT_RX; int_req = int_req & ~INT_RX; return IOT_SKP + AC; } break; case 6: /* INTR */ if (AC & 1) int_enable = int_enable | INT_RX; else int_enable = int_enable & ~INT_RX; int_req = INT_UPDATE; break; case 7: /* INIT */ rx_reset (&rx_dev); /* reset device */ break; } /* end case pulse */ return AC; } void rx_cmd (void) { int32 drv = ((rx_csr & RXCS_DRV)? 1: 0); /* get drive number */ switch (RXCS_GETFNC (rx_csr)) { /* decode command */ case RXCS_FILL: rx_state = FILL; /* state = fill */ rx_tr = 1; /* xfer is ready */ rx_esr = rx_esr & RXES_ID; /* clear errors */ break; case RXCS_EMPTY: rx_state = EMPTY; /* state = empty */ rx_esr = rx_esr & RXES_ID; /* clear errors */ sim_activate (&rx_unit[drv], rx_xwait); /* sched xfer */ break; case RXCS_READ: case RXCS_WRITE: case RXCS_WRDEL: rx_state = RWDS; /* state = get sector */ rx_tr = 1; /* xfer is ready */ rx_esr = rx_esr & RXES_ID; /* clear errors */ break; case RXCS_SDEN: if (rx_28) { /* RX28? */ rx_state = SDCNF; /* state = get conf */ rx_tr = 1; /* xfer is ready */ rx_esr = rx_esr & RXES_ID; /* clear errors */ break; } /* else fall thru */ default: rx_state = CMD_COMPLETE; /* state = cmd compl */ sim_activate (&rx_unit[drv], rx_cwait); /* sched done */ break; } /* end switch func */ return; } /* Unit service; the action to be taken depends on the transfer state: IDLE Should never get here RWDS Save sector, set TR, set RWDT RWDT Save track, set RWXFR RWXFR Read/write buffer FILL copy dbr to rx_buf[rx_bptr], advance ptr if rx_bptr > max, finish command, else set tr EMPTY if rx_bptr > max, finish command, else copy rx_buf[rx_bptr] to dbr, advance ptr, set tr CMD_COMPLETE copy requested data to dbr, finish command INIT_COMPLETE read drive 0, track 1, sector 1 to buffer, finish command For RWDT and CMD_COMPLETE, the input argument is the selected drive; otherwise, it is drive 0. */ t_stat rx_svc (UNIT *uptr) { int32 i, func, byptr, bps, wps; int8 *fbuf = (int8 *) uptr->filebuf; uint32 da; #define PTR12(x) (((x) + (x) + (x)) >> 1) if (rx_28 && (uptr->flags & UNIT_DEN)) /* RX28 and double density? */ bps = RX2_NUMBY; /* double bytes/sector */ else bps = RX_NUMBY; /* RX8E, normal count */ wps = bps / 2; func = RXCS_GETFNC (rx_csr); /* get function */ switch (rx_state) { /* case on state */ case IDLE: /* idle */ return SCPE_IERR; case EMPTY: /* empty buffer */ if (rx_csr & RXCS_MODE) { /* 8b xfer? */ if (rx_bptr >= bps) { /* done? */ rx_done (0, 0); /* set done */ break; /* and exit */ } rx_dbr = rx_buf[rx_bptr]; /* else get data */ } else { byptr = PTR12 (rx_bptr); /* 12b xfer */ if (rx_bptr >= wps) { /* done? */ rx_done (0, 0); /* set done */ break; /* and exit */ } rx_dbr = (rx_bptr & 1)? /* get data */ ((rx_buf[byptr] & 017) << 8) | rx_buf[byptr + 1]: (rx_buf[byptr] << 4) | ((rx_buf[byptr + 1] >> 4) & 017); } rx_bptr = rx_bptr + 1; rx_tr = 1; break; case FILL: /* fill buffer */ if (rx_csr & RXCS_MODE) { /* 8b xfer? */ rx_buf[rx_bptr] = rx_dbr; /* fill buffer */ rx_bptr = rx_bptr + 1; if (rx_bptr < bps) /* if more, set xfer */ rx_tr = 1; else rx_done (0, 0); /* else done */ } else { byptr = PTR12 (rx_bptr); /* 12b xfer */ if (rx_bptr & 1) { /* odd or even? */ rx_buf[byptr] = (rx_buf[byptr] & 0360) | ((rx_dbr >> 8) & 017); rx_buf[byptr + 1] = rx_dbr & 0377; } else { rx_buf[byptr] = (rx_dbr >> 4) & 0377; rx_buf[byptr + 1] = (rx_dbr & 017) << 4; } rx_bptr = rx_bptr + 1; if (rx_bptr < wps) /* if more, set xfer */ rx_tr = 1; else { for (i = PTR12 (wps); i < bps; i++) rx_buf[i] = 0; /* else fill sector */ rx_done (0, 0); /* set done */ } } break; case RWDS: /* wait for sector */ rx_sector = rx_dbr & RX_M_SECTOR; /* save sector */ rx_tr = 1; /* set xfer ready */ rx_state = RWDT; /* advance state */ return SCPE_OK; case RWDT: /* wait for track */ rx_track = rx_dbr & RX_M_TRACK; /* save track */ rx_state = RWXFR; sim_activate (uptr, /* sched done */ rx_swait * abs (rx_track - uptr->TRACK)); return SCPE_OK; case RWXFR: /* transfer */ if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ rx_done (0, 0110); /* done, error */ return IORETURN (rx_stopioe, SCPE_UNATT); } if (rx_track >= RX_NUMTR) { /* bad track? */ rx_done (0, 0040); /* done, error */ break; } uptr->TRACK = rx_track; /* now on track */ if ((rx_sector == 0) || (rx_sector > RX_NUMSC)) { /* bad sect? */ rx_done (0, 0070); /* done, error */ break; } if (rx_28 && /* RX28? */ (((uptr->flags & UNIT_DEN) != 0) ^ ((rx_csr & RXCS_DEN) != 0))) { /* densities agree? */ rx_done (RXES_DERR, 0240); /* no, error */ break; } da = CALC_DA (rx_track, rx_sector, bps); /* get disk address */ if (func == RXCS_WRDEL) /* del data? */ rx_esr = rx_esr | RXES_DD; if (func == RXCS_READ) { /* read? */ for (i = 0; i < bps; i++) rx_buf[i] = fbuf[da + i]; } else { /* write */ if (uptr->flags & UNIT_WPRT) { /* locked? */ rx_done (0, 0100); /* done, error */ break; } for (i = 0; i < bps; i++) fbuf[da + i] = rx_buf[i]; da = da + bps; if (da > uptr->hwmark) uptr->hwmark = da; } rx_done (0, 0); /* done */ break; case SDCNF: /* confirm set density */ if ((rx_dbr & 0377) != 0111) { /* confirmed? */ rx_done (0, 0250); /* no, error */ break; } rx_state = SDXFR; /* next state */ sim_activate (uptr, rx_cwait * 100); /* schedule operation */ break; case SDXFR: /* erase disk */ for (i = 0; i < (int32) uptr->capac; i++) fbuf[i] = 0; uptr->hwmark = uptr->capac; if (rx_csr & RXCS_DEN) uptr->flags = uptr->flags | UNIT_DEN; else uptr->flags = uptr->flags & ~UNIT_DEN; rx_done (0, 0); break; case CMD_COMPLETE: /* command complete */ if (func == RXCS_ECODE) { /* read ecode? */ rx_dbr = rx_ecode; /* set dbr */ rx_done (0, -1); /* don't update */ } else if (rx_28) { /* no, read sta; RX28? */ rx_esr = rx_esr & ~RXES_DERR; /* assume dens match */ if (((uptr->flags & UNIT_DEN) != 0) ^ /* densities mismatch? */ ((rx_csr & RXCS_DEN) != 0)) rx_done (RXES_DERR, 0240); /* yes, error */ else rx_done (0, 0); /* no, ok */ } else rx_done (0, 0); /* RX8E status */ break; case INIT_COMPLETE: /* init complete */ rx_unit[0].TRACK = 1; /* drive 0 to trk 1 */ rx_unit[1].TRACK = 0; /* drive 1 to trk 0 */ if ((rx_unit[0].flags & UNIT_BUF) == 0) { /* not buffered? */ rx_done (RXES_ID, 0010); /* init done, error */ break; } da = CALC_DA (1, 1, bps); /* track 1, sector 1 */ for (i = 0; i < bps; i++) /* read sector */ rx_buf[i] = fbuf[da + i]; rx_done (RXES_ID, 0); /* set done */ if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020; break; } /* end case state */ return SCPE_OK; } /* Command complete. Set done and put final value in interface register, return to IDLE state. */ void rx_done (int32 esr_flags, int32 new_ecode) { int32 drv = (rx_csr & RXCS_DRV)? 1: 0; rx_state = IDLE; /* now idle */ dev_done = dev_done | INT_RX; /* set done */ int_req = INT_UPDATE; /* update ints */ rx_esr = (rx_esr | esr_flags) & ~(RXES_DRDY|RXES_RX02|RXES_DEN); if (rx_28) /* RX28? */ rx_esr = rx_esr | RXES_RX02; if (rx_unit[drv].flags & UNIT_ATT) { /* update drv rdy */ rx_esr = rx_esr | RXES_DRDY; if (rx_unit[drv].flags & UNIT_DEN) /* update density */ rx_esr = rx_esr | RXES_DEN; } if (new_ecode > 0) /* test for error */ rx_err = 1; if (new_ecode < 0) /* don't update? */ return; rx_ecode = new_ecode; /* update ecode */ rx_dbr = rx_esr; /* update RXDB */ return; } /* Reset routine. The RX is one of the few devices that schedules an I/O transfer as part of its initialization */ t_stat rx_reset (DEVICE *dptr) { rx_dbr = rx_csr = 0; /* 12b mode, drive 0 */ rx_esr = rx_ecode = 0; /* clear error */ rx_tr = rx_err = 0; /* clear flags */ rx_track = rx_sector = 0; /* clear address */ rx_state = IDLE; /* ctrl idle */ dev_done = dev_done & ~INT_RX; /* clear done, int */ int_req = int_req & ~INT_RX; int_enable = int_enable & ~INT_RX; sim_cancel (&rx_unit[1]); /* cancel drive 1 */ if (dptr->flags & DEV_DIS) /* disabled? */ sim_cancel (&rx_unit[0]); else if (rx_unit[0].flags & UNIT_BUF) { /* attached? */ rx_state = INIT_COMPLETE; /* yes, sched init */ sim_activate (&rx_unit[0], rx_swait * abs (1 - rx_unit[0].TRACK)); } else rx_done (rx_esr | RXES_ID, 0010); /* no, error */ return SCPE_OK; } /* Attach routine */ t_stat rx_attach (UNIT *uptr, CONST char *cptr) { uint32 sz; if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) { if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN; else uptr->flags = uptr->flags & ~UNIT_DEN; } uptr->capac = (uptr->flags & UNIT_DEN)? RX2_SIZE: RX_SIZE; return attach_unit (uptr, cptr); } /* Set size routine */ t_stat rx_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { if (uptr->flags & UNIT_ATT) return SCPE_ALATT; if ((rx_28 == 0) && val) /* not on RX8E */ return SCPE_NOFNC; uptr->capac = val? RX2_SIZE: RX_SIZE; return SCPE_OK; } /* Set controller type */ t_stat rx_settype (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int32 i; if ((val < 0) || (val > 1) || (cptr != NULL)) return SCPE_ARG; if (val == rx_28) return SCPE_OK; for (i = 0; i < RX_NUMDR; i++) { if (rx_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } for (i = 0; i < RX_NUMDR; i++) { if (val) rx_unit[i].flags = rx_unit[i].flags | UNIT_DEN | UNIT_AUTO; else rx_unit[i].flags = rx_unit[i].flags & ~(UNIT_DEN | UNIT_AUTO); rx_unit[i].capac = val? RX2_SIZE: RX_SIZE; } rx_28 = val; return SCPE_OK; } /* Show controller type */ t_stat rx_showtype (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { if (rx_28) fprintf (st, "RX28"); else fprintf (st, "RX8E"); return SCPE_OK; } /* Bootstrap routine */ #define BOOT_START 022 #define BOOT_ENTRY 022 #define BOOT_INST 060 #define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) #define BOOT2_START 020 #define BOOT2_ENTRY 033 #define BOOT2_LEN (sizeof (boot2_rom) / sizeof (int16)) static const uint16 boot_rom[] = { 06755, /* 22, SDN */ 05022, /* 23, JMP .-1 */ 07126, /* 24, CLL CML RTL ; read command + */ 01060, /* 25, TAD UNIT ; unit no */ 06751, /* 26, LCD ; load read+unit */ 07201, /* 27, CLA IAC ; AC = 1 */ 04053, /* 30, JMS LOAD ; load sector */ 04053, /* 31, JMS LOAD ; load track */ 07104, /* 32, CLL RAL ; AC = 2 */ 06755, /* 33, SDN */ 05054, /* 34, JMP LOAD+1 */ 06754, /* 35, SER */ 07450, /* 36, SNA ; more to do? */ 07610, /* 37, CLA SKP ; error */ 05046, /* 40, JMP 46 ; go empty */ 07402, /* 41-45, HALT ; error */ 07402, 07402, 07402, 07402, 06751, /* 46, LCD ; load empty */ 04053, /* 47, JMS LOAD ; get data */ 03002, /* 50, DCA 2 ; store */ 02050, /* 51, ISZ 50 ; incr store */ 05047, /* 52, JMP 47 ; loop until done */ 00000, /* LOAD, 0 */ 06753, /* 54, STR */ 05033, /* 55, JMP 33 */ 06752, /* 56, XDR */ 05453, /* 57, JMP I LOAD */ 07024, /* UNIT, CML RAL ; for unit 1 */ 06030 /* 61, KCC */ }; static const uint16 boot2_rom[] = { 01061, /* READ, TAD UNIT ; next unit+den */ 01046, /* 21, TAD CON360 ; add in 360 */ 00060, /* 22, AND CON420 ; mask to 420 */ 03061, /* 23, DCA UNIT ; 400,420,0,20... */ 07327, /* 24, STL CLA IAC RTL ; AC = 6 = read */ 01061, /* 25, TAD UNIT ; +unit+den */ 06751, /* 26, LCD ; load cmd */ 07201, /* 27, CLA IAC; ; AC = 1 = trksec */ 04053, /* 30, JMS LOAD ; load trk */ 04053, /* 31, JMS LOAD ; load sec */ 07004, /* CN7004, RAL ; AC = 2 = empty */ 06755, /* START, SDN ; done? */ 05054, /* 34, JMP LOAD+1 ; check xfr */ 06754, /* 35, SER ; error? */ 07450, /* 36, SNA ; AC=0 on start */ 05020, /* 37, JMP RD ; try next den,un */ 01061, /* 40, TAD UNIT ; +unit+den */ 06751, /* 41, LCD ; load cmd */ 01061, /* 42, TAD UNIT ; set 60 for sec boot */ 00046, /* 43, AND CON360 ; only density */ 01032, /* 44, TAD CN7004 ; magic */ 03060, /* 45, DCA 60 */ 00360, /* CON360, 360 ; NOP */ 04053, /* 47, JMS LOAD ; get data */ 03002, /* 50, DCA 2 ; store */ 02050, /* 51, ISZ .-1 ; incr store */ 05047, /* 52, JMP .-3 ; loop until done */ 00000, /* LOAD, 0 */ 06753, /* 54, STR ; xfr ready? */ 05033, /* 55, JMP 33 ; no, chk done */ 06752, /* 56, XDR ; get word */ 05453, /* 57, JMP I 53 ; return */ 00420, /* CON420, 420 ; toggle */ 00020 /* UNIT, 20 ; unit+density */ }; t_stat rx_boot (int32 unitno, DEVICE *dptr) { size_t i; extern uint16 M[]; if (rx_dib.dev != DEV_RX) /* only std devno */ return STOP_NOTSTD; if (rx_28) { for (i = 0; i < BOOT2_LEN; i++) M[BOOT2_START + i] = boot2_rom[i]; cpu_set_bootpc (BOOT2_ENTRY); } else { for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; M[BOOT_INST] = unitno? 07024: 07004; cpu_set_bootpc (BOOT_ENTRY); } return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 | /* pdp8_sys.c: PDP-8 simulator interface Copyright (c) 1993-2016, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 15-Dec-16 RMS Added PKSTF (Dave Gesswein) 17-Sep-13 RMS Fixed recognition of initial field change (Dave Gesswein) 24-Mar-09 RMS Added link to FPP 24-Jun-08 RMS Fixed bug in new rim loader (Don North) 24-May-08 RMS Fixed signed/unsigned declaration inconsistency 03-Sep-07 RMS Added FPP8 support Rewrote rim and binary loaders 15-Dec-06 RMS Added TA8E support, IOT disambiguation 30-Oct-06 RMS Added infinite loop stop 18-Oct-06 RMS Re-ordered device list 17-Oct-03 RMS Added TSC8-75, TD8E support, DECtape off reel message 25-Apr-03 RMS Revised for extended file support 30-Dec-01 RMS Revised for new TTX 26-Nov-01 RMS Added RL8A support 17-Sep-01 RMS Removed multiconsole support 16-Sep-01 RMS Added TSS/8 packed char support, added KL8A support 27-May-01 RMS Added multiconsole support 18-Mar-01 RMS Added DF32 support 14-Mar-01 RMS Added extension detection of RIM binary tapes 15-Feb-01 RMS Added DECtape support 30-Oct-00 RMS Added support for examine to file 27-Oct-98 RMS V2.4 load interface 10-Apr-98 RMS Added RIM loader support 17-Feb-97 RMS Fixed bug in handling of bin loader fields */ #include "pdp8_defs.h" #include <ctype.h> extern DEVICE cpu_dev; extern UNIT cpu_unit; extern DEVICE tsc_dev; extern DEVICE fpp_dev; extern DEVICE ptr_dev, ptp_dev; extern DEVICE tti_dev, tto_dev; extern DEVICE clk_dev, lpt_dev; extern DEVICE rk_dev, rl_dev; extern DEVICE rx_dev; extern DEVICE df_dev, rf_dev; extern DEVICE dt_dev, td_dev; extern DEVICE mt_dev, ct_dev; extern DEVICE ttix_dev, ttox_dev; extern REG cpu_reg[]; extern uint16 M[]; t_stat fprint_sym_fpp (FILE *of, t_value *val); t_stat parse_sym_fpp (CONST char *cptr, t_value *val); CONST char *parse_field (CONST char *cptr, uint32 max, uint32 *val, uint32 c); CONST char *parse_fpp_xr (CONST char *cptr, uint32 *xr, t_bool inc); int32 test_fpp_addr (uint32 ad, uint32 max); /* SCP data structures and interface routines sim_name simulator name string sim_PC pointer to saved PC register descriptor sim_emax maximum number of words for examine/deposit sim_devices array of pointers to simulated devices sim_consoles array of pointers to consoles (if more than one) sim_stop_messages array of pointers to stop messages sim_load binary loader */ char sim_name[] = "PDP-8"; REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 4; DEVICE *sim_devices[] = { &cpu_dev, &tsc_dev, &fpp_dev, &clk_dev, &ptr_dev, &ptp_dev, &tti_dev, &tto_dev, &ttix_dev, &ttox_dev, &lpt_dev, &rk_dev, &rl_dev, &rx_dev, &df_dev, &rf_dev, &dt_dev, &td_dev, &mt_dev, &ct_dev, NULL }; const char *sim_stop_messages[] = { "Unknown error", "Unimplemented instruction", "HALT instruction", "Breakpoint", "Opcode Breakpoint", "Non-standard device number", "DECtape off reel", "Infinite loop" }; /* Ambiguous device list - these devices have overlapped IOT codes */ DEVICE *amb_dev[] = { &rl_dev, &ct_dev, &td_dev, NULL }; #define AMB_RL (1 << 12) #define AMB_CT (2 << 12) #define AMB_TD (3 << 12) /* RIM loader format consists of alternating pairs of addresses and 12-bit words. It can only operate in field 0 and is not checksummed. */ t_stat sim_load_rim (FILE *fi) { int32 origin, hi, lo, wd; origin = 0200; do { /* skip leader */ if ((hi = getc (fi)) == EOF) return SCPE_FMT; } while ((hi == 0) || (hi >= 0200)); do { /* data block */ if ((lo = getc (fi)) == EOF) return SCPE_FMT; wd = (hi << 6) | lo; if (wd > 07777) origin = wd & 07777; else M[origin++ & 07777] = wd; if ((hi = getc (fi)) == EOF) return SCPE_FMT; } while (hi < 0200); /* until trailer */ return SCPE_OK; } /* BIN loader format consists of a string of 12-bit words (made up from 7-bit characters) between leader and trailer (200). The last word on tape is the checksum. A word with the "link" bit set is a new origin; a character > 0200 indicates a change of field. */ int32 sim_bin_getc (FILE *fi, uint32 *newf) { int32 c, rubout; rubout = 0; /* clear toggle */ while ((c = getc (fi)) != EOF) { /* read char */ if (rubout) /* toggle set? */ rubout = 0; /* clr, skip */ else if (c == 0377) /* rubout? */ rubout = 1; /* set, skip */ else if (c > 0200) /* channel 8 set? */ *newf = (c & 070) << 9; /* change field */ else return c; /* otherwise ok */ } return EOF; } t_stat sim_load_bin (FILE *fi) { int32 hi, lo, wd, csum, t; uint32 field, newf, origin; int32 sections_read = 0; for (;;) { csum = origin = field = newf = 0; /* init */ do { /* skip leader */ if ((hi = sim_bin_getc (fi, &newf)) == EOF) { if (sections_read != 0) { sim_printf ("%d sections sucessfully read\n\r", sections_read); return SCPE_OK; } else return SCPE_FMT; } } while ((hi == 0) || (hi >= 0200)); for (;;) { /* data blocks */ if ((lo = sim_bin_getc (fi, &newf)) == EOF) /* low char */ return SCPE_FMT; wd = (hi << 6) | lo; /* form word */ t = hi; /* save for csum */ if ((hi = sim_bin_getc (fi, &newf)) == EOF) /* next char */ return SCPE_FMT; if (hi == 0200) { /* end of tape? */ if ((csum - wd) & 07777) { /* valid csum? */ if (sections_read != 0) sim_printf ("%d sections sucessfully read\n\r", sections_read); return SCPE_CSUM; } if (!(sim_switches & SWMASK ('A'))) /* Load all sections? */ return SCPE_OK; sections_read++; break; } csum = csum + t + lo; /* add to csum */ if (wd > 07777) /* chan 7 set? */ origin = wd & 07777; /* new origin */ else { /* no, data */ if ((field | origin) >= MEMSIZE) return SCPE_NXM; M[field | origin] = wd; origin = (origin + 1) & 07777; } field = newf; /* update field */ } } return SCPE_IERR; } /* Binary loader Two loader formats are supported: RIM loader (-r) and BIN (-b) loader. */ t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) { if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; if ((sim_switches & SWMASK ('R')) || /* RIM format? */ (match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B')))) return sim_load_rim (fileref); else return sim_load_bin (fileref); /* no, BIN */ } /* Symbol tables */ #define I_V_FL 18 /* flag start */ #define I_M_FL 07 /* flag mask */ #define I_V_NPN 0 /* no operand */ #define I_V_FLD 1 /* field change */ #define I_V_MRF 2 /* mem ref */ #define I_V_IOT 3 /* general IOT */ #define I_V_OP1 4 /* operate 1 */ #define I_V_OP2 5 /* operate 2 */ #define I_V_OP3 6 /* operate 3 */ #define I_V_IOA 7 /* ambiguous IOT */ #define I_NPN (I_V_NPN << I_V_FL) #define I_FLD (I_V_FLD << I_V_FL) #define I_MRF (I_V_MRF << I_V_FL) #define I_IOT (I_V_IOT << I_V_FL) #define I_OP1 (I_V_OP1 << I_V_FL) #define I_OP2 (I_V_OP2 << I_V_FL) #define I_OP3 (I_V_OP3 << I_V_FL) #define I_IOA (I_V_IOA << I_V_FL) static const int32 masks[] = { 07777, 07707, 07000, 07000, 07416, 07571, 017457, 077777, }; /* Ambiguous device mnemonics must precede default mnemonics */ static const char *opcode[] = { "SKON", "ION", "IOF", "SRQ", /* std IOTs */ "GTF", "RTF", "SGT", "CAF", "RPE", "RSF", "RRB", "RFC", "RFC RRB", /* reader/punch */ "PCE", "PSF", "PCF", "PPC", "PLS", "KCF", "KSF", "KCC", "KRS", "KIE", "KRB", /* console */ "TLF", "TSF", "TCF", "TPC", "SPI", "TLS", "SBE", "SPL", "CAL", /* power fail */ "CLEI", "CLDI", "CLSC", "CLLE", "CLCL", "CLSK", /* clock */ "CINT", "RDF", "RIF", "RIB", /* mem mmgt */ "RMF", "SINT", "CUF", "SUF", "RLDC", "RLSD", "RLMA", "RLCA", /* RL - ambiguous */ "RLCB", "RLSA", "RLWC", "RRER", "RRWC", "RRCA", "RRCB", "RRSA", "RRSI", "RLSE", "KCLR", "KSDR", "KSEN", "KSBF", /* CT - ambiguous */ "KLSA", "KSAF", "KGOA", "KRSB", "SDSS", "SDST", "SDSQ", /* TD - ambiguous */ "SDLC", "SDLD", "SDRC", "SDRD", "ADCL", "ADLM", "ADST", "ADRB", /* A/D */ "ADSK", "ADSE", "ADLE", "ADRS", "DCMA", "DMAR", "DMAW", /* DF/RF */ "DCIM", "DSAC", "DIML", "DIMA", "DCEA", "DEAL", "DEAC", "DFSE", "DFSC", "DISK", "DMAC", "DCXA", "DXAL", "DXAC", "PKSTF", "PSKF", "PCLF", "PSKE", /* LPT */ "PSTB", "PSIE", "PCLF PSTB", "PCIE", "LWCR", "CWCR", "LCAR", /* MT */ "CCAR", "LCMR", "LFGR", "LDBR", "RWCR", "CLT", "RCAR", "RMSR", "RCMR", "RFSR", "RDBR", "SKEF", "SKCB", "SKJD", "SKTR", "CLF", "DSKP", "DCLR", "DLAG", /* RK */ "DLCA", "DRST", "DLDC", "DMAN", "LCD", "XDR", "STR", /* RX */ "SER", "SDN", "INTR", "INIT", "DTRA", "DTCA", "DTXA", "DTLA", /* DT */ "DTSF", "DTRB", "DTLB", "ETDS", "ESKP", "ECTF", "ECDF", /* TSC75 */ "ERTB", "ESME", "ERIOT", "ETEN", "FFST", "FPINT", "FPICL", "FPCOM", /* FPP8 */ "FPHLT", "FPST", "FPRST", "FPIST", "FMODE", "FMRB", "FMRP", "FMDO", "FPEP", "CDF", "CIF", "CIF CDF", "AND", "TAD", "ISZ", "DCA", "JMS", "JMP", "IOT", "NOP", "NOP2", "NOP3", "SWAB", "SWBA", "STL", "GLK", "STA", "LAS", "CIA", "BSW", "RAL", "RTL", "RAR", "RTR", "RAL RAR", "RTL RTR", "SKP", "SNL", "SZL", "SZA", "SNA", "SZA SNL", "SNA SZL", "SMA", "SPA", "SMA SNL", "SPA SZL", "SMA SZA", "SPA SNA", "SMA SZA SNL", "SPA SNA SZL", "SCL", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR", "SCA", "SCA SCL", "SCA MUY", "SCA DVI", "SCA NMI", "SCA SHL", "SCA ASR", "SCA LSR", "ACS", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR", "SCA", "DAD", "DST", "SWBA", "DPSZ", "DPIC", "DCIM", "SAM", "CLA", "CLL", "CMA", "CML", "IAC", /* encode only */ "CLA", "OAS", "HLT", "CLA", "MQA", "MQL", NULL, NULL, NULL, NULL, /* decode only */ NULL }; static const int32 opc_val[] = { 06000+I_NPN, 06001+I_NPN, 06002+I_NPN, 06003+I_NPN, 06004+I_NPN, 06005+I_NPN, 06006+I_NPN, 06007+I_NPN, 06010+I_NPN, 06011+I_NPN, 06012+I_NPN, 06014+I_NPN, 06016+I_NPN, 06020+I_NPN, 06021+I_NPN, 06022+I_NPN, 06024+I_NPN, 06026+I_NPN, 06030+I_NPN, 06031+I_NPN, 06032+I_NPN, 06034+I_NPN, 06035+I_NPN, 06036+I_NPN, 06040+I_NPN, 06041+I_NPN, 06042+I_NPN, 06044+I_NPN, 06045+I_NPN, 06046+I_NPN, 06101+I_NPN, 06102+I_NPN, 06103+I_NPN, 06131+I_NPN, 06132+I_NPN, 06133+I_NPN, 06135+I_NPN, 06136+I_NPN, 06137+I_NPN, 06204+I_NPN, 06214+I_NPN, 06224+I_NPN, 06234+I_NPN, 06244+I_NPN, 06254+I_NPN, 06264+I_NPN, 06274+I_NPN, 06600+I_IOA+AMB_RL, 06601+I_IOA+AMB_RL, 06602+I_IOA+AMB_RL, 06603+I_IOA+AMB_RL, 06604+I_IOA+AMB_RL, 06605+I_IOA+AMB_RL, 06607+I_IOA+AMB_RL, 06610+I_IOA+AMB_RL, 06611+I_IOA+AMB_RL, 06612+I_IOA+AMB_RL, 06613+I_IOA+AMB_RL, 06614+I_IOA+AMB_RL, 06615+I_IOA+AMB_RL, 06617+I_IOA+AMB_RL, 06700+I_IOA+AMB_CT, 06701+I_IOA+AMB_CT, 06702+I_IOA+AMB_CT, 06703+I_IOA+AMB_CT, 06704+I_IOA+AMB_CT, 06705+I_IOA+AMB_CT, 06706+I_IOA+AMB_CT, 06707+I_IOA+AMB_CT, 06771+I_IOA+AMB_TD, 06772+I_IOA+AMB_TD, 06773+I_IOA+AMB_TD, 06774+I_IOA+AMB_TD, 06775+I_IOA+AMB_TD, 06776+I_IOA+AMB_TD, 06777+I_IOA+AMB_TD, 06530+I_NPN, 06531+I_NPN, 06532+I_NPN, 06533+I_NPN, /* AD */ 06534+I_NPN, 06535+I_NPN, 06536+I_NPN, 06537+I_NPN, 06660+I_NPN, 06601+I_NPN, 06603+I_NPN, 06605+I_NPN, /* DF/RF */ 06611+I_NPN, 06612+I_NPN, 06615+I_NPN, 06616+I_NPN, 06611+I_NPN, 06615+I_NPN, 06616+I_NPN, 06621+I_NPN, 06622+I_NPN, 06623+I_NPN, 06626+I_NPN, 06641+I_NPN, 06643+I_NPN, 06645+I_NPN, 06661+I_NPN, 06662+I_NPN, 06663+I_NPN, /* LPT */ 06664+I_NPN, 06665+I_NPN, 06666+I_NPN, 06667+I_NPN, 06701+I_NPN, 06702+I_NPN, 06703+I_NPN, /* MT */ 06704+I_NPN, 06705+I_NPN, 06706+I_NPN, 06707+I_NPN, 06711+I_NPN, 06712+I_NPN, 06713+I_NPN, 06714+I_NPN, 06715+I_NPN, 06716+I_NPN, 06717+I_NPN, 06721+I_NPN, 06722+I_NPN, 06723+I_NPN, 06724+I_NPN, 06725+I_NPN, 06741+I_NPN, 06742+I_NPN, 06743+I_NPN, /* RK */ 06744+I_NPN, 06745+I_NPN, 06746+I_NPN, 06747+I_NPN, 06751+I_NPN, 06752+I_NPN, 06753+I_NPN, /* RX */ 06754+I_NPN, 06755+I_NPN, 06756+I_NPN, 06757+I_NPN, 06761+I_NPN, 06762+I_NPN, 06764+I_NPN, 06766+I_NPN, /* DT */ 06771+I_NPN, 06772+I_NPN, 06774+I_NPN, 06360+I_NPN, 06361+I_NPN, 06362+I_NPN, 06363+I_NPN, /* TSC */ 06364+I_NPN, 06365+I_NPN, 06366+I_NPN, 06367+I_NPN, 06550+I_NPN, 06551+I_NPN, 06552+I_NPN, 06553+I_NPN, /* FPP8 */ 06554+I_NPN, 06555+I_NPN, 06556+I_NPN, 06557+I_NPN, 06561+I_NPN, 06563+I_NPN, 06564+I_NPN, 06565+I_NPN, 06567+I_NPN, 06201+I_FLD, 06202+I_FLD, 06203+I_FLD, 00000+I_MRF, 01000+I_MRF, 02000+I_MRF, 03000+I_MRF, 04000+I_MRF, 05000+I_MRF, 06000+I_IOT, 07000+I_NPN, 07400+I_NPN, 07401+I_NPN, 07431+I_NPN, 07447+I_NPN, 07120+I_NPN, 07204+I_NPN, 07240+I_NPN, 07604+I_NPN, 07041+I_NPN, 07002+I_OP1, 07004+I_OP1, 07006+I_OP1, 07010+I_OP1, 07012+I_OP1, 07014+I_OP1, 07016+I_OP1, 07410+I_OP2, 07420+I_OP2, 07430+I_OP2, 07440+I_OP2, 07450+I_OP2, 07460+I_OP2, 07470+I_OP2, 07500+I_OP2, 07510+I_OP2, 07520+I_OP2, 07530+I_OP2, 07540+I_OP2, 07550+I_OP2, 07560+I_OP2, 07570+I_OP2, 07403+I_OP3, 07405+I_OP3, 07407+I_OP3, 07411+I_OP3, 07413+I_OP3, 07415+I_OP3, 07417+I_OP3, 07441+I_OP3, 07443+I_OP3, 07445+I_OP3, 07447+I_OP3, 07451+I_OP3, 07453+I_OP3, 07455+I_OP3, 07457+I_OP3, 017403+I_OP3, 017405+I_OP3, 0174017+I_OP3, 017411+I_OP3, 017413+I_OP3, 017415+I_OP3, 017417+I_OP3, 017441+I_OP3, 017443+I_OP3, 017445+I_OP3, 017447+I_OP3, 017451+I_OP3, 017453+I_OP3, 017455+I_OP3, 017457+I_OP3, 07200+I_OP1, 07100+I_OP1, 07040+I_OP1, 07020+I_OP1, 07001+I_OP1, 07600+I_OP2, 07404+I_OP2, 07402+I_OP2, 07601+I_OP3, 07501+I_OP3, 07421+I_OP3, 07000+I_OP1, 07400+I_OP2, 07401+I_OP3, 017401+I_OP3, -1 }; /* Symbol tables for FPP-8 */ #define F_V_FL 18 /* flag start */ #define F_M_FL 017 /* flag mask */ #define F_V_NOP12 0 /* no opnd 12b */ #define F_V_NOP9 1 /* no opnd 9b */ #define F_V_AD15 2 /* 15b dir addr */ #define F_V_AD15X 3 /* 15b dir addr indx */ #define F_V_IMMX 4 /* 12b immm indx */ #define F_V_X 5 /* index */ #define F_V_MRI 6 /* mem ref ind */ #define F_V_MR1D 7 /* mem ref dir 1 word */ #define F_V_MR2D 8 /* mem ref dir 2 word */ #define F_V_LEMU 9 /* LEA/IMUL */ #define F_V_LEMUI 10 /* LEAI/IMULI */ #define F_V_LTR 11 /* LTR */ #define F_V_MRD 12 /* mem ref direct (enc) */ #define F_NOP12 (F_V_NOP12 << F_V_FL) #define F_NOP9 (F_V_NOP9 << F_V_FL) #define F_AD15 (F_V_AD15 << F_V_FL) #define F_AD15X (F_V_AD15X << F_V_FL) #define F_IMMX (F_V_IMMX << F_V_FL) #define F_X (F_V_X << F_V_FL) #define F_MRI (F_V_MRI << F_V_FL) #define F_MR1D (F_V_MR1D << F_V_FL) #define F_MR2D (F_V_MR2D << F_V_FL) #define F_LEMU (F_V_LEMU << F_V_FL) #define F_LEMUI (F_V_LEMUI << F_V_FL) #define F_LTR (F_V_LTR << F_V_FL) #define F_MRD (F_V_MRD << F_V_FL) static const uint32 fmasks[] = { 07777, 07770, 07770, 07600, 07770, 07770, 07600, 07600, 07600, 017600, 017600, 07670, 07777 }; /* Memory references are encode dir / decode 1D / decode 2D / indirect */ static const char *fopcode[] = { "FEXIT", "FPAUSE", "FCLA", "FNEG", "FNORM", "STARTF", "STARTD", "JAC", "ALN", "ATX", "XTA", "FNOP", "STARTE", "LDX", "ADDX", "FLDA", "FLDA", "FLDA", "FLDAI", "JEQ", "JGE", "JLE", "JA", "JNE", "JLT", "JGT", "JAL", "SETX", "SETB", "JSA", "JSR", "FADD", "FADD", "FADD", "FADDI", "JNX", "FSUB", "FSUB", "FSUB", "FSUBI", "TRAP3", "FDIV", "FDIV", "FDIV", "FDIVI", "TRAP4", "FMUL", "FMUL", "FMUL", "FMULI", "LTREQ", "LTRGE", "LTRLE", "LTRA", "LTRNE", "LTRLT", "LTRGT", "LTRAL", "FADDM", "FADDM", "FADDM", "FADDMI", "IMUL", "LEA", "FSTA", "FSTA", "FSTA", "FSTAI", "IMULI", "LEAI", "FMULM", "FMULM", "FMULM", "FMULMI", NULL }; static const int32 fop_val[] = { 00000+F_NOP12, 00001+F_NOP12, 00002+F_NOP12, 00003+F_NOP12, 00004+F_NOP12, 00005+F_NOP12, 00006+F_NOP12, 00007+F_NOP12, 00010+F_X, 00020+F_X, 00030+F_X, 00040+F_NOP9, 00050+F_NOP9, 00100+F_IMMX, 00110+F_IMMX, 00000+F_MRD, 00200+F_MR1D, 00400+F_MR2D, 00600+F_MRI, 01000+F_AD15, 01010+F_AD15, 01020+F_AD15, 01030+F_AD15, 01040+F_AD15, 01050+F_AD15, 01060+F_AD15, 01070+F_AD15, 01100+F_AD15, 01110+F_AD15, 01120+F_AD15, 01130+F_AD15, 01000+F_MRD, 01200+F_MR1D, 01400+F_MR2D, 01600+F_MRI, 02000+F_AD15X, 02000+F_MRD, 02200+F_MR1D, 02400+F_MR2D, 02600+F_MRI, 03000+F_AD15, 03000+F_MRD, 03200+F_MR1D, 03400+F_MR2D, 03600+F_MRI, 04000+F_AD15, 04000+F_MRD, 04200+F_MR1D, 04400+F_MR2D, 04600+F_MRI, 05000+F_LTR, 05010+F_LTR, 05020+F_LTR, 05030+F_LTR, 05040+F_LTR, 05050+F_LTR, 05060+F_LTR, 05070+F_LTR, 05000+F_MRD, 05200+F_MR1D, 05400+F_MR2D, 05600+F_MRI, 016000+F_LEMU, 006000+F_LEMU, 06000+F_MRD, 06200+F_MR1D, 06400+F_MR2D, 06600+F_MRI, 017000+F_LEMUI, 007000+F_LEMUI, 07000+F_MRD, 07200+F_MR1D, 07400+F_MR2D, 07600+F_MRI, -1 }; /* Operate decode Inputs: *of = output stream inst = mask bits Class = instruction class code sp = space needed? Outputs: status = space needed */ int32 fprint_opr (FILE *of, int32 inst, int32 Class, int32 sp) { int32 i, j; for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ if ((j == Class) && (opc_val[i] & inst)) { /* same class? */ inst = inst & ~opc_val[i]; /* mask bit set? */ fprintf (of, (sp? " %s": "%s"), opcode[i]); sp = 1; } } return sp; } /* Symbolic decode Inputs: *of = output stream addr = current PC *val = pointer to data *uptr = pointer to unit sw = switches Outputs: return = status code */ #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) #define SIXTOASC(x) (((x) >= 040)? (x): (x) + 0100) #define TSSTOASC(x) ((x) + 040) t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) { int32 cflag, i, j, sp, inst, disp, opc; extern int32 emode; t_stat r; cflag = (uptr == NULL) || (uptr == &cpu_unit); inst = val[0]; if (sw & SWMASK ('A')) { /* ASCII? */ if (inst > 0377) return SCPE_ARG; fprintf (of, FMTASC (inst & 0177)); return SCPE_OK; } if (sw & SWMASK ('C')) { /* characters? */ fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077)); fprintf (of, "%c", SIXTOASC (inst & 077)); return SCPE_OK; } if (sw & SWMASK ('T')) { /* TSS8 packed? */ fprintf (of, "%c", TSSTOASC ((inst >> 6) & 077)); fprintf (of, "%c", TSSTOASC (inst & 077)); return SCPE_OK; } if ((sw & SWMASK ('F')) && /* FPP8? */ ((r = fprint_sym_fpp (of, val)) != SCPE_ARG)) return r; if (!(sw & SWMASK ('M'))) return SCPE_ARG; /* Instruction decode */ opc = (inst >> 9) & 07; /* get major opcode */ if (opc == 07) /* operate? */ inst = inst | ((emode & 1) << 12); /* include EAE mode */ if (opc == 06) { /* IOT? */ DEVICE *dptr; DIB *dibp; uint32 dno = (inst >> 3) & 077; for (i = 0; (dptr = amb_dev[i]) != NULL; i++) { /* check amb devices */ if ((dptr->ctxt == NULL) || /* no DIB or */ (dptr->flags & DEV_DIS)) continue; /* disabled? skip */ dibp = (DIB *) dptr->ctxt; /* get DIB */ if ((dno >= dibp->dev) || /* IOT for this dev? */ (dno < (dibp->dev + dibp->num))) { inst = inst | ((i + 1) << 12); /* disambiguate */ break; /* done */ } } } for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ if ((opc_val[i] & 077777) == (inst & masks[j])) { /* match? */ switch (j) { /* case on class */ case I_V_NPN: case I_V_IOA: /* no operands */ fprintf (of, "%s", opcode[i]); /* opcode */ break; case I_V_FLD: /* field change */ fprintf (of, "%s %-o", opcode[i], (inst >> 3) & 07); break; case I_V_MRF: /* mem ref */ disp = inst & 0177; /* displacement */ fprintf (of, "%s%s", opcode[i], ((inst & 00400)? " I ": " ")); if (inst & 0200) { /* current page? */ if (cflag) fprintf (of, "%-o", (addr & 07600) | disp); else fprintf (of, "C %-o", disp); } else fprintf (of, "%-o", disp); /* page zero */ break; case I_V_IOT: /* IOT */ fprintf (of, "%s %-o", opcode[i], inst & 0777); break; case I_V_OP1: /* operate group 1 */ sp = fprint_opr (of, inst & 0361, j, 0); if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); break; case I_V_OP2: /* operate group 2 */ if (opcode[i]) fprintf (of, "%s", opcode[i]); /* skips */ fprint_opr (of, inst & 0206, j, opcode[i] != NULL); break; case I_V_OP3: /* operate group 3 */ sp = fprint_opr (of, inst & 0320, j, 0); if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); break; } /* end case */ return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; } /* Symbolic input Inputs: *cptr = pointer to input string addr = current PC *uptr = pointer to unit *val = pointer to output values sw = switches Outputs: status = error status */ t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) { uint32 cflag, d, i, j, k; t_stat r; char gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); while (isspace (*cptr)) cptr++; /* absorb spaces */ if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ if (cptr[0] == 0) /* must have 1 char */ return SCPE_ARG; val[0] = (t_value) cptr[0] | 0200; return SCPE_OK; } if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */ if (cptr[0] == 0) /* must have 1 char */ return SCPE_ARG; val[0] = (((t_value) cptr[0] & 077) << 6) | ((t_value) cptr[1] & 077); return SCPE_OK; } if ((sw & SWMASK ('T')) || ((*cptr == '"') && cptr++)) { /* TSS8 string? */ if (cptr[0] == 0) /* must have 1 char */ return SCPE_ARG; val[0] = (((t_value) (cptr[0] - 040) & 077) << 6) | ((t_value) (cptr[1] - 040) & 077); return SCPE_OK; } if ((r = parse_sym_fpp (cptr, val)) != SCPE_ARG) /* FPP8 inst? */ return r; /* Instruction parse */ cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; if (opcode[i] == NULL) return SCPE_ARG; val[0] = opc_val[i] & 07777; /* get value */ j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ switch (j) { /* case on class */ case I_V_IOT: /* IOT */ if ((cptr = parse_field (cptr, 0777, &d, 0)) == NULL) return SCPE_ARG; /* get dev+pulse */ val[0] = val[0] | d; break; case I_V_FLD: /* field */ for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; cptr = get_glyph (cptr, gbuf, 0)) { for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; if (opcode[i] != NULL) { k = (opc_val[i] >> I_V_FL) & I_M_FL; if (k != j) return SCPE_ARG; val[0] = val[0] | (opc_val[i] & 07777); } else { d = get_uint (gbuf, 8, 07, &r); if (r != SCPE_OK) return SCPE_ARG; val[0] = val[0] | (d << 3); break; } } break; case I_V_MRF: /* mem ref */ cptr = get_glyph (cptr, gbuf, 0); /* get next field */ if (strcmp (gbuf, "I") == 0) { /* indirect? */ val[0] = val[0] | 0400; cptr = get_glyph (cptr, gbuf, 0); } if ((k = (strcmp (gbuf, "C") == 0)) || (strcmp (gbuf, "Z") == 0)) { if ((cptr = parse_field (cptr, 0177, &d, 0)) == NULL) return SCPE_ARG; val[0] = val[0] | d | (k? 0200: 0); } else { d = get_uint (gbuf, 8, 07777, &r); if (r != SCPE_OK) return SCPE_ARG; if (d <= 0177) val[0] = val[0] | d; else if (cflag && (((addr ^ d) & 07600) == 0)) val[0] = val[0] | (d & 0177) | 0200; else return SCPE_ARG; } break; case I_V_OP1: case I_V_OP2: case I_V_OP3: /* operates */ case I_V_NPN: case I_V_IOA: for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; cptr = get_glyph (cptr, gbuf, 0)) { for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; k = opc_val[i] & 07777; if ((opcode[i] == NULL) || (((k ^ val[0]) & 07000) != 0)) return SCPE_ARG; val[0] = val[0] | k; } break; } /* end case */ if (*cptr != 0) return SCPE_ARG; /* junk at end? */ return SCPE_OK; } /* FPP8 instruction decode */ t_stat fprint_sym_fpp (FILE *of, t_value *val) { uint32 wd1, wd2, xr4b, xr3b, ad15; uint32 i, j; extern uint32 fpp_bra, fpp_cmd; wd1 = (uint32) val[0] | ((fpp_cmd & 04000) << 1); wd2 = (uint32) val[1]; xr4b = (wd1 >> 3) & 017; xr3b = wd1 & 07; ad15 = (xr3b << 12) | wd2; for (i = 0; fop_val[i] >= 0; i++) { /* loop thru ops */ j = (fop_val[i] >> F_V_FL) & F_M_FL; /* get class */ if ((fop_val[i] & 017777) == (wd1 & fmasks[j])) { /* match? */ switch (j) { /* case on class */ case F_V_NOP12: case F_V_NOP9: case F_V_LTR: /* no operands */ fprintf (of, "%s", fopcode[i]); break; case F_V_X: /* index */ fprintf (of, "%s %o", fopcode[i], xr3b); break; case F_V_IMMX: /* index imm */ fprintf (of, "%s %-o,%o", fopcode[i], wd2, xr3b); return -1; /* extra word */ case F_V_AD15: /* 15b address */ fprintf (of, "%s %-o", fopcode[i], ad15); return -1; /* extra word */ case F_V_AD15X: /* 15b addr, indx */ fprintf (of, "%s %-o", fopcode[i], ad15); if (xr4b >= 010) fprintf (of, ",%o+", xr4b & 7); else fprintf (of, ",%o", xr4b); return -1; /* extra word */ case F_V_MR1D: /* 1 word direct */ ad15 = (fpp_bra + (3 * (wd1 & 0177))) & ADDRMASK; fprintf (of, "%s %-o", fopcode[i], ad15); break; case F_V_LEMU: case F_V_MR2D: /* 2 word direct */ fprintf (of, "%s %-o", fopcode[i], ad15); if (xr4b >= 010) fprintf (of, ",%o+", xr4b & 7); else if (xr4b != 0) fprintf (of, ",%o", xr4b); return -1; /* extra word */ case F_V_LEMUI: case F_V_MRI: /* indirect */ ad15 = (fpp_bra + (3 * xr3b)) & ADDRMASK; fprintf (of, "%s %-o", fopcode[i], ad15); if (xr4b >= 010) fprintf (of, ",%o+", xr4b & 7); else if (xr4b != 0) fprintf (of, ",%o", xr4b); break; case F_V_MRD: /* encode only */ return SCPE_IERR; } return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; } /* FPP8 instruction parse */ t_stat parse_sym_fpp (CONST char *cptr, t_value *val) { uint32 i, j, ad, xr; int32 broff, nwd; char gbuf[CBUFSIZE]; cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ for (i = 0; (fopcode[i] != NULL) && (strcmp (fopcode[i], gbuf) != 0) ; i++) ; if (fopcode[i] == NULL) return SCPE_ARG; val[0] = fop_val[i] & 07777; /* get value */ j = (fop_val[i] >> F_V_FL) & F_M_FL; /* get class */ xr = 0; nwd = 0; switch (j) { /* case on class */ case F_V_NOP12: case F_V_NOP9: case F_V_LTR: /* no operands */ break; case F_V_X: /* 3b XR */ if ((cptr = parse_field (cptr, 07, &xr, 0)) == NULL) return SCPE_ARG; val[0] |= xr; break; case F_V_IMMX: /* 12b, XR */ if ((cptr = parse_field (cptr, 07777, &ad, ',')) == NULL) return SCPE_ARG; if ((*cptr == 0) || ((cptr = parse_fpp_xr (cptr, &xr, FALSE)) == NULL)) return SCPE_ARG; val[0] |= xr; val[++nwd] = ad; break; case F_V_AD15: /* 15b addr */ if ((cptr = parse_field (cptr, 077777, &ad, 0)) == NULL) return SCPE_ARG; val[0] |= (ad >> 12) & 07; val[++nwd] = ad & 07777; break; case F_V_AD15X: /* 15b addr, idx */ if ((cptr = parse_field (cptr, 077777, &ad, ',')) == NULL) return SCPE_ARG; if ((*cptr == 0) || ((cptr = parse_fpp_xr (cptr, &xr, FALSE)) == NULL)) return SCPE_ARG; val[0] |= ((xr << 3) | ((ad >> 12) & 07)); val[++nwd] = ad & 07777; break; case F_V_LEMUI: case F_V_MRI: /* indirect */ if ((cptr = parse_field (cptr, 077777, &ad, ',')) == NULL) return SCPE_ARG; if ((*cptr != 0) && ((cptr = parse_fpp_xr (cptr, &xr, TRUE)) == NULL)) return SCPE_ARG; if ((broff = test_fpp_addr (ad, 07)) < 0) return SCPE_ARG; val[0] |= ((xr << 3) | broff); break; case F_V_MRD: /* direct */ if ((cptr = parse_field (cptr, 077777, &ad, ',')) == NULL) return SCPE_ARG; if (((broff = test_fpp_addr (ad, 0177)) < 0) || (*cptr != 0)) { if ((*cptr != 0) && ((cptr = parse_fpp_xr (cptr, &xr, TRUE)) == NULL)) return SCPE_ARG; val[0] |= (00400 | (xr << 3) | ((ad >> 12) & 07)); val[++nwd] = ad & 07777; } else val[0] |= (00200 | broff); break; case F_V_LEMU: if ((cptr = parse_field (cptr, 077777, &ad, ',')) == NULL) return SCPE_ARG; if ((*cptr != 0) && ((cptr = parse_fpp_xr (cptr, &xr, TRUE)) == NULL)) return SCPE_ARG; val[0] |= ((xr << 3) | ((ad >> 12) & 07)); val[++nwd] = ad & 07777; break; case F_V_MR1D: case F_V_MR2D: return SCPE_IERR; } /* end case */ if (*cptr != 0) return SCPE_ARG; /* junk at end? */ return -nwd; } /* Parse field */ CONST char *parse_field (CONST char *cptr, uint32 max, uint32 *val, uint32 c) { char gbuf[CBUFSIZE]; t_stat r; cptr = get_glyph (cptr, gbuf, c); /* get field */ *val = get_uint (gbuf, 8, max, &r); if (r != SCPE_OK) return NULL; return cptr; } /* Parse index register */ CONST char *parse_fpp_xr (CONST char *cptr, uint32 *xr, t_bool inc) { char gbuf[CBUFSIZE]; uint32 len; t_stat r; cptr = get_glyph (cptr, gbuf, 0); /* get field */ len = strlen (gbuf); if (gbuf[len - 1] == '+') { if (!inc) return NULL; gbuf[len - 1] = 0; *xr = 010; } else *xr = 0; *xr += get_uint (gbuf, 8, 7, &r); if (r != SCPE_OK) return NULL; return cptr; } /* Test address in range of base register */ int32 test_fpp_addr (uint32 ad, uint32 max) { uint32 off; extern uint32 fpp_bra; off = ad - fpp_bra; if (((off % 3) != 0) || (off > (max * 3))) return -1; return ((int32) off / 3); } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 | /* pdp8_td.c: PDP-8 simple DECtape controller (TD8E) simulator Copyright (c) 1993-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. This module was inspired by Gerold Pauler's TD8E simulator for Doug Jones' PDP8 simulator but tracks the hardware implementation more closely. td TD8E/TU56 DECtape 17-Sep-13 RMS Changed to use central set_bootpc routine 23-Mar-11 RMS Fixed SDLC to clear AC (from Dave Gesswein) 23-Jun-06 RMS Fixed switch conflict in ATTACH 16-Aug-05 RMS Fixed C++ declaration and cast problems 09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR PDP-8 DECtapes are represented in memory by fixed length buffer of 12b words. Three file formats are supported: 18b/36b 256 words per block [256 x 18b] 16b 256 words per block [256 x 16b] 12b 129 words per block [129 x 12b] When a 16b or 18/36b DECtape file is read in, it is converted to 12b format. DECtape motion is measured in 3b lines. Time between lines is 33.33us. Tape density is nominally 300 lines per inch. The format of a DECtape (as taken from the TD8E formatter) is: reverse end zone 8192 reverse end zone codes ~ 10 feet reverse buffer 200 interblock codes block 0 : block n forward buffer 200 interblock codes forward end zone 8192 forward end zone codes ~ 10 feet A block consists of five 18b header words, a tape-specific number of data words, and five 18b trailer words. All systems except the PDP-8 use a standard block length of 256 words; the PDP-8 uses a standard block length of 86 words (x 18b = 129 words x 12b). Because a DECtape file only contains data, the simulator cannot support write timing and mark track and can only do a limited implementation of non-data words. Read assumes that the tape has been conventionally written forward: header word 0 0 header word 1 block number (for forward reads) header words 2,3 0 header word 4 checksum (for reverse reads) : trailer word 4 checksum (for forward reads) trailer words 3,2 0 trailer word 1 block number (for reverse reads) trailer word 0 0 Write modifies only the data words and dumps the non-data words in the bit bucket. */ #include "pdp8_defs.h" #define DT_NUMDR 2 /* #drives */ #define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ #define UNIT_V_8FMT (UNIT_V_UF + 1) /* 12b format */ #define UNIT_V_11FMT (UNIT_V_UF + 2) /* 16b format */ #define UNIT_WLK (1 << UNIT_V_WLK) #define UNIT_8FMT (1 << UNIT_V_8FMT) #define UNIT_11FMT (1 << UNIT_V_11FMT) #define STATE u3 /* unit state */ #define LASTT u4 /* last time update */ #define WRITTEN u5 /* device buffer is dirty and needs flushing */ #define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ /* System independent DECtape constants */ #define DT_LPERMC 6 /* lines per mark track */ #define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ #define DT_BFLIN (200 * DT_LPERMC) /* end zone buffer */ #define DT_HTLIN (5 * DT_LPERMC) /* lines per hdr/trlr */ /* 16b, 18b, 36b DECtape constants */ #define D18_WSIZE 6 /* word size in lines */ #define D18_BSIZE 384 /* block size in 12b */ #define D18_TSIZE 578 /* tape size */ #define D18_LPERB (DT_HTLIN + (D18_BSIZE * DT_WSIZE) + DT_HTLIN) #define D18_FWDEZ (DT_EZLIN + (D18_LPERB * D18_TSIZE)) #define D18_CAPAC (D18_TSIZE * D18_BSIZE) /* tape capacity */ #define D18_NBSIZE ((D18_BSIZE * D8_WSIZE) / D18_WSIZE) #define D18_FILSIZ (D18_NBSIZE * D18_TSIZE * sizeof (int32)) #define D11_FILSIZ (D18_NBSIZE * D18_TSIZE * sizeof (int16)) /* 12b DECtape constants */ #define D8_WSIZE 4 /* word size in lines */ #define D8_BSIZE 129 /* block size in 12b */ #define D8_TSIZE 1474 /* tape size */ #define D8_LPERB (DT_HTLIN + (D8_BSIZE * DT_WSIZE) + DT_HTLIN) #define D8_FWDEZ (DT_EZLIN + (D8_LPERB * D8_TSIZE)) #define D8_CAPAC (D8_TSIZE * D8_BSIZE) /* tape capacity */ #define D8_FILSIZ (D8_CAPAC * sizeof (int16)) /* This controller */ #define DT_CAPAC D8_CAPAC /* default */ #define DT_WSIZE D8_WSIZE /* Calculated constants, per unit */ #define DTU_BSIZE(u) (((u)->flags & UNIT_8FMT)? D8_BSIZE: D18_BSIZE) #define DTU_TSIZE(u) (((u)->flags & UNIT_8FMT)? D8_TSIZE: D18_TSIZE) #define DTU_LPERB(u) (((u)->flags & UNIT_8FMT)? D8_LPERB: D18_LPERB) #define DTU_FWDEZ(u) (((u)->flags & UNIT_8FMT)? D8_FWDEZ: D18_FWDEZ) #define DTU_CAPAC(u) (((u)->flags & UNIT_8FMT)? D8_CAPAC: D18_CAPAC) #define DT_LIN2BL(p,u) (((p) - DT_EZLIN) / DTU_LPERB (u)) #define DT_LIN2OF(p,u) (((p) - DT_EZLIN) % DTU_LPERB (u)) /* Command register */ #define TDC_UNIT 04000 /* unit select */ #define TDC_FWDRV 02000 /* fwd/rev */ #define TDC_STPGO 01000 /* stop/go */ #define TDC_RW 00400 /* read/write */ #define TDC_MASK 07400 /* implemented */ #define TDC_GETUNIT(x) (((x) & TDC_UNIT)? 1: 0) /* Status register */ #define TDS_WLO 00200 /* write lock */ #define TDS_TME 00100 /* timing/sel err */ /* Mark track register and codes */ #define MTK_MASK 077 #define MTK_REV_END 055 /* rev end zone */ #define MTK_INTER 025 /* interblock */ #define MTK_FWD_BLK 026 /* fwd block */ #define MTK_REV_GRD 032 /* reverse guard */ #define MTK_FWD_PRE 010 /* lock, etc */ #define MTK_DATA 070 /* data */ #define MTK_REV_PRE 073 /* lock, etc */ #define MTK_FWD_GRD 051 /* fwd guard */ #define MTK_REV_BLK 045 /* rev block */ #define MTK_FWD_END 022 /* fwd end zone */ /* DECtape state */ #define STA_STOP 0 /* stopped */ #define STA_DEC 2 /* decelerating */ #define STA_ACC 4 /* accelerating */ #define STA_UTS 6 /* up to speed */ #define STA_DIR 1 /* fwd/rev */ #define ABS(x) (((x) < 0)? (-(x)): (x)) #define MTK_BIT(c,p) (((c) >> (DT_LPERMC - 1 - ((p) % DT_LPERMC))) & 1) /* State and declarations */ int32 td_cmd = 0; /* command */ int32 td_dat = 0; /* data */ int32 td_mtk = 0; /* mark track */ int32 td_slf = 0; /* single line flag */ int32 td_qlf = 0; /* quad line flag */ int32 td_tme = 0; /* timing error flag */ int32 td_csum = 0; /* save check sum */ int32 td_qlctr = 0; /* quad line ctr */ int32 td_ltime = 20; /* interline time */ int32 td_dctime = 40000; /* decel time */ int32 td_stopoffr = 0; static uint8 tdb_mtk[DT_NUMDR][D18_LPERB]; /* mark track bits */ int32 td77 (int32 IR, int32 AC); t_stat td_svc (UNIT *uptr); t_stat td_reset (DEVICE *dptr); t_stat td_attach (UNIT *uptr, CONST char *cptr); void td_flush (UNIT *uptr); t_stat td_detach (UNIT *uptr); t_stat td_boot (int32 unitno, DEVICE *dptr); t_bool td_newsa (int32 newf); t_bool td_setpos (UNIT *uptr); int32 td_header (UNIT *uptr, int32 blk, int32 line); int32 td_trailer (UNIT *uptr, int32 blk, int32 line); int32 td_read (UNIT *uptr, int32 blk, int32 line); void td_write (UNIT *uptr, int32 blk, int32 line, int32 datb); int32 td_set_mtk (int32 code, int32 u, int32 k); t_stat td_show_pos (FILE *st, UNIT *uptr, int32 val, CONST void *desc); extern uint16 M[]; /* TD data structures td_dev DT device descriptor td_unit DT unit list td_reg DT register list td_mod DT modifier list */ DIB td_dib = { DEV_TD8E, 1, { &td77 } }; UNIT td_unit[] = { { UDATA (&td_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, { UDATA (&td_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) } }; REG td_reg[] = { { GRDATAD (TDCMD, td_cmd, 8, 4, 8, "command register") }, { ORDATAD (TDDAT, td_dat, 12, "data register") }, { ORDATAD (TDMTK, td_mtk, 6, "mark track register") }, { FLDATAD (TDSLF, td_slf, 0, "single line flag") }, { FLDATAD (TDQLF, td_qlf, 0, "quad line flag") }, { FLDATAD (TDTME, td_tme, 0, "timing error flag") }, { ORDATAD (TDQL, td_qlctr, 2, "quad line counter") }, { ORDATA (TDCSUM, td_csum, 6), REG_RO }, { DRDATAD (LTIME, td_ltime, 31, "time between lines"), REG_NZ | PV_LEFT }, { DRDATAD (DCTIME, td_dctime, 31, "time to decelerate to a full stop"), REG_NZ | PV_LEFT }, { URDATAD (POS, td_unit[0].pos, 10, T_ADDR_W, 0, DT_NUMDR, PV_LEFT | REG_RO, "positions, in lines, units 0 and 1") }, { URDATAD (STATT, td_unit[0].STATE, 8, 18, 0, DT_NUMDR, REG_RO, "unit state, units 0 and 1") }, { URDATA (LASTT, td_unit[0].LASTT, 10, 32, 0, DT_NUMDR, REG_HRO) }, { FLDATAD (STOP_OFFR, td_stopoffr, 0, "stop on off-reel error") }, { ORDATA (DEVNUM, td_dib.dev, 6), REG_HRO }, { NULL } }; MTAB td_mod[] = { { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, { UNIT_8FMT + UNIT_11FMT, 0, "18b", NULL, NULL }, { UNIT_8FMT + UNIT_11FMT, UNIT_8FMT, "12b", NULL, NULL }, { UNIT_8FMT + UNIT_11FMT, UNIT_11FMT, "16b", NULL, NULL }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, "POSITION", NULL, NULL, &td_show_pos }, { 0 } }; DEVICE td_dev = { "TD", td_unit, td_reg, td_mod, DT_NUMDR, 8, 24, 1, 8, 12, NULL, NULL, &td_reset, &td_boot, &td_attach, &td_detach, &td_dib, DEV_DISABLE | DEV_DIS }; /* IOT routines */ int32 td77 (int32 IR, int32 AC) { int32 pulse = IR & 07; int32 u = TDC_GETUNIT (td_cmd); /* get unit */ int32 diff, t; switch (pulse) { case 01: /* SDSS */ if (td_slf) return AC | IOT_SKP; break; case 02: /* SDST */ if (td_tme) return AC | IOT_SKP; break; case 03: /* SDSQ */ if (td_qlf) return AC | IOT_SKP; break; case 04: /* SDLC */ td_tme = 0; /* clear tim err */ diff = (td_cmd ^ AC) & TDC_MASK; /* cmd changes */ td_cmd = AC & TDC_MASK; /* update cmd */ if ((diff != 0) && (diff != TDC_RW)) { /* signif change? */ if (td_newsa (td_cmd)) /* new command */ return AC | (IORETURN (td_stopoffr, STOP_DTOFF) << IOT_V_REASON); } AC = 0; break; case 05: /* SDLD */ td_slf = 0; /* clear flags */ td_qlf = 0; td_qlctr = 0; td_dat = AC; /* load data reg */ break; case 06: /* SDRC */ td_slf = 0; /* clear flags */ td_qlf = 0; td_qlctr = 0; t = td_cmd | td_mtk; /* form status */ if (td_tme || !(td_unit[u].flags & UNIT_ATT)) /* tim/sel err? */ t = t | TDS_TME; if (td_unit[u].flags & UNIT_WPRT) /* write locked? */ t = t | TDS_WLO; return t; /* return status */ case 07: /* SDRD */ td_slf = 0; /* clear flags */ td_qlf = 0; td_qlctr = 0; return td_dat; /* return data */ } return AC; } /* Command register change (start/stop, forward/reverse, new unit) 1. If change in motion, stop to start - schedule up to speed - set function as next state 2. If change in motion, start to stop, or change in direction - schedule stop */ t_bool td_newsa (int32 newf) { int32 prev_mving, new_mving, prev_dir, new_dir; UNIT *uptr; uptr = td_dev.units + TDC_GETUNIT (newf); /* new unit */ if ((uptr->flags & UNIT_ATT) == 0) /* new unit attached? */ return FALSE; new_mving = ((newf & TDC_STPGO) != 0); /* new moving? */ prev_mving = (uptr->STATE != STA_STOP); /* previous moving? */ new_dir = ((newf & TDC_FWDRV) != 0); /* new dir? */ prev_dir = ((uptr->STATE & STA_DIR) != 0); /* previous dir? */ td_mtk = 0; /* mark trk reg cleared */ if (!prev_mving && !new_mving) /* stop from stop? */ return FALSE; if (new_mving && !prev_mving) { /* start from stop? */ if (td_setpos (uptr)) /* update pos */ return TRUE; sim_cancel (uptr); /* stop current */ sim_activate (uptr, td_dctime - (td_dctime >> 2)); /* sched accel */ uptr->STATE = STA_ACC | new_dir; /* set status */ td_slf = td_qlf = td_qlctr = 0; /* clear state */ return FALSE; } if ((prev_mving && !new_mving) || /* stop from moving? */ (prev_dir != new_dir)) { /* dir chg while moving? */ if (uptr->STATE >= STA_ACC) { /* not stopping? */ if (td_setpos (uptr)) /* update pos */ return TRUE; sim_cancel (uptr); /* stop current */ sim_activate (uptr, td_dctime); /* schedule decel */ uptr->STATE = STA_DEC | prev_dir; /* set status */ td_slf = td_qlf = td_qlctr = 0; /* clear state */ } return FALSE; } return FALSE; } /* Update DECtape position DECtape motion is modeled as a constant velocity, with linear acceleration and deceleration. The motion equations are as follows: t = time since operation started tmax = time for operation (accel, decel only) v = at speed velocity in lines (= 1/td_ltime) Then: at speed dist = t * v accel dist = (t^2 * v) / (2 * tmax) decel dist = (((2 * t * tmax) - t^2) * v) / (2 * tmax) This routine uses the relative (integer) time, rather than the absolute (floating point) time, to allow save and restore of the start times. */ t_bool td_setpos (UNIT *uptr) { uint32 new_time, ut, ulin, udelt; int32 delta; new_time = sim_grtime (); /* current time */ ut = new_time - uptr->LASTT; /* elapsed time */ if (ut == 0) /* no time gone? exit */ return FALSE; uptr->LASTT = new_time; /* update last time */ switch (uptr->STATE & ~STA_DIR) { /* case on motion */ case STA_STOP: /* stop */ delta = 0; break; case STA_DEC: /* slowing */ ulin = ut / (uint32) td_ltime; udelt = td_dctime / td_ltime; delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt); break; case STA_ACC: /* accelerating */ ulin = ut / (uint32) td_ltime; udelt = (td_dctime - (td_dctime >> 2)) / td_ltime; delta = (ulin * ulin) / (2 * udelt); break; case STA_UTS: /* at speed */ delta = ut / (uint32) td_ltime; break; } if (uptr->STATE & STA_DIR) /* update pos */ uptr->pos = uptr->pos - delta; else uptr->pos = uptr->pos + delta; if (((int32) uptr->pos < 0) || ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { detach_unit (uptr); /* off reel */ sim_cancel (uptr); /* no timing pulses */ return TRUE; } return FALSE; } /* Unit service - unit is either changing speed, or it is up to speed */ t_stat td_svc (UNIT *uptr) { int32 mot = uptr->STATE & ~STA_DIR; int32 dir = uptr->STATE & STA_DIR; int32 unum = uptr - td_dev.units; int32 su = TDC_GETUNIT (td_cmd); int32 mtkb, datb; /* Motion cases Decelerating - if go, next state must be accel as specified by td_cmd Accelerating - next state must be up to speed, fall through Up to speed - process line */ if (mot == STA_STOP) /* stopped? done */ return SCPE_OK; if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ uptr->STATE = uptr->pos = 0; /* also done */ return SCPE_UNATT; } switch (mot) { /* case on motion */ case STA_DEC: /* deceleration */ if (td_setpos (uptr)) /* upd pos; off reel? */ return IORETURN (td_stopoffr, STOP_DTOFF); if ((unum != su) || !(td_cmd & TDC_STPGO)) /* not sel or stop? */ uptr->STATE = 0; /* stop */ else { /* selected and go */ uptr->STATE = STA_ACC | /* accelerating */ ((td_cmd & TDC_FWDRV)? STA_DIR: 0); /* in new dir */ sim_activate (uptr, td_dctime - (td_dctime >> 2)); } return SCPE_OK; case STA_ACC: /* accelerating */ if (td_setpos (uptr)) /* upd pos; off reel? */ return IORETURN (td_stopoffr, STOP_DTOFF); uptr->STATE = STA_UTS | dir; /* set up to speed */ break; case STA_UTS: /* up to speed */ if (dir) /* adjust position */ uptr->pos = uptr->pos - 1; else uptr->pos = uptr->pos + 1; uptr->LASTT = sim_grtime (); /* save time */ if (((int32) uptr->pos < 0) || /* off reel? */ (uptr->pos >= (((uint32) DTU_FWDEZ (uptr)) + DT_EZLIN))) { detach_unit (uptr); return IORETURN (td_stopoffr, STOP_DTOFF); } break; /* check function */ } /* At speed - process the current line Once the TD8E is running at speed, it operates line by line. If reading, the current mark track bit is shifted into the mark track register, and the current data nibble (3b) is shifted into the data register. If writing, the current mark track bit is shifted into the mark track register, the top nibble from the data register is written to tape, and the data register is shifted up. The complexity here comes from synthesizing the mark track, based on tape position, and the header data. */ sim_activate (uptr, td_ltime); /* sched next line */ if (unum != su) /* not sel? done */ return SCPE_OK; td_slf = 1; /* set single */ td_qlctr = (td_qlctr + 1) % DT_WSIZE; /* count words */ if (td_qlctr == 0) { /* lines mod 4? */ if (td_qlf) { /* quad line set? */ td_tme = 1; /* timing error */ td_cmd = td_cmd & ~TDC_RW; /* clear write */ } else td_qlf = 1; /* no, set quad */ } datb = 0; /* assume no data */ if (uptr->pos < (DT_EZLIN - DT_BFLIN)) /* rev end zone? */ mtkb = MTK_BIT (MTK_REV_END, uptr->pos); else if (uptr->pos < DT_EZLIN) /* rev buffer? */ mtkb = MTK_BIT (MTK_INTER, uptr->pos); else if (uptr->pos < ((uint32) DTU_FWDEZ (uptr))) { /* data zone? */ int32 blkno = DT_LIN2BL (uptr->pos, uptr); /* block # */ int32 lineno = DT_LIN2OF (uptr->pos, uptr); /* line # within block */ if (lineno < DT_HTLIN) { /* header? */ if ((td_cmd & TDC_RW) == 0) /* read? */ datb = td_header (uptr, blkno, lineno); /* get nibble */ } else if (lineno < (DTU_LPERB (uptr) - DT_HTLIN)) { /* data? */ if (td_cmd & TDC_RW) /* write? */ td_write (uptr, blkno, /* write data nibble */ lineno - DT_HTLIN, /* data rel line num */ (td_dat >> 9) & 07); else datb = td_read (uptr, blkno, /* no, read */ lineno - DT_HTLIN); } else if ((td_cmd & TDC_RW) == 0) /* trailer; read? */ datb = td_trailer (uptr, blkno, lineno - /* get trlr nibble */ (DTU_LPERB (uptr) - DT_HTLIN)); mtkb = tdb_mtk[unum][lineno]; } else if (uptr->pos < (((uint32) DTU_FWDEZ (uptr)) + DT_BFLIN)) mtkb = MTK_BIT (MTK_INTER, uptr->pos); /* fwd buffer? */ else mtkb = MTK_BIT (MTK_FWD_END, uptr->pos); /* fwd end zone */ if (dir) { /* reverse? */ mtkb = mtkb ^ 01; /* complement mark bit, */ datb = datb ^ 07; /* data bits */ } td_mtk = ((td_mtk << 1) | mtkb) & MTK_MASK; /* shift mark reg */ td_dat = ((td_dat << 3) | datb) & 07777; /* shift data reg */ return SCPE_OK; } /* Header read - reads out 18b words in 3b increments word lines contents 0 0-5 0 1 6-11 block number 2 12-17 0 3 18-23 0 4 24-29 reverse checksum (0777777) */ int32 td_header (UNIT *uptr, int32 blk, int32 line) { int32 nibp; switch (line) { case 8: case 9: case 10: case 11: /* block num */ nibp = 3 * (DT_LPERMC - 1 - (line % DT_LPERMC)); return (blk >> nibp) & 07; case 24: case 25: case 26: case 27: case 28: case 29: /* rev csum */ return 07; /* 777777 */ default: return 0; } } /* Trailer read - reads out 18b words in 3b increments Checksum is stored to avoid double calculation word lines contents 0 0-5 forward checksum (lines 0-1, rest 0) 1 6-11 0 2 12-17 0 3 18-23 reverse block mark 4 24-29 0 Note that the reverse block mark (when read forward) appears as the complement obverse (3b nibbles swapped end for end and complemented). */ int32 td_trailer (UNIT *uptr, int32 blk, int32 line) { int32 nibp, i, ba; int16 *fbuf= (int16 *) uptr->filebuf; switch (line) { case 0: td_csum = 07777; /* init csum */ ba = blk * DTU_BSIZE (uptr); for (i = 0; i < DTU_BSIZE (uptr); i++) /* loop thru buf */ td_csum = (td_csum ^ ~fbuf[ba + i]) & 07777; td_csum = ((td_csum >> 6) ^ td_csum) & 077; return (td_csum >> 3) & 07; case 1: return (td_csum & 07); case 18: case 19: case 20: case 21: nibp = 3 * (line % DT_LPERMC); return ((blk >> nibp) & 07) ^ 07; default: return 0; } } /* Data read - convert block number/data line # to offset in data array */ int32 td_read (UNIT *uptr, int32 blk, int32 line) { int16 *fbuf = (int16 *) uptr->filebuf; /* buffer */ uint32 ba = blk * DTU_BSIZE (uptr); /* block base */ int32 nibp = 3 * (DT_WSIZE - 1 - (line % DT_WSIZE)); /* nibble pos */ ba = ba + (line / DT_WSIZE); /* block addr */ return (fbuf[ba] >> nibp) & 07; /* get data nibble */ } /* Data write - convert block number/data line # to offset in data array */ void td_write (UNIT *uptr, int32 blk, int32 line, int32 dat) { int16 *fbuf = (int16 *) uptr->filebuf; /* buffer */ uint32 ba = blk * DTU_BSIZE (uptr); /* block base */ int32 nibp = 3 * (DT_WSIZE - 1 - (line % DT_WSIZE)); /* nibble pos */ ba = ba + (line / DT_WSIZE); /* block addr */ fbuf[ba] = (fbuf[ba] & ~(07 << nibp)) | (dat << nibp); /* upd data nibble */ uptr->WRITTEN = TRUE; if (ba >= uptr->hwmark) /* upd length */ uptr->hwmark = ba + 1; return; } /* Reset routine */ t_stat td_reset (DEVICE *dptr) { int32 i; UNIT *uptr; for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */ uptr = td_dev.units + i; if (sim_is_running) { /* CAF? */ if (uptr->STATE >= STA_ACC) { /* accel or uts? */ if (td_setpos (uptr)) /* update pos */ continue; sim_cancel (uptr); sim_activate (uptr, td_dctime); /* sched decel */ uptr->STATE = STA_DEC | (uptr->STATE & STA_DIR); } } else { sim_cancel (uptr); /* sim reset */ uptr->STATE = 0; uptr->LASTT = sim_grtime (); } } td_slf = td_qlf = td_qlctr = 0; /* clear state */ td_cmd = td_dat = td_mtk = 0; td_csum = 0; return SCPE_OK; } /* Bootstrap routine - OS/8 only 1) Read reverse until reverse end zone (mark track is complement obverse) 2) Read forward until mark track code 031. This is a composite code from the last 4b of the forward block number and the first two bits of the reverse guard (01 -0110 01- 1010). There are 16 lines before the first data word. 3) Store data words from 7354 to end of page. This includes header and trailer words. 4) Continue at location 7400. */ #define BOOT_START 07300 #define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) static const uint16 boot_rom[] = { 01312, /* ST, TAD L4MT ;=2000, reverse */ 04312, /* JMS L4MT ; rev lk for 022 */ 04312, /* JMS L4MT ; fwd lk for 031 */ 06773, /* DAT, SDSQ ; wait for 12b */ 05303, /* JMP .-1 */ 06777, /* SDRD ; read word */ 03726, /* DCA I BUF ; store */ 02326, /* ISZ BUF ; incr ptr */ 05303, /* JMP DAT ; if not 0, cont */ 05732, /* JMP I SCB ; jump to boot */ 02000, /* L4MT,2000 ; overwritten */ 01300, /* TAD ST ; =1312, go */ 06774, /* SDLC ; new command */ 06771, /* MTK, SDSS ; wait for mark */ 05315, /* JMP .-1 */ 06776, /* SDRC ; get mark code */ 00331, /* AND K77 ; mask to 6b */ 01327, /* CMP, TAD MCD ; got target code? */ 07640, /* SZA CLA ; skip if yes */ 05315, /* JMP MTK ; wait for mark */ 02321, /* ISZ CMP ; next target */ 05712, /* JMP I L4MT ; exit */ 07354, /* BUF, 7354 ; loading point */ 07756, /* MCD, -22 ; target 1 */ 07747, /* -31 ; target 2 */ 00077, /* 77 ; mask */ 07400 /* SCB, 7400 ; secondary boot */ }; t_stat td_boot (int32 unitno, DEVICE *dptr) { size_t i; if (unitno) return SCPE_ARG; /* only unit 0 */ if (td_dib.dev != DEV_TD8E) return STOP_NOTSTD; /* only std devno */ td_unit[unitno].pos = DT_EZLIN; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; cpu_set_bootpc (BOOT_START); return SCPE_OK; } /* Attach routine Determine 12b, 16b, or 18b/36b format Allocate buffer If 16b or 18b, read 16b or 18b format and convert to 12b in buffer If 12b, read data into buffer Set up mark track bit array */ t_stat td_attach (UNIT *uptr, CONST char *cptr) { uint32 pdp18b[D18_NBSIZE]; uint16 pdp11b[D18_NBSIZE], *fbuf; int32 i, k, mtkpb; int32 u = uptr - td_dev.units; t_stat r; uint32 ba, sz; r = attach_unit (uptr, cptr); /* attach */ if (r != SCPE_OK) /* fail? */ return r; if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; if (sim_switches & SWMASK ('F')) /* att 18b? */ uptr->flags = uptr->flags & ~UNIT_8FMT; else if (sim_switches & SWMASK ('S')) /* att 16b? */ uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; else if (!(sim_switches & SWMASK ('A')) && /* autosize? */ (sz = sim_fsize (uptr->fileref))) { if (sz == D11_FILSIZ) uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; else if (sz > D8_FILSIZ) uptr->flags = uptr->flags & ~UNIT_8FMT; } } uptr->capac = DTU_CAPAC (uptr); /* set capacity */ uptr->filebuf = calloc (uptr->capac, sizeof (int16)); if (uptr->filebuf == NULL) { /* can't alloc? */ detach_unit (uptr); return SCPE_MEM; } fbuf = (uint16 *) uptr->filebuf; /* file buffer */ sim_printf ("%s%d: ", sim_dname (&td_dev), u); if (uptr->flags & UNIT_8FMT) sim_printf ("12b format"); else if (uptr->flags & UNIT_11FMT) sim_printf ("16b format"); else sim_printf ("18b/36b format"); sim_printf (", buffering file in memory\n"); uptr->io_flush = td_flush; if (uptr->flags & UNIT_8FMT) /* 12b? */ uptr->hwmark = fxread (uptr->filebuf, sizeof (uint16), uptr->capac, uptr->fileref); else { /* 16b/18b */ for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ if (uptr->flags & UNIT_11FMT) { k = fxread (pdp11b, sizeof (uint16), D18_NBSIZE, uptr->fileref); for (i = 0; i < k; i++) pdp18b[i] = pdp11b[i]; } else k = fxread (pdp18b, sizeof (uint32), D18_NBSIZE, uptr->fileref); if (k == 0) break; for ( ; k < D18_NBSIZE; k++) pdp18b[k] = 0; for (k = 0; k < D18_NBSIZE; k = k + 2) { /* loop thru blk */ fbuf[ba] = (pdp18b[k] >> 6) & 07777; fbuf[ba + 1] = ((pdp18b[k] & 077) << 6) | ((pdp18b[k + 1] >> 12) & 077); fbuf[ba + 2] = pdp18b[k + 1] & 07777; ba = ba + 3; } /* end blk loop */ } /* end file loop */ uptr->hwmark = ba; } /* end else */ uptr->flags = uptr->flags | UNIT_BUF; /* set buf flag */ uptr->pos = DT_EZLIN; /* beyond leader */ uptr->LASTT = sim_grtime (); /* last pos update */ uptr->STATE = STA_STOP; /* stopped */ mtkpb = (DTU_BSIZE (uptr) * DT_WSIZE) / DT_LPERMC; /* mtk codes per blk */ k = td_set_mtk (MTK_INTER, u, 0); /* fill mark track */ k = td_set_mtk (MTK_FWD_BLK, u, k); /* bit array */ k = td_set_mtk (MTK_REV_GRD, u, k); for (i = 0; i < 4; i++) k = td_set_mtk (MTK_FWD_PRE, u, k); for (i = 0; i < (mtkpb - 4); i++) k = td_set_mtk (MTK_DATA, u, k); for (i = 0; i < 4; i++) k = td_set_mtk (MTK_REV_PRE, u, k); k = td_set_mtk (MTK_FWD_GRD, u, k); k = td_set_mtk (MTK_REV_BLK, u, k); k = td_set_mtk (MTK_INTER, u, k); return SCPE_OK; } /* Detach routine If 12b, write buffer to file If 16b or 18b, convert 12b buffer to 16b or 18b and write to file Deallocate buffer */ void td_flush (UNIT* uptr) { uint32 pdp18b[D18_NBSIZE]; uint16 pdp11b[D18_NBSIZE], *fbuf; int32 i, k; uint32 ba; if (uptr->WRITTEN && uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ rewind (uptr->fileref); /* start of file */ fbuf = (uint16 *) uptr->filebuf; /* file buffer */ if (uptr->flags & UNIT_8FMT) /* PDP8? */ fxwrite (uptr->filebuf, sizeof (uint16), /* write file */ uptr->hwmark, uptr->fileref); else { /* 16b/18b */ for (ba = 0; ba < uptr->hwmark; ) { /* loop thru buf */ for (k = 0; k < D18_NBSIZE; k = k + 2) { pdp18b[k] = ((uint32) (fbuf[ba] & 07777) << 6) | ((uint32) (fbuf[ba + 1] >> 6) & 077); pdp18b[k + 1] = ((uint32) (fbuf[ba + 1] & 077) << 12) | ((uint32) (fbuf[ba + 2] & 07777)); ba = ba + 3; } /* end loop blk */ if (uptr->flags & UNIT_11FMT) { /* 16b? */ for (i = 0; i < D18_NBSIZE; i++) pdp11b[i] = pdp18b[i]; fxwrite (pdp11b, sizeof (uint16), D18_NBSIZE, uptr->fileref); } else fxwrite (pdp18b, sizeof (uint32), D18_NBSIZE, uptr->fileref); } /* end loop buf */ } /* end else */ if (ferror (uptr->fileref)) sim_perror ("I/O error"); } uptr->WRITTEN = FALSE; /* no longer dirty */ } t_stat td_detach (UNIT* uptr) { int u = (int)(uptr - td_dev.units); if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ sim_printf ("%s%d: writing buffer to file\n", sim_dname (&td_dev), u); td_flush (uptr); } /* end if hwmark */ free (uptr->filebuf); /* release buf */ uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */ uptr->filebuf = NULL; /* clear buf ptr */ uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; /* default fmt */ uptr->capac = DT_CAPAC; /* default size */ uptr->pos = uptr->STATE = 0; sim_cancel (uptr); /* no more pulses */ return detach_unit (uptr); } /* Set mark track code into bit array */ int32 td_set_mtk (int32 code, int32 u, int32 k) { int32 i; for (i = 5; i >= 0; i--) tdb_mtk[u][k++] = (code >> i) & 1; return k; } /* Show position */ t_stat td_show_pos (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; if (uptr->pos < DT_EZLIN) /* rev end zone? */ fprintf (st, "Reverse end zone\n"); else if (uptr->pos < ((uint32) DTU_FWDEZ (uptr))) { /* data zone? */ int32 blkno = DT_LIN2BL (uptr->pos, uptr); /* block # */ int32 lineno = DT_LIN2OF (uptr->pos, uptr); /* line # within block */ fprintf (st, "Block %d, line %d, ", blkno, lineno); if (lineno < DT_HTLIN) /* header? */ fprintf (st, "header cell %d, nibble %d\n", lineno / DT_LPERMC, lineno % DT_LPERMC); else if (lineno < (DTU_LPERB (uptr) - DT_HTLIN)) /* data? */ fprintf (st, "data word %d, nibble %d\n", (lineno - DT_HTLIN) / DT_WSIZE, (lineno - DT_HTLIN) % DT_WSIZE); else fprintf (st, "trailer cell %d, nibble %d\n", (lineno - (DTU_LPERB (uptr) - DT_HTLIN)) / DT_LPERMC, (lineno - (DTU_LPERB (uptr) - DT_HTLIN)) % DT_LPERMC); } else fprintf (st, "Forward end zone\n"); /* fwd end zone */ return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | /* pdp8_tsc.c: PDP-8 ETOS timesharing option board (TSC8-75) Copyright (c) 2003-2011, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. This module is based on Bernhard Baehr's PDP-8/E simulator PDP-8/E Simulator Source Code Copyright ) 2001-2003 Bernhard Baehr TSC8iots.c - IOTs for the TSC8-75 Board plugin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA tsc TSC8-75 option board */ #include "pdp8_defs.h" extern int32 int_req; extern int32 SF; extern int32 tsc_ir; /* "ERIOT" */ extern int32 tsc_pc; /* "ERTB" */ extern int32 tsc_cdf; /* "ECDF" */ extern int32 tsc_enb; /* enable */ #define UNIT_V_SN699 (UNIT_V_UF + 0) /* SN 699 or above */ #define UNIT_SN699 (1 << UNIT_V_SN699) int32 tsc (int32 IR, int32 AC); t_stat tsc_reset (DEVICE *dptr); /* TSC data structures tsc_dev TSC device descriptor tsc_unit TSC unit descriptor tsc_reg TSC register list */ DIB tsc_dib = { DEV_TSC, 1, { &tsc } }; UNIT tsc_unit = { UDATA (NULL, UNIT_SN699, 0) }; REG tsc_reg[] = { { ORDATAD (IR, tsc_ir, 12, "most recently trapped instruction") }, { ORDATAD (PC, tsc_pc, 12, "PC of most recently trapped instruction") }, { FLDATAD (CDF, tsc_cdf, 0, "1 if trapped instruction is CDF, 0 otherwise") }, { FLDATAD (ENB, tsc_enb, 0, "interrupt enable flag") }, { FLDATAD (INT, int_req, INT_V_TSC, "interrupt pending flag") }, { NULL } }; MTAB tsc_mod[] = { { UNIT_SN699, UNIT_SN699, "ESME", "ESME", NULL }, { UNIT_SN699, 0, "no ESME", "NOESME", NULL }, { 0 } }; DEVICE tsc_dev = { "TSC", &tsc_unit, tsc_reg, tsc_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &tsc_reset, NULL, NULL, NULL, &tsc_dib, DEV_DISABLE | DEV_DIS }; /* IOT routine */ int32 tsc (int32 IR, int32 AC) { switch (IR & 07) { /* decode IR<9:11> */ case 0: /* ETDS */ tsc_enb = 0; /* disable int req */ int_req = int_req & ~INT_TSC; /* clear flag */ break; case 1: /* ESKP */ return (int_req & INT_TSC)? IOT_SKP + AC: AC; /* skip on int req */ case 2: /* ECTF */ int_req = int_req & ~INT_TSC; /* clear int req */ break; case 3: /* ECDF */ AC = AC | ((tsc_ir >> 3) & 07); /* read "ERIOT"<6:8> */ if (tsc_cdf) /* if cdf, skip */ AC = AC | IOT_SKP; tsc_cdf = 0; break; case 4: /* ERTB */ return tsc_pc; case 5: /* ESME */ if (tsc_unit.flags & UNIT_SN699) { /* enabled? */ if (tsc_cdf && ((tsc_ir & 070) >> 3) == (SF & 07)) { AC = AC | IOT_SKP; tsc_cdf = 0; } } break; case 6: /* ERIOT */ return tsc_ir; case 7: /* ETEN */ tsc_enb = 1; break; } /* end switch */ return AC; } /* Reset routine */ t_stat tsc_reset (DEVICE *dptr) { tsc_ir = 0; tsc_pc = 0; tsc_cdf = 0; tsc_enb = 0; int_req = int_req & ~INT_TSC; return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | /* pdp8_tt.c: PDP-8 console terminal simulator Copyright (c) 1993-2016, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. tti,tto KL8E terminal input/output 18-Apr-12 RMS Revised to use clock coscheduling 18-Jun-07 RMS Added UNIT_IDLE flag to console input 18-Oct-06 RMS Synced keyboard to clock 30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode 22-Nov-05 RMS Revised for new terminal processing routines 28-May-04 RMS Removed SET TTI CTRL-C 29-Dec-03 RMS Added console output backpressure support 25-Apr-03 RMS Revised for extended file support 02-Mar-02 RMS Added SET TTI CTRL-C 22-Dec-02 RMS Added break support 01-Nov-02 RMS Added 7B/8B support 04-Oct-02 RMS Added DIBs, device number support 30-May-02 RMS Widened POS to 32b 07-Sep-01 RMS Moved function prototypes */ #include "pdp8_defs.h" #include "sim_tmxr.h" #include <ctype.h> extern int32 int_req, int_enable, dev_done, stop_inst; extern int32 tmxr_poll; int32 tti (int32 IR, int32 AC); int32 tto (int32 IR, int32 AC); t_stat tti_svc (UNIT *uptr); t_stat tto_svc (UNIT *uptr); t_stat tti_reset (DEVICE *dptr); t_stat tto_reset (DEVICE *dptr); t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); /* TTI data structures tti_dev TTI device descriptor tti_unit TTI unit descriptor tti_reg TTI register list tti_mod TTI modifiers list */ DIB tti_dib = { DEV_TTI, 1, { &tti } }; UNIT tti_unit = { UDATA (&tti_svc, UNIT_IDLE|TT_MODE_KSR, 0), SERIAL_IN_WAIT }; REG tti_reg[] = { { ORDATAD (BUF, tti_unit.buf, 8, "last data item processed") }, { FLDATAD (DONE, dev_done, INT_V_TTI, "device done flag") }, { FLDATAD (ENABLE, int_enable, INT_V_TTI, "interrupt enable flag") }, { FLDATAD (INT, int_req, INT_V_TTI, "interrupt pending flag") }, { DRDATAD (POS, tti_unit.pos, T_ADDR_W, "number of characters input"), PV_LEFT }, { DRDATAD (TIME, tti_unit.wait, 24, "input polling interval (if 0, the keyboard is polled synchronously with the clock)"), PV_LEFT+REG_NZ }, { NULL } }; MTAB tti_mod[] = { { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode }, { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, { TT_MODE, TT_MODE_7P, "7b", NULL, NULL }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev, NULL }, { 0 } }; DEVICE tti_dev = { "TTI", &tti_unit, tti_reg, tti_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &tti_reset, NULL, NULL, NULL, &tti_dib, 0 }; uint32 tti_buftime; /* time input character arrived */ /* TTO data structures tto_dev TTO device descriptor tto_unit TTO unit descriptor tto_reg TTO register list */ DIB tto_dib = { DEV_TTO, 1, { &tto } }; UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_KSR, 0), SERIAL_OUT_WAIT }; REG tto_reg[] = { { ORDATAD (BUF, tto_unit.buf, 8, "last date item processed") }, { FLDATAD (DONE, dev_done, INT_V_TTO, "device done flag") }, { FLDATAD (ENABLE, int_enable, INT_V_TTO, "interrupt enable flag") }, { FLDATAD (INT, int_req, INT_V_TTO, "interrupt pending flag") }, { DRDATAD (POS, tto_unit.pos, T_ADDR_W, "number of characters output"), PV_LEFT }, { DRDATAD (TIME, tto_unit.wait, 24, "time form I/O initiation to interrupt"), PV_LEFT }, { NULL } }; MTAB tto_mod[] = { { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode }, { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, { 0 } }; DEVICE tto_dev = { "TTO", &tto_unit, tto_reg, tto_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &tto_reset, NULL, NULL, NULL, &tto_dib, 0 }; /* Terminal input: IOT routine */ int32 tti (int32 IR, int32 AC) { switch (IR & 07) { /* decode IR<9:11> */ case 0: /* KCF */ dev_done = dev_done & ~INT_TTI; /* clear flag */ int_req = int_req & ~INT_TTI; return AC; case 1: /* KSF */ return (dev_done & INT_TTI)? IOT_SKP + AC: AC; case 2: /* KCC */ dev_done = dev_done & ~INT_TTI; /* clear flag */ int_req = int_req & ~INT_TTI; return 0; /* clear AC */ case 4: /* KRS */ return (AC | tti_unit.buf); /* return buffer */ case 5: /* KIE */ if (AC & 1) int_enable = int_enable | (INT_TTI+INT_TTO); else int_enable = int_enable & ~(INT_TTI+INT_TTO); int_req = INT_UPDATE; /* update interrupts */ return AC; case 6: /* KRB */ dev_done = dev_done & ~INT_TTI; /* clear flag */ int_req = int_req & ~INT_TTI; sim_activate_abs (&tti_unit, tti_unit.wait); /* check soon for more input */ return (tti_unit.buf); /* return buffer */ default: return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ } /* Unit service */ t_stat tti_svc (UNIT *uptr) { int32 c; sim_clock_coschedule (uptr, tmxr_poll); /* continue poll */ if ((dev_done & INT_TTI) && /* prior character still pending and < 500ms? */ ((sim_os_msec () - tti_buftime) < 500)) return SCPE_OK; if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ return c; if (c & SCPE_BREAK) /* break? */ uptr->buf = 0; else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR); tti_buftime = sim_os_msec (); uptr->pos = uptr->pos + 1; dev_done = dev_done | INT_TTI; /* set done */ int_req = INT_UPDATE; /* update interrupts */ return SCPE_OK; } /* Reset routine */ t_stat tti_reset (DEVICE *dptr) { tmxr_set_console_units (&tti_unit, &tto_unit); tti_unit.buf = 0; dev_done = dev_done & ~INT_TTI; /* clear done, int */ int_req = int_req & ~INT_TTI; int_enable = int_enable | INT_TTI; /* set enable */ if (!sim_is_running) /* RESET (not CAF)? */ sim_activate (&tti_unit, tmxr_poll); return SCPE_OK; } /* Terminal output: IOT routine */ int32 tto (int32 IR, int32 AC) { switch (IR & 07) { /* decode IR<9:11> */ case 0: /* TLF */ dev_done = dev_done | INT_TTO; /* set flag */ int_req = INT_UPDATE; /* update interrupts */ return AC; case 1: /* TSF */ return (dev_done & INT_TTO)? IOT_SKP + AC: AC; case 2: /* TCF */ dev_done = dev_done & ~INT_TTO; /* clear flag */ int_req = int_req & ~INT_TTO; /* clear int req */ return AC; case 5: /* SPI */ return (int_req & (INT_TTI+INT_TTO))? IOT_SKP + AC: AC; case 6: /* TLS */ dev_done = dev_done & ~INT_TTO; /* clear flag */ int_req = int_req & ~INT_TTO; /* clear int req */ case 4: /* TPC */ sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ tto_unit.buf = AC; /* load buffer */ return AC; default: return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ } /* Unit service */ t_stat tto_svc (UNIT *uptr) { int32 c; t_stat r; c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags) | TTUF_KSR); if (c >= 0) { if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output char; error? */ sim_activate (uptr, uptr->wait); /* try again */ return ((r == SCPE_STALL)? SCPE_OK: r); /* if !stall, report */ } } dev_done = dev_done | INT_TTO; /* set done */ int_req = INT_UPDATE; /* update interrupts */ uptr->pos = uptr->pos + 1; return SCPE_OK; } /* Reset routine */ t_stat tto_reset (DEVICE *dptr) { tto_unit.buf = 0; dev_done = dev_done & ~INT_TTO; /* clear done, int */ int_req = int_req & ~INT_TTO; int_enable = int_enable | INT_TTO; /* set enable */ sim_cancel (&tto_unit); /* deactivate unit */ return SCPE_OK; } t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { tti_unit.flags = (tti_unit.flags & ~TT_MODE) | val; tto_unit.flags = (tto_unit.flags & ~TT_MODE) | val; return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 | /* pdp8_ttx.c: PDP-8 additional terminals simulator Copyright (c) 1993-2016, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. ttix,ttox PT08/KL8JA terminal input/output 18-Sep-16 RMS Expanded support to 16 terminals 11-Oct-13 RMS Poll TTIX immediately to pick up initial connect (Mark Pizzolato) 18-Apr-12 RMS Revised to use clock coscheduling 19-Nov-08 RMS Revised for common TMXR show routines 07-Jun-06 RMS Added UNIT_IDLE flag 06-Jul-06 RMS Fixed bug in DETACH routine 22-Nov-05 RMS Revised for new terminal processing routines 29-Jun-05 RMS Added SET TTOXn DISCONNECT Fixed bug in SET LOG/NOLOG 21-Jun-05 RMS Fixed bug in SHOW CONN/STATS 05-Jan-04 RMS Revised for tmxr library changes 09-May-03 RMS Added network device flag 25-Apr-03 RMS Revised for extended file support 22-Dec-02 RMS Added break support 02-Nov-02 RMS Added 7B/8B support 04-Oct-02 RMS Added DIB, device number support 22-Aug-02 RMS Updated for changes to sim_tmxr.c 06-Jan-02 RMS Added device enable/disable support 30-Dec-01 RMS Complete rebuild 30-Nov-01 RMS Added extended SET/SHOW support This module implements 1-16 individual serial interfaces similar in function to the console. These interfaces are mapped to Telnet based connections as though they were the four lines of a terminal multiplexor. The connection polling mechanism is superimposed onto the keyboard of the first interface. The done and enable flags are maintained locally, and only a master interrupt request is maintained in global register dev_done. Because this is actually an interrupt request flag, the corresponding bit in int_enable must always be set to 1. */ #include "pdp8_defs.h" #include "sim_sock.h" #include "sim_tmxr.h" #include <ctype.h> #define TTX_MAXL 16 #define TTX_INIL 4 #define TTX_GETLN(x) (((x) >> 4) & TTX_MASK) extern int32 int_req, int_enable, dev_done, stop_inst; extern int32 tmxr_poll; uint32 ttix_done = 0; /* input ready flags */ uint32 ttox_done = 0; /* output ready flags */ uint32 ttx_enbl = 0; /* intr enable flags */ uint8 ttix_buf[TTX_MAXL] = { 0 }; /* input buffers */ uint8 ttox_buf[TTX_MAXL] = { 0 }; /* output buffers */ TMLN ttx_ldsc[TTX_MAXL] = { {0} }; /* line descriptors */ TMXR ttx_desc = { TTX_INIL, 0, 0, ttx_ldsc }; /* mux descriptor */ #define ttx_lines ttx_desc.lines int32 ttix (int32 IR, int32 AC); int32 ttox (int32 IR, int32 AC); t_stat ttix_svc (UNIT *uptr); t_stat ttox_svc (UNIT *uptr); int32 ttx_getln (int32 inst); void ttx_new_flags (uint32 newi, uint32 newo, uint32 newe); t_stat ttx_reset (DEVICE *dptr); t_stat ttx_attach (UNIT *uptr, CONST char *cptr); t_stat ttx_detach (UNIT *uptr); void ttx_reset_ln (int32 i); t_stat ttx_vlines (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat ttx_show_devno (FILE *st, UNIT *uptr, int32 val, CONST void *desc); #define TTIX_SET_DONE(ln) ttx_new_flags (ttix_done | (1u << (ln)), ttox_done, ttx_enbl) #define TTIX_CLR_DONE(ln) ttx_new_flags (ttix_done & ~(1u << (ln)), ttox_done, ttx_enbl) #define TTIX_TST_DONE(ln) ((ttix_done & (1u << (ln))) != 0) #define TTOX_SET_DONE(ln) ttx_new_flags (ttix_done, ttox_done | (1u << (ln)), ttx_enbl) #define TTOX_CLR_DONE(ln) ttx_new_flags (ttix_done, ttox_done & ~(1u << (ln)), ttx_enbl) #define TTOX_TST_DONE(ln) ((ttox_done & (1u << (ln))) != 0) #define TTX_SET_ENBL(ln) ttx_new_flags (ttix_done, ttox_done, ttx_enbl | (1u << (ln))) #define TTX_CLR_ENBL(ln) ttx_new_flags (ttix_done, ttox_done, ttx_enbl & ~(1u << (ln))) #define TTX_TST_ENBL(ln) ((ttx_enbl & (1u << (ln))) != 0) /* TTIx data structures ttix_dev TTIx device descriptor ttix_unit TTIx unit descriptor ttix_reg TTIx register list ttix_mod TTIx modifiers list */ DIB_DSP ttx_dsp[TTX_MAXL * 2] = { { DEV_TTI1, &ttix }, { DEV_TTO1, &ttox }, { DEV_TTI2, &ttix }, { DEV_TTO2, &ttox }, { DEV_TTI3, &ttix }, { DEV_TTO3, &ttox }, { DEV_TTI4, &ttix }, { DEV_TTO4, &ttox }, { DEV_TTI5, &ttix }, { DEV_TTO5, &ttox }, { DEV_TTI6, &ttix }, { DEV_TTO6, &ttox }, { DEV_TTI7, &ttix }, { DEV_TTO7, &ttox }, { DEV_TTI8, &ttix }, { DEV_TTO8, &ttox }, { DEV_TTI9, &ttix }, { DEV_TTO9, &ttox }, { DEV_TTI10, &ttix }, { DEV_TTO10, &ttox }, { DEV_TTI11, &ttix }, { DEV_TTO11, &ttox }, { DEV_TTI12, &ttix }, { DEV_TTO12, &ttox }, { DEV_TTI13, &ttix }, { DEV_TTO13, &ttox }, { DEV_TTI14, &ttix }, { DEV_TTO14, &ttox }, { DEV_TTI15, &ttix }, { DEV_TTO15, &ttox }, { DEV_TTI16, &ttix }, { DEV_TTO16, &ttox } }; DIB ttx_dib = { DEV_TTI1, TTX_INIL * 2, { &ttix, &ttox }, ttx_dsp }; UNIT ttix_unit = { UDATA (&ttix_svc, UNIT_IDLE|UNIT_ATTABLE, 0), SERIAL_IN_WAIT }; REG ttix_reg[] = { { BRDATAD (BUF, ttix_buf, 8, 8, TTX_MAXL, "input buffer, lines 0 to 15") }, { ORDATAD (DONE, ttix_done, TTX_MAXL, "device done flag (line 0 rightmost)") }, { ORDATAD (ENABLE, ttx_enbl, TTX_MAXL, "interrupt enable flag") }, { FLDATA (SUMDONE, dev_done, INT_V_TTI1), REG_HRO }, { FLDATA (SUMENABLE, int_enable, INT_V_TTI1), REG_HRO }, { DRDATAD (TIME, ttix_unit.wait, 24, "initial polling interval"), REG_NZ + PV_LEFT }, { DRDATA (LINES, ttx_desc.lines, 6), REG_HRO }, { NULL } }; MTAB ttix_mod[] = { { MTAB_VDV, 0, "LINES", "LINES", &ttx_vlines, &tmxr_show_lines, (void *) &ttx_desc }, { MTAB_VDV, 0, "DEVNO", NULL, NULL, &ttx_show_devno, (void *) &ttx_desc }, { UNIT_ATT, UNIT_ATT, "SUMMARY", NULL, NULL, &tmxr_show_summ, (void *) &ttx_desc }, { MTAB_VDV, 1, NULL, "DISCONNECT", &tmxr_dscln, NULL, (void *) &ttx_desc }, { MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, NULL, &tmxr_show_cstat, (void *) &ttx_desc }, { MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, NULL, &tmxr_show_cstat, (void *) &ttx_desc }, { 0 } }; /* debugging bitmaps */ #define DBG_XMT TMXR_DBG_XMT /* display Transmitted Data */ #define DBG_RCV TMXR_DBG_RCV /* display Received Data */ #define DBG_RET TMXR_DBG_RET /* display Returned Received Data */ #define DBG_CON TMXR_DBG_CON /* display connection activities */ #define DBG_TRC TMXR_DBG_TRC /* display trace routine calls */ DEBTAB ttx_debug[] = { {"XMT", DBG_XMT, "Transmitted Data"}, {"RCV", DBG_RCV, "Received Data"}, {"RET", DBG_RET, "Returned Received Data"}, {"CON", DBG_CON, "connection activities"}, {"TRC", DBG_TRC, "trace routine calls"}, {0} }; DEVICE ttix_dev = { "TTIX", &ttix_unit, ttix_reg, ttix_mod, 1, 10, 31, 1, 8, 8, &tmxr_ex, &tmxr_dep, &ttx_reset, NULL, &ttx_attach, &ttx_detach, &ttx_dib, DEV_MUX | DEV_DISABLE | DEV_DEBUG, 0, ttx_debug }; /* TTOx data structures ttox_dev TTOx device descriptor ttox_unit TTOx unit descriptor ttox_reg TTOx register list */ UNIT ttox_unit[] = { { UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT }, { UDATA (&ttox_svc, TT_MODE_UC+UNIT_DIS, 0), SERIAL_OUT_WAIT } }; REG ttox_reg[] = { { BRDATAD (BUF, ttox_buf, 8, 8, TTX_MAXL, "last data item processed, lines 0 to 3") }, { ORDATAD (DONE, ttox_done, TTX_MAXL, "device done flag (line 0 rightmost)") }, { ORDATAD (ENABLE, ttx_enbl, TTX_MAXL, "interrupt enable flag") }, { FLDATA (SUMDONE, dev_done, INT_V_TTO1), REG_HRO }, { FLDATA (SUMENABLE, int_enable, INT_V_TTO1), REG_HRO }, { URDATAD (TIME, ttox_unit[0].wait, 10, 24, 0, TTX_MAXL, PV_LEFT, "line from I/O initiation to interrupt, lines 0 to 3") }, { NULL } }; MTAB ttox_mod[] = { { TT_MODE, TT_MODE_UC, "UC", "UC", NULL }, { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, { MTAB_VDV, 0, "DEVNO", NULL, NULL, &ttx_show_devno, &ttx_desc }, { MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT", &tmxr_dscln, NULL, &ttx_desc }, { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", &tmxr_set_log, &tmxr_show_log, &ttx_desc }, { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", &tmxr_set_nolog, NULL, &ttx_desc }, { 0 } }; DEVICE ttox_dev = { "TTOX", ttox_unit, ttox_reg, ttox_mod, TTX_MAXL, 10, 31, 1, 8, 8, NULL, NULL, &ttx_reset, NULL, NULL, NULL, NULL, DEV_DISABLE | DEV_DEBUG, 0, ttx_debug }; /* Terminal input: IOT routine */ int32 ttix (int32 inst, int32 AC) { int32 pulse = inst & 07; /* IOT pulse */ int32 ln = ttx_getln (inst); /* line # */ if (ln < 0) /* bad line #? */ return (SCPE_IERR << IOT_V_REASON) | AC; switch (pulse) { /* case IR<9:11> */ case 0: /* KCF */ TTIX_CLR_DONE (ln); /* clear flag */ break; case 1: /* KSF */ return (TTIX_TST_DONE (ln))? IOT_SKP | AC: AC; case 2: /* KCC */ TTIX_CLR_DONE (ln); /* clear flag */ sim_activate_abs (&ttix_unit, ttix_unit.wait); /* check soon for more input */ return 0; /* clear AC */ case 4: /* KRS */ return (AC | ttix_buf[ln]); /* return buf */ case 5: /* KIE */ if (AC & 1) TTX_SET_ENBL (ln); else TTX_CLR_ENBL (ln); break; case 6: /* KRB */ TTIX_CLR_DONE (ln); /* clear flag */ sim_activate_abs (&ttix_unit, ttix_unit.wait); /* check soon for more input */ return ttix_buf[ln]; /* return buf */ default: return (stop_inst << IOT_V_REASON) | AC; } /* end switch */ return AC; } /* Unit service */ t_stat ttix_svc (UNIT *uptr) { int32 ln, c, temp; if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ return SCPE_OK; sim_clock_coschedule (uptr, tmxr_poll); /* continue poll */ ln = tmxr_poll_conn (&ttx_desc); /* look for connect */ if (ln >= 0) /* got one? */ ttx_ldsc[ln].rcve = 1; /* set rcv enable */ tmxr_poll_rx (&ttx_desc); /* poll for input */ for (ln = 0; ln < ttx_lines; ln++) { /* loop thru lines */ if (ttx_ldsc[ln].conn) { /* connected? */ if (TTIX_TST_DONE (ln)) /* last char still pending? */ continue; if ((temp = tmxr_getc_ln (&ttx_ldsc[ln]))) { /* get char */ if (temp & SCPE_BREAK) /* break? */ c = 0; else c = sim_tt_inpcvt (temp, TT_GET_MODE (ttox_unit[ln].flags)); ttix_buf[ln] = c; TTIX_SET_DONE (ln); /* set flag */ } } } return SCPE_OK; } /* Terminal output: IOT routine */ int32 ttox (int32 inst, int32 AC) { int32 pulse = inst & 07; /* pulse */ int32 ln = ttx_getln (inst); /* line # */ if (ln < 0) /* bad line #? */ return (SCPE_IERR << IOT_V_REASON) | AC; switch (pulse) { /* case IR<9:11> */ case 0: /* TLF */ TTOX_SET_DONE (ln); /* set flag */ break; case 1: /* TSF */ return (TTOX_TST_DONE (ln))? IOT_SKP | AC: AC; case 2: /* TCF */ TTOX_CLR_DONE (ln); /* clear flag */ break; case 5: /* SPI */ if ((TTIX_TST_DONE (ln) || TTOX_TST_DONE (ln)) /* either done set */ && TTX_TST_ENBL (ln)) /* and enabled? */ return IOT_SKP | AC; return AC; case 6: /* TLS */ TTOX_CLR_DONE (ln); /* clear flag */ case 4: /* TPC */ sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate */ ttox_buf[ln] = AC & 0377; /* load buffer */ break; default: return (stop_inst << IOT_V_REASON) | AC; } /* end switch */ return AC; } /* Unit service */ t_stat ttox_svc (UNIT *uptr) { int32 c, ln = uptr - ttox_unit; /* line # */ if (ttx_ldsc[ln].conn) { /* connected? */ if (ttx_ldsc[ln].xmte) { /* tx enabled? */ TMLN *lp = &ttx_ldsc[ln]; /* get line */ c = sim_tt_outcvt (ttox_buf[ln], TT_GET_MODE (ttox_unit[ln].flags)); if (c >= 0) /* output char */ tmxr_putc_ln (lp, c); tmxr_poll_tx (&ttx_desc); /* poll xmt */ } else { tmxr_poll_tx (&ttx_desc); /* poll xmt */ sim_activate (uptr, ttox_unit[ln].wait); /* wait */ return SCPE_OK; } } TTOX_SET_DONE (ln); /* set done */ return SCPE_OK; } /* Flag routine Global dev_done is used as a master interrupt; therefore, global int_enable must always be set */ void ttx_new_flags (uint32 newidone, uint32 newodone, uint32 newenbl) { ttix_done = newidone; ttox_done = newodone; ttx_enbl = newenbl; if ((ttix_done & ttx_enbl) != 0) dev_done |= INT_TTI1; else dev_done &= ~INT_TTI1; if ((ttox_done & ttx_enbl) != 0) dev_done |= INT_TTO1; else dev_done &= ~INT_TTO1; int_enable |= (INT_TTI1 | INT_TTO1); int_req = INT_UPDATE; return; } /* Compute relative line number, based on table of device numbers */ int32 ttx_getln (int32 inst) { int32 i; int32 device = (inst >> 3) & 077; /* device = IR<3:8> */ for (i = 0; i < (ttx_lines * 2); i++) { /* loop thru disp tbl */ if (device == ttx_dsp[i].dev) /* dev # match? */ return (i >> 1); /* return line # */ } return -1; } /* Reset routine */ t_stat ttx_reset (DEVICE *dptr) { int32 ln; if (dptr->flags & DEV_DIS) { /* sync enables */ ttix_dev.flags |= DEV_DIS; ttox_dev.flags |= DEV_DIS; } else { ttix_dev.flags &= ~DEV_DIS; ttox_dev.flags &= ~DEV_DIS; } if (ttix_unit.flags & UNIT_ATT) /* if attached, */ sim_activate (&ttix_unit, tmxr_poll); /* activate */ else sim_cancel (&ttix_unit); /* else stop */ for (ln = 0; ln < TTX_MAXL; ln++) /* for all lines */ ttx_reset_ln (ln); /* reset line */ int_enable |= (INT_TTI1 | INT_TTO1); /* set master enable */ return SCPE_OK; } /* Reset line n */ void ttx_reset_ln (int32 ln) { uint32 mask = (1u << ln); ttix_buf[ln] = 0; /* clr buf */ ttox_buf[ln] = 0; /* clr done, set enbl */ ttx_new_flags (ttix_done & ~mask, ttox_done & ~mask, ttx_enbl | mask); sim_cancel (&ttox_unit[ln]); /* stop output */ return; } /* Attach master unit */ t_stat ttx_attach (UNIT *uptr, CONST char *cptr) { t_stat r; r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */ if (r != SCPE_OK) /* error */ return r; sim_activate (uptr, 0); /* start poll at once */ return SCPE_OK; } /* Detach master unit */ t_stat ttx_detach (UNIT *uptr) { int32 i; t_stat r; r = tmxr_detach (&ttx_desc, uptr); /* detach */ for (i = 0; i < TTX_MAXL; i++) /* all lines, */ ttx_ldsc[i].rcve = 0; /* disable rcv */ sim_cancel (uptr); /* stop poll */ return r; } /* Change number of lines */ t_stat ttx_vlines (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int32 newln, i, t; t_stat r; if (cptr == NULL) return SCPE_ARG; newln = get_uint (cptr, 10, TTX_MAXL, &r); if ((r != SCPE_OK) || (newln == ttx_lines)) return r; if (newln == 0) return SCPE_ARG; if (newln < ttx_lines) { for (i = newln, t = 0; i < ttx_lines; i++) t = t | ttx_ldsc[i].conn; if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) return SCPE_OK; for (i = newln; i < ttx_lines; i++) { if (ttx_ldsc[i].conn) { tmxr_linemsg (&ttx_ldsc[i], "\r\nOperator disconnected line\r\n"); tmxr_reset_ln (&ttx_ldsc[i]); /* reset line */ } ttox_unit[i].flags |= UNIT_DIS; ttx_reset_ln (i); } } else { for (i = ttx_lines; i < newln; i++) { ttox_unit[i].flags &= ~UNIT_DIS; ttx_reset_ln (i); } } ttx_lines = newln; ttx_dib.num = newln * 2; return SCPE_OK; } /* Show device numbers */ t_stat ttx_show_devno (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { int32 i, dev_offset; DEVICE *dptr; if (uptr == NULL) return SCPE_IERR; dptr = find_dev_from_unit (uptr); if (dptr == NULL) return SCPE_IERR; /* Select correct devno entry for Input or Output device */ if (dptr->name[2] == 'O') dev_offset = 1; else dev_offset = 0; fprintf(st, "devno="); for (i = 0; i < ttx_lines; i++) { fprintf(st, "%02o%s", ttx_dsp[i*2+dev_offset].dev, i < ttx_lines-1 ? "," : ""); } return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 | /* pidp8i.c: PiDP-8/I additions to the PDP-8 simulator Copyright © 2015-2017 by Oscar Vermeulen, Ian Schofield, and Warren Young Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the names of the authors above shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from those authors. */ #include "pidp8i.h" #include "../gpio-common.h" #include <assert.h> #include <dirent.h> // for USB stick searching //// MODULE GLOBALS //////////////////////////////////////////////////// // handle_sing_step() sets this to nonzero and returns a value breaking // us out of the PDP-8 simulator's sim_instr() loop, which causes SCP to // call our build_pidp8i_scp_cmd(), which gives SCP a command to run: // either "exit" when it wants the simulator to stop (e.g the shutdown // and reboot combos) or "do $script" on IF + SING_STEP combo. // // We loop the flow control from this module out into the generic SIMH // code and then back in here so we don't have to export this global. // Basically, this module global lets us remember what handle_sing_step // wants SCP to do in the window between switch handling time and SCP // command handling time. static enum { CMD_NONE = 0, // "do nothing" idle case CMD_DO_BOOTSCRIPT_1, // SING_STEP + IF combos CMD_DO_BOOTSCRIPT_2, CMD_DO_BOOTSCRIPT_3, CMD_DO_BOOTSCRIPT_4, CMD_DO_BOOTSCRIPT_5, CMD_DO_BOOTSCRIPT_6, CMD_DO_BOOTSCRIPT_7, CMD_EXIT, } insert_scp_cmd = CMD_NONE; //// build_pidp8i_scp_cmd ////////////////////////////////////////////// // If insert_scp_cmd is nonzero, we return the corresponding SCP command // we want run to make the simulator do something else. char *build_pidp8i_scp_cmd (char *cbuf, size_t cbufsize) { if (insert_scp_cmd == CMD_NONE) { return 0; // nothing to do yet } else if ((insert_scp_cmd > 0) && (insert_scp_cmd <= 7)) { // We got one of the IF + SING_STEP combos, so restart the // simulator with the corresponding init script. char path[256]; snprintf (path, sizeof (path), "@BOOTDIR@/%d.script", insert_scp_cmd); insert_scp_cmd = CMD_NONE; // it's a one-shot if (access(path, R_OK) == 0) { snprintf (cbuf, cbufsize, "do %s", path); return cbuf; } else { // That boot script doesn't exist or isn't readable. // // Fall through to the "exit" command builder below because // we don't want to keep coming back in here at host CPU // speed, failing the same way and issuing the same error // until the slow human manages to flip the offending switch // back. This is especially annoying when the PiDP-8/I is // attached to a slow serial console. Ask me how I know. int access_errno = errno; // preserve it from getcwd() char cwd[256]; getcwd (cwd, sizeof (cwd)); printf ("Cannot read %s from %s: %s!\n", path, cwd, strerror (access_errno)); } } else if (insert_scp_cmd > CMD_EXIT) { printf ("Invalid PiDP-8/I SCP command value %d given!\n", insert_scp_cmd); } else { // C doesn't require that "if" statements handle all cases // statically, so do a runtime check to make sure we have // exhausted all the other cases above. // // We can get in here by means other than programmer error in // modifying the enum: some C compilers allow signed values // to be assigned to enums, so we could get in here on negative // values. We can't test for that above because one of the C // compilers we build under (clang on macOS 10.12+) won't allow // that short of nasty low-level hackery, so it complains if we // test for negative values, claiming it can never happen. assert (insert_scp_cmd == CMD_EXIT); } // If we get here, we got a nonzero command value but didn't get // into the happy path above, so die. return strncpy (cbuf, "exit", cbufsize); } //// set_pidp8i_led //////////////////////////////////////////////////// // Sets the current state for a single LED at the given row and column // on the PiDP-8/I PCB. Also increments the LED on-count value for // that LED. // // You may say, "You can't just use the C postincrement operator here! // Look at the assembly output! You must use an atomic increment for // this!" And indeed, there is a big difference between the two // methods: https://godbolt.org/g/0Qt0Ap // // The thing is, both structures referred to by pdis_* are fixed in RAM, // and the two threads involved are arranged in a strict producer-and- // consumer fashion, so it doesn't actually matter if pdis_update gets // swapped for pdis_paint while we're halfway through an increment: we // get a copy of the pointer to dereference here, so we'll finish our // increment within the same structure we started with, even if // pdis_update points at the other display structure before we leave. static inline void set_pidp8i_led (display *pd, size_t row, size_t col) { ++pd->on[row][col]; pd->curr[row] |= 1 << col; } //// set_pidp8i_row_leds /////////////////////////////////////////////// // Like set_pidp8i_led, except that it takes a 12-bit state value for // setting all LEDs on the given row. Because we copy the pdis_update // pointer before making changes, if the display swap happens while // we're working, we'll simply finish updating what has become the // paint-from display, which is what you want; you don't want the // updates spread over both displays. static inline void set_pidp8i_row_leds (display *pd, size_t row, uint16 state) { size_t *prow = pd->on[row]; pd->curr[row] = state; for (size_t col = 0, mask = 1; col < NCOLS; ++col, mask <<= 1) { if (state & mask) ++prow[col]; } } //// set_3_pidp8i_leds ///////////////////////////////////////////////// // Special case of set_pidp8i_row_leds for the DF and IF LEDs: we only // pay attention to bits 12, 13, and 14 of the given state value, // because SIMH's PDP-8 simulator shifts those 3 bits up there so it can // simply OR these 3-bit registers with PC to produce a 15-bit extended // address. // // We don't take a row parameter because we know which row they're on, // but we do take a column parameter so we can generalize for IF & DF. static inline void set_3_pidp8i_leds (display *pd, size_t col, uint16 state) { static const int row = 7; // DF and IF are on row 6 size_t *prow = pd->on[row]; size_t last_col = col + 3; pd->curr[row] |= state >> (12 - col); for (size_t mask = 1 << 12; col < last_col; ++col, mask <<= 1) { if (state & mask) ++prow[col]; } } //// set_5_pidp8i_leds ///////////////////////////////////////////////// // Like set_3... but for the 5-bit SC register. Because it's only used // for that purpose, we don't need the col parameter. static inline void set_5_pidp8i_leds (display *pd, uint16 state) { static const int row = 6; // SC is on row 6 size_t *prow = pd->on[row]; size_t last_col = 7; pd->curr[row] |= (state & 0x1f) << 2; for (size_t col = 2, mask = 1; col < last_col; ++col, mask <<= 1) { if (state & mask) ++prow[col]; } } //// get_pidp8i_initial_max_skips ////////////////////////////////////// // Return the number of times we should skip updating the front panel // LEDs the first time thru, to give the simulator time to settle. // If we don't do this, the front panel LEDs can start out dim and // slowly rise or they can overshoot and then take a while to recover // with the IPS. size_t get_pidp8i_initial_max_skips (size_t updates_per_sec) { DEVICE *pthrot = find_dev ("INT-THROTTLE"); if (pthrot) { REG *ptyper = find_reg ("THROT_TYPE", NULL, pthrot); REG *pvalr = find_reg ("THROT_VAL", NULL, pthrot); if (ptyper && pvalr) { uint32 *ptype = ptyper->loc; uint32 *pval = pvalr->loc; size_t ips = 0; switch (*ptype) { case SIM_THROT_MCYC: ips = *pval * 1e6; break; case SIM_THROT_KCYC: ips = *pval * 1e3; break; } if (ips) { printf("PiDP-8/I initial throttle = %zu IPS\r\n", ips); return ips / updates_per_sec; } } } // No better idea, so give a plausible value for an unthrottled Pi 1 return 200; } //// set_pidp8i_leds /////////////////////////////////////////////////// // Given all of the PDP-8's internal registers that affect the front // panel display, modify the GPIO thread's LED state values accordingly. // // Also update the LED brightness values based on those new states. void set_pidp8i_leds (uint32 sPC, uint32 sMA, uint16 sMB, uint16 sIR, int32 sLAC, int32 sMQ, int32 sIF, int32 sDF, int32 sSC, int32 int_req, int Pause) { // Bump the instruction count. This should always be equal to the // Fetch LED's value, but integers are too cheap to get cute here. // // Note that we only update pdis_update directly once in this whole // process. This is in case the display swap happens while we're // working: we want to finish work on the same display even though // it's now called the paint-from display, so it's consistent. display* pd = pdis_update; ++pd->inst_count; // Rows 0-4, easy cases: single-register LED strings set_pidp8i_row_leds (pd, 0, sPC); set_pidp8i_row_leds (pd, 1, sMA); set_pidp8i_row_leds (pd, 2, sMB); set_pidp8i_row_leds (pd, 3, sLAC & 07777); set_pidp8i_row_leds (pd, 4, sMQ); #if 0 // debugging static time_t last = 0, now; if (time(&now) != last) { uint16* pcurr = pd->curr; printf("\r\nSET: [PC:%04o] [MA:%04o] [MB:%04o] [AC:%04o] [MQ:%04o]", pcurr[0], pcurr[1], pcurr[2], pcurr[3], pcurr[4]); last = now; } #endif // Row 5a: instruction type column, decoded from high octal // digit of IR value pd->curr[5] = 0; uint16 inst_type = sIR & 07000; switch (inst_type) { case 00000: set_pidp8i_led (pd, 5, 11); break; // 000 AND case 01000: set_pidp8i_led (pd, 5, 10); break; // 001 TAD case 02000: set_pidp8i_led (pd, 5, 9); break; // 010 DCA case 03000: set_pidp8i_led (pd, 5, 8); break; // 011 ISZ case 04000: set_pidp8i_led (pd, 5, 7); break; // 100 JMS case 05000: set_pidp8i_led (pd, 5, 6); break; // 101 JMP case 06000: set_pidp8i_led (pd, 5, 5); break; // 110 IOT case 07000: set_pidp8i_led (pd, 5, 4); break; // 111 OPR 1 & 2 } // Row 5b: set the Defer LED if... if ((inst_type <= 05000) && // it's a memory reference instruction (sIR & 00400)) { // and indirect addressing flag is set set_pidp8i_led (pd, 5, 1); } // Row 5c: The Fetch LED is bumped once per CPU instruction, as is // Execute while we're not in STOP state. They're set at different // times, but they're twiddled so rapidly that they both just become // a 50% blur in normal operation, so we don't make the CPU core set // these "on-time." It just doesn't matter. extern int swStop, swSingInst; int running = !swStop && !swSingInst; if (running) set_pidp8i_led (pd, 5, 2); // Execute set_pidp8i_led (pd, 5, 3); // Fetch // Row 6a: Remaining LEDs in upper right block pd->curr[6] = 0; if (running) set_pidp8i_led (pd, 6, 7); // bump Run LED if (Pause) set_pidp8i_led (pd, 6, 8); // bump Pause LED if (int_req & INT_ION) set_pidp8i_led (pd, 6, 9); // bump ION LED // Row 6b: The Step Count LEDs are also on row 6 set_5_pidp8i_leds (pd, sSC); // Row 7: DF, IF, and Link. pd->curr[7] = 0; set_3_pidp8i_leds (pd, 9, sDF); set_3_pidp8i_leds (pd, 6, sIF); if (sLAC & 010000) set_pidp8i_led (pd, 7, 5); // If we're stopped or single-stepped, the display-swapping code // won't happen, so copy the above over to the paint-from version. extern int resumeFromInstructionLoopExit; if (!running || resumeFromInstructionLoopExit) { memcpy(pdis_paint, pdis_update, sizeof(struct display)); } } //// mount_usb_stick_file ////////////////////////////////////////////// // Search for a PDP-8 media image in one of the Pi's USB auto-mount // directories and attempt to ATTACH it to the simulator. static void mount_usb_stick_file (int devNo, char *devCode) { char sFoundFile[CBUFSIZE] = { '\0' }; char sUSBPath[CBUFSIZE]; // will be "/media/usb0" etc char fileExtension[4]; // will be ".RX" etc int i, j; // Build expected file name extension from the first two characters of // the passed-in device code. fileExtension[0] = '.'; // extension starts with a . strncpy (fileExtension + 1, devCode, 2); // extension is PT, RX, RL etc fileExtension[3] = '\0'; // chop off device number #if 0 // debugging printf("\r\nMOUNT USB: [DEV:%d] [CODE:%s], [EXT:%s]", devNo, devCode, fileExtension); #endif // Forget the prior file attached to this PDP-8 device. The only reason // we keep track is so we don't have the same media image file attached // to both devices of a given type we support. That is, you can't have // a given floppy image file attached to both RX01 drives, but you *can* // repeatedly re-ATTACH the same floppy image to the first RX01 drive. static char mountedFiles[8][CBUFSIZE]; mountedFiles[devNo][0] = '\0'; for (i = 0; i < 8 && sFoundFile[0] == '\0'; ++i) { // search all 8 USB mount points, numbered 0-7 snprintf (sUSBPath, sizeof (sUSBPath), "/media/usb%d", i); DIR *pDir = opendir (sUSBPath); if (pDir) { struct dirent* pDirent; while ((pDirent = readdir (pDir)) != 0) { // search all files in directory if (pDirent->d_name[0] == '.') continue; // dotfiles clutter debug output char* pext = strstr (pDirent->d_name, fileExtension); if (pext && (pext == (pDirent->d_name + strlen (pDirent->d_name) - 3))) { snprintf (sFoundFile, sizeof (sFoundFile), "%s/%s", sUSBPath, pDirent->d_name); #if 0 // debugging printf("\r\nFound candidate file %s for dev %s, ext *%s...", sFoundFile, devCode, fileExtension); #endif for (j = 0; j < 7; ++j) { if (strncmp (mountedFiles[j], sFoundFile, CBUFSIZE) == 0) { #if 0 // debugging printf("\r\nAlready have %s mounted, slot %d; will not remount.", sFoundFile, j); #endif sFoundFile[0] = '\0'; // don't leave outer loop; keep looking break; } } if (j == 7) { // Media image file is not already mounted, so leave while // loop with path set to mount it break; } } #if 0 // debugging else { printf("\r\nFile %s on %s doesn't match *%s...", pDirent->d_name, sUSBPath, fileExtension); } #endif } closedir (pDir); } else { // Not a Pi or the USB auto-mounting software isn't installed printf ("\r\nCannot open %s: %s\r\n", sUSBPath, strerror (errno)); return; } } if (sFoundFile[0]) { // no file found, exit if (access (sFoundFile, R_OK) == 0) { char sAttachCmd[CBUFSIZE] = { '\0' }; snprintf (sAttachCmd, sizeof(sAttachCmd), "%s %s", devCode, sFoundFile); t_stat scpCode = attach_cmd ((int32) 0, sAttachCmd); if (scpCode == SCPE_OK) { // add file to mount list strncpy (mountedFiles[devNo], sFoundFile, CBUFSIZE); printf ("\r\nMounted %s %s\r\n", devCode, mountedFiles[devNo]); } else { // SIMH ATTACH command failed printf ("\r\nSIMH error mounting %s on %s: %s\r\n", sFoundFile, devCode, sim_error_text (scpCode)); } } else { printf ("\r\nCannot read medium image %s from USB: %s\r\n", sFoundFile, strerror (errno)); } } else { printf ("\r\nNo unmounted %s file found\r\n", devCode); } } //// handle_sing_step ////////////////////////////////////////////////// // Handle SING_STEP combinations as nonstandard functions with respect // to a real PDP-8, since SIMH doesn't try to emulate the PDP-8's // single-stepping mode — not to be confused with single-instruction // mode, which SIMH *does* emulate — so the SING_STEP switch is free // for our nonstandard uses. // // This is separate from handle_flow_control_switches only because // there are so many cases here that it would obscure the overall flow // of our calling function to do all this there. static pidp8i_flow_t handle_sing_step (int closed) { // If SING_STEP is open, we do nothing here except reset the single-shot // flag if it was set. static int single_shot = 0; if (!closed) { single_shot = 0; return pft_normal; } // There are two sets of SING_STEP combos: first up are those where the // other switches involved have to be set already, and the function is // triggered as soon as SING_STEP closes. These are functions we don't // want re-executing repeatedly while SING_STEP remains closed. if (single_shot == 0) { // SING_STEP switch was open last we knew, and now it's closed, so // set the single-shot flag. single_shot = 1; // 1. Convert DF switch values to a device number, which // we will map to a PDP-8 device type, then attempt to // ATTACH some unmounted medium from USB to that device // // We treat DF == 0 as nothing to mount, since we use // SING_STEP for other things, so we need a way to // decide which meaning of SING_STEP to take here. // // The shift by 9 is how many non-DF bits are below // DF in switchstatus[1] // // The bit complement is because closed DF switches show // as 0, because they're dragging the pull-up down, but // we want those treated as 1s, and vice versa. uint16_t css1 = ~switchstatus[1]; int swDevice = (css1 & SS1_DF_ALL) >> 9; if (swDevice) { char swDevCode[4] = { '\0' }; switch (swDevice) { case 1: strcpy (swDevCode, "ptr"); break; // PTR paper tape reader case 2: strcpy (swDevCode, "ptp"); break; // High speed paper tape punch case 3: strcpy (swDevCode, "dt0"); break; // TC08 DECtape (#8 is first!) case 4: strcpy (swDevCode, "dt1"); break; case 5: strcpy (swDevCode, "rx0"); break; // RX8E (8/e peripheral!) case 6: strcpy (swDevCode, "rx1"); break; case 7: strcpy (swDevCode, "rk1"); break; // second RK05 disk pack } if (swDevCode[0]) mount_usb_stick_file (swDevice, swDevCode); } // 2. Do the same with IF, except that the switch value // is used to decide which boot script to restart with via // SIMH's DO command. // // The shift value of 6 is because the IF switches are 3 // down from the DF switches above. int swScript = (css1 & SS1_IF_ALL) >> 6; if (swScript) { printf ("\r\n\nRestarting with IF == %d...\r\n\r\n", swScript); insert_scp_cmd = swScript; return pft_halt; } } // end if single-shot flag clear else { // Now handle the second set of SING_STEP special-function // combos, being those where the switches can be pressed in any // order, so that we take action when the last one of the set // closes, no matter which one that is. These immediately exit // the SIMH instruction interpreter, so they won't re-execute // merely because the human isn't fast enough to lift his finger // by the time the next iteration of that loop starts. // 3. Scan for host poweroff command (Sing_Step + Sing_Inst + Stop) if ((switchstatus[2] & (SS2_S_INST | SS2_STOP)) == 0) { printf ("\r\nShutdown\r\n\r\n"); insert_scp_cmd = CMD_EXIT; if (spawn_cmd (0, "sudo /bin/systemctl poweroff") != SCPE_OK) { printf ("\r\n\r\npoweroff failed\r\n\r\n"); } return pft_halt; } // 4. Scan for host reboot command (Sing_Step + Sing_Inst + Start) if ((switchstatus[2] & (SS2_S_INST | SS2_START)) == 0) { printf ("\r\nReboot\r\n\r\n"); insert_scp_cmd = CMD_EXIT; if (spawn_cmd (0, "sudo /bin/systemctl reboot") != SCPE_OK) { printf ("\r\n\r\nreboot failed\r\n\r\n"); } return pft_halt; } #if 0 // These combos once meant something, but no longer do. If you // reassign them, think carefully whether they should continue to // be handled here and not above in the "if" branch. If nothing // prevents your function from being re-executed while SING_STEP // remains closed and re-execution would be bad, move the test // under the aegis of the single_shot flag. // 5. Sing_Step + Sing_Inst + Load Add if ((switchstatus[2] & (SS2_S_INST | SS2_L_ADD)) == 0) { } // 6. Sing_Step + Sing_Inst + Deposit if ((switchstatus[2] & (SS2_S_INST | SS2_DEP)) == 0) { } #endif } return pft_normal; } //// handle_flow_control_switches ////////////////////////////////////// // Process all of the PiDP-8/I front panel switches that can affect the // flow path of the PDP-8 simulator's instruction interpretation loop, // returning a code telling the simulator our decision. // // The simulator passes in pointers to PDP-8 registers we may modify as // a side effect of handling these switches. pidp8i_flow_t handle_flow_control_switches (uint16* pM, uint32 *pPC, uint32 *pMA, int32 *pMB, int32 *pLAC, int32 *pIF, int32 *pDF, int32* pint_req) { // Exit early if the blink thread has not attached itself to the GPIO // peripheral in the Pi, since that means we cannot safely interpret the // data in the switchstatus array. This is especially important on // non-Pi hosts, since switchstatus will remain zeroed, which we would // interpret as "all switches are pressed!", causing havoc. // // It would be cheaper for our caller to check this for us and skip the // call, but there's no good reason to expose such implementations // details to it. We're trying to keep the PDP-8 simulator's CPU core // as free of PiDP-8/I details as is practical. if (!pidp8i_gpio_present) return pft_normal; // Handle the nonstandard SING_STEP + X combos, some of which halt // the processor. if (handle_sing_step ((switchstatus[2] & SS2_S_STEP) == 0) == pft_halt) { return pft_halt; } // Check for SING_INST switch close... extern int swSingInst; if (((switchstatus[2] & SS2_S_INST) == 0) && (swSingInst == 0)) { // Put the processor in single-instruction mode until we get a // CONT or START switch closure. Technically this is wrong // according to DEC's docs: we're supposed to finish executing // the next instruction before we "clear the RUN flip-flop" in // DEC terms, whereas we're testing these switches before we // fetch the next instruction. Show me how it matters, and // I'll fix it. :) swSingInst = 1; } // ...and SING_INST switch open extern int swStop; if (swSingInst && (switchstatus[2] & SS2_S_INST)) { swSingInst = 0; swStop = 1; // still stopped on leaving SING_INST mode } // Check for START switch press... static int swStart = 0; if (((switchstatus[2] & SS2_START) == 0) && (swStart == 0)) { // Reset the CPU. extern DEVICE cpu_dev; extern t_stat cpu_reset (DEVICE *); cpu_reset (&cpu_dev); // DEC's docs say there are a few additional things START does // that cpu_reset() doesn't do for us. // // Don't need to do anything with MA and IR, as SIMH does that // shortly after this function returns. *pLAC = *pMB = 0; // cpu_reset() does its thing to the saved_* register copies // in a few cases, but we need it to happen to the "real" // registers instead, since our STOP/START behavior doesn't // make use of saved_*. REG* pibr = find_reg ("IB", NULL, &cpu_dev); int32* pIB = pibr ? pibr->loc : 0 /* force segfault on err */ ; *pIB = *pIF; // Reset our switch flags, too swStop = 0; // START cancels STOP mode swSingInst = 0; // allow SING INST mode re-entry swStart = 1; // make it single-shot #if 0 // debugging printf("\r\nSTART: [DF:%o] [IF:%o] [IB:%o] [PC:%04o] " "[MA:%04o] [MB:%04o] [L:%d] [AC:%04o]", (*pDF >> 12), (*pIF >> 12), (*pIB >> 12), (*pPC & 07777), *pMA, *pMB, !!(*pLAC & 010000), *pLAC & 07777); #endif } // ...and START switch release if (swStart && (switchstatus[2] & SS2_START)) { swStart = 0; } // Check for CONT switch press... static int swCont = 0; extern int resumeFromInstructionLoopExit; if ((((switchstatus[2] & SS2_CONT) == 0) && (swCont == 0)) || resumeFromInstructionLoopExit) { // The initial CONT press is special: how we handle it // depends on the processor's state. // // FIXME: Are we handling MB correctly? [973271ae36] swCont = 1; // make it single-shot resumeFromInstructionLoopExit = 0; if (swSingInst) { // On the initial CONT press while in SING_INST mode, run // one instruction only. return pft_normal; } else if (swStop) { // We were HLTed or STOPped, so CONT returns us to // free-running mode. swStop = 0; #if 0 // debugging printf("\r\nCONT: [DF:%o] [IF:%o] [PC:%04o] " "[MA:%04o] [MB:%04o] [L:%d] [AC:%04o]", (*pDF >> 12), (*pIF >> 12), (*pPC & 07777), *pMA, *pMB, !!(*pLAC & 010000), *pLAC & 07777); #endif } // else, CONT has no effect in this state } // ...and CONT switch release if (swCont && (switchstatus[2] & SS2_CONT)) { swCont = 0; } // Check for LOAD_ADD switch press. The only reason we bother // making it single-shot is in case debugging is enabled. // Otherwise, it matters not how long the slow human holds this // swithc down, and thus how often we apply the values: all else // but our printf() here is idempotent. static int swLAdd = 0; if ((swLAdd == 0) && (switchstatus[2] & SS2_L_ADD) == 0) { // Copy SR into PC. Have to flip the bits because GPIO gives // 0 for a closed switch and 1 for open, opposite what we want. *pPC = (~switchstatus[0]) & 07777; // Copy DF switch settings to DF register // // The shift is because the DF positions inside the switchstatus[1] // register happen to be 3 bit positions off of where we want them // in DF here: we want to be able to logically OR PC and DF to make // 15-bit data access addresses. // // We complement the bits here for the same reason we did above uint16_t css1 = ~switchstatus[1]; *pDF = (css1 & SS1_DF_ALL) << 3; // Do the same for IF. The only difference comes from the fact // that IF is the next 3 bits down in switchstatus[1]. *pIF = (css1 & SS1_IF_ALL) << 6; #if 0 // debugging printf("\r\nL_ADD: [DF:%o] [IF:%o] [PC:%04o] " "[MA:%04o] [MB:%04o] [L:%d] [AC:%04o]", (*pDF >> 12), (*pIF >> 12), (*pPC & 07777), *pMA, *pMB, !!(*pLAC & 010000), *pLAC & 07777); #endif swLAdd = 1; // make it single-shot } // ...and L_ADD switch release if (swLAdd && (switchstatus[2] & SS2_L_ADD)) { swLAdd = 0; } // Check for DEP switch press... static int swDep = 0; if (((switchstatus[2] & SS2_DEP) == 0) && (swDep == 0)) { uint16 sSR = (~switchstatus[0]) & 07777; // bit flip justified above *pPC = *pPC & 07777; // sometimes high bits get set; squish 'em #if 0 // debugging printf("\r\nDEP: [IF:%o] [PC:%04o] [SR:%04o]", (*pIF >> 12), *pPC, sSR); #endif /* ??? in 66 handbook: strictly speaking, SR goes into AC, then AC into MB. Does it clear AC afterwards? If not, needs fix */ pM[*pPC] = sSR; // FIXME: shouldn't we use IF/DF here? *pMB = sSR; *pMA = *pPC & 07777; // MA trails PC on FP; FIXME: OR in IF? *pPC = (*pPC + 1) & 07777; // increment PC swDep = 1; // make it single-shot } // ...and DEP switch release if (swDep && (switchstatus[2] & SS2_DEP)) { swDep = 0; } // Check for EXAM switch press... static int swExam = 0; if (((switchstatus[2] & SS2_EXAM) == 0) && (swExam == 0)) { *pMB = pM[*pPC]; *pMA = *pPC & 07777; // MA trails PC on FP *pPC = (*pPC + 1) & 07777; // increment PC swExam = 1; // make it single-shot } // ...and EXAM switch release if (swExam && (switchstatus[2] & SS2_EXAM)) { swExam = 0; } // Check for STOP switch press. No "and release" because we get out of // STOP mode with START or CONT, not by releasing STOP, and while in // STOP mode, this switch's function is idempotent. if (!swStop && ((switchstatus[2] & SS2_STOP) == 0)) { swStop = 1; #if 0 // debugging printf("\r\nSTOP: [DF:%o] [IF:%o] [PC:%04o] " "[MA:%04o] [MB:%04o] [L:%d] [AC:%04o]", (*pDF >> 12), (*pIF >> 12), (*pPC & 07777), *pMA, *pMB, !!(*pLAC & 010000), *pLAC & 07777); #endif } // If any of the above put us into STOP or SING_INST mode, go no // further. In particular, fetch no more instructions, and do not // touch PC! The only way to get un-stuck is CONT or STOP. return (swStop || swSingInst) ? pft_stop : pft_normal; } //// get_switch_register /////////////////////////////////////////////// // Return the current contents of the switch register int32 get_switch_register (void) { return switchstatus[0] ^ 07777; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | /* pidp8i.h: Interface between PiDP-8/I additions and the stock SIMH PDP-8 simulator Copyright © 2015-2017 by Oscar Vermeulen and Warren Young Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the names of the authors above shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from those authors. */ #if !defined(PIDP8I_H) #define PIDP8I_H #include "pdp8_defs.h" typedef enum { pft_normal, pft_halt, pft_stop, } pidp8i_flow_t; extern char *build_pidp8i_scp_cmd (char* cbuf, size_t cbufsize); extern int32 get_switch_register (void); extern size_t get_pidp8i_initial_max_skips (size_t updates_per_sec); extern pidp8i_flow_t handle_flow_control_switches (uint16* pM, uint32 *pPC, uint32 *pMA, int32 *pMB, int32 *pLAC, int32 *pIF, int32 *pDF, int32* pint_req); extern void set_pidp8i_leds (uint32 sPC, uint32 sMA, uint16 sMB, uint16 sIR, int32 sLAC, int32 sMQ, int32 sIF, int32 sDF, int32 sSC, int32 int_req, int Pause); #endif // !defined(PIDP8I_H) |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 | /* * gpio-common.c: functions common to both gpio.c and gpio-nls.c * * Copyright © 2015-2017 Oscar Vermeulen and Warren Young * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the names of the authors above shall * not be used in advertising or otherwise to promote the sale, use or other * dealings in this Software without prior written authorization from those * authors. * * www.obsolescenceguaranteed.blogspot.com * * This is part of the GPIO thread, which communicates with the * simulator's main thread via *pdis_update and switchstatus[]. * All of this module's other external interfaces are only called * by the other gpio-* modules, from the GPIO thread. */ #include "gpio-common.h" #include "config.h" #include "PDP8/pidp8i.h" #include <pthread.h> #include <sys/file.h> #include <sys/time.h> #include <ctype.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef HAVE_TIME_H # include <time.h> #endif #define BLOCK_SIZE (4*1024) //// GLOBALS /////////////////////////////////////////////////////////// // Flag set after we successfully init the GPIO mechanism. While this // is false, the rest of the code knows not to expect useful values for // LED and switch states. It is also useful as a cross-thread signal, // since merely starting the blink() thread doesn't tell you whether it // managed to lock the GPIO device. uint8_t pidp8i_gpio_present; // Flag external programs can set to make us use the old-style (and // simpler, hence still supported) ledstatus[] interface for updating // the LED values when swapping displays internally. The external // program doesn't need to know anything about struct display. int pidp8i_simple_gpio_mode = 0; // GPIO peripheral info, initted in start_pidp8i_gpio_thread() struct bcm2835_peripheral gpio; #define pgpio (&gpio) #ifdef PCB_SERIAL_MOD_JLW struct bcm2835_peripheral gpio2; #endif // A constant meaning "indeterminate milliseconds", used for error // returns from ms_time() and for the case where the switch is in the // stable state in the switch_state array. static const ms_time_t na_ms = (ms_time_t)-1; // Adjust columns to scan based on whether Oscar Vermeulen's serial mod // was done, as that affects the free GPIOs for our use, and how the PCB // connects them to the LED matrix. James L-W's mod leaves GPIO pin // numbering unchanged relative to the stock circuit design. #ifdef PCB_SERIAL_MOD_OV uint8_t cols[NCOLS] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2}; #else uint8_t cols[NCOLS] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 15, 14}; #endif uint8_t ledrows[NLEDROWS] = {20, 21, 22, 23, 24, 25, 26, 27}; uint8_t rows[NROWS] = {16, 17, 18}; // Current switch states, as reported by the debouncing algorithm. Set // from the GPIO thread to control the SIMH CPU thread. uint16_t switchstatus[NROWS]; // Double-buffered LED display brightness values. The update-to copy is // modified by the SIMH CPU thread as it executes instructions, and the // paint-from copy is read by the gpio-*.c module in its "set LEDs" // loop. When the GPIO thread is finished with the paint-from copy, it // zeroes it and swaps it for the current "update-to" copy, giving the // CPU thread a blank slate, and giving the GPIO thread a stable set of // LED "on" time values to work with. display display_bufs[2]; display* pdis_update = display_bufs + 0; // exported to SIMH CPU thread display* pdis_paint = display_bufs + 1; // exported to gpio-*.c // GPIO thread control variables manipulated by start/stop_*() below static pthread_t gpio_thread_info; static int terminate_gpio_thread = 0; static pthread_mutex_t gpio_start_mutex; // Time-delayed reaction to switch changes to debounce the contacts. // This is especially important with the incandescent lamp simulation // feature enabled since that speeds up the GPIO scanning loop, making // it more susceptible to contact bounce. struct switch_state { // switch state currently reported via switchstatus[] int stable_state; // ms the switch state has been != stable_state, or na_ms // if it is currently in that same state ms_time_t last_change; }; static struct switch_state gss[NROWS][NCOLS]; static int gss_initted = 0; static const ms_time_t debounce_ms = 50; // time switch state must remain stable // Flow-control switch states which are owned by -- that is, primarily // modified by -- the PDP8/pidp8i module, but we can't define these // there because we refer to them below, and not all programs that link // to us link to that module as well. For such programs, it's fine if // these two flags stay 0. int swStop = 0, swSingInst = 0; // Flag set when sim_instr() exits due to some SIMH event like Ctrl-E, // which lets us resume from our imposed "pause" display state. int resumeFromInstructionLoopExit = 0; //// MEMORY MAPPED GPIO FUNCTIONS ////////////////////////////////////// //// map_peripheral //////////////////////////////////////////////////// // Exposes the physical address defined in the passed structure int map_peripheral(struct bcm2835_peripheral *p, int exclusive) { // Name of GPIO memory-mapped device static const char* gpio_mem_dev = "/dev/gpiomem"; if (access(gpio_mem_dev, F_OK) < 0) { // That dev node isn't even present, so it's probably not a Pi return -1; } // Open the GPIO device if ((p->mem_fd = open(gpio_mem_dev, O_RDWR|O_SYNC)) < 0) { #ifdef DEBUG printf("Failed to open %s: %s\n", gpio_mem_dev, strerror(errno)); puts("Disabling PiDP-8/I front panel functionality."); #endif return -1; } // Attempt to lock it. If we can't, another program has it locked, // so we shouldn't keep running; it'll just end in tears. if (exclusive && (flock(p->mem_fd, LOCK_EX | LOCK_NB) < 0)) { if (errno == EWOULDBLOCK) { printf("Failed to lock %s. Only one PiDP-8/I\n", gpio_mem_dev); puts("program can be running at a given time."); } else { printf("Failed to lock %s: %s\n", gpio_mem_dev, strerror(errno)); puts("Only one PiDP-8/I program can be running at a given time."); } return -1; } // Map the GPIO peripheral into our address space if ((p->map = mmap( NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, p->mem_fd, p->addr_p)) == MAP_FAILED) { perror("mmap"); return -1; } // Success! p->addr = (volatile unsigned int *)p->map; pidp8i_gpio_present = 1; return 0; } //// unmap_peripheral ////////////////////////////////////////////////// // Unwind the map_peripheral() steps in reverse order void unmap_peripheral(struct bcm2835_peripheral *p) { if (pidp8i_gpio_present) { if (p->mem_fd > 0) { if (p->map) munmap(p->map, BLOCK_SIZE); flock(p->mem_fd, LOCK_UN); close(p->mem_fd); } pidp8i_gpio_present = 0; } } //// bcm_host_get_peripheral_address /////////////////////////////////// // Find Pi's GPIO base address unsigned bcm_host_get_peripheral_address(void) { unsigned address = ~0; FILE *fp = fopen("/proc/device-tree/soc/ranges", "rb"); if (fp) { unsigned char buf[4]; fseek(fp, 4, SEEK_SET); if (fread(buf, 1, sizeof buf, fp) == sizeof buf) address = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0; fclose(fp); } return address == ~0 ? 0x20000000 : address; } //// DOUBLE BUFFERED DISPLAY MANIPULATION FUNCTIONS //////////////////// //// swap_displays //////////////////////////////////////////////////// // Clear the current "paint-from" display, then exchange the double- // buffered display pointers atomically, saving the current update-to // display pointer as our paint-from display pointer and re-pointing // the update-to pointer at the now-zeroed paint-from values. This // gives the CPU thread a blank slate to begin modifying while the GPIO // thread consumes the values provided by the CPU thread. #define SWAP(dir) \ __atomic_exchange_n (&pdis_update, display_bufs + dir, __ATOMIC_SEQ_CST) void swap_displays () { if (!swStop && !swSingInst) { if (pidp8i_simple_gpio_mode) { // We're linked to a program that wants to use the old // ledstatus[] interface for updating the display, so copy // its values into the paint-from display structure and // return. We don't need to touch the update-to display or // swap anything, because set_pidp8i_leds won't be called. static const int levels = 32; memcpy (pdis_paint->curr, ledstatus, sizeof (pdis_paint->curr)); pdis_paint->inst_count = levels; for (size_t row = 0; row < NLEDROWS; ++row) { size_t *prow = pdis_paint->on[row]; for (size_t col = 0, mask = 1; col < NCOLS; ++col, mask <<= 1) { prow[col] = !!(ledstatus[row] & mask) * levels; } } } else { // Clear old paint-from display memset (pdis_paint, 0, sizeof(display)); // Send old paint-from display to CPU as new update-to // display, and overwrite paint-from pointer with prior // update-to pointer. pdis_paint = pdis_update == display_bufs + 0 ? SWAP(1) : SWAP(0); } } // else, leave current LED values as-is so we don't go to a black // screen while in STOP mode, either from front panel or HLT } //// FINE GRAINED SLEEP FUNCTIONS ////////////////////////////////////// //// sleep_ns ////////////////////////////////////////////////////////// // Like sleep(2) except that it takes nanoseconds instead of seconds void sleep_ns(ns_time_t ns) { struct timespec ts = { 0, ns }; #if defined(HAVE_CLOCK_NANOSLEEP) clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL); #elif defined(HAVE_NANOSLEEP) nanosleep(&ts, NULL); #elif defined(HAVE_USLEEP) usleep(ns / 1000); #else # error Cannot build GPIO controller without high-res "sleep" function! #endif } //// ms_time /////////////////////////////////////////////////////////// // Like time(2) except that it returns milliseconds since the Unix epoch ms_time_t ms_time(ms_time_t* pt) { struct timeval tv; if (gettimeofday(&tv, 0) == 0) { ms_time_t t = tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0; if (pt) *pt = t; return t; } else { return na_ms; } } //// SWITCH DEBOUNCING and READING FUNCTIONS /////////////////////////// //// report_ss ///////////////////////////////////////////////////////// // Save given switch state ss into the exported switchstatus bitfield // so the simulator core will see it. (Constrast the gss matrix, // which holds our internal view of the unstable truth.) static void report_ss(int row, int col, int ss, struct switch_state* pss) { pss->stable_state = ss; pss->last_change = na_ms; int mask = 1 << col; if (ss) switchstatus[row] |= mask; else switchstatus[row] &= ~mask; #ifdef DEBUG printf("%cSS[%d][%02d] = %d ", gss_initted ? 'N' : 'I', row, col, ss); #endif } //// debounce_switch /////////////////////////////////////////////////// // Given the state of the switch at (row,col), work out if this requires // a change in our exported switch state. static void debounce_switch(int row, int col, int ss, ms_time_t now_ms) { struct switch_state* pss = &gss[row][col]; if (!gss_initted) { // First time thru, so set this switch's module-global and // exported state to its defaults now that we know the switch's // initial state. report_ss(row, col, ss, pss); } else if (ss == pss->stable_state) { // This switch is still/again in the state we consider "stable", // which we are reporting in our switchstatus bitfield. Reset // the debounce timer in case it is returning to its stable // state from a brief blip into the other state. pss->last_change = na_ms; } else if (pss->last_change == na_ms) { // This switch just left what we consider the "stable" state, so // start the debounce timer. pss->last_change = now_ms; } else if ((now_ms - pss->last_change) > debounce_ms) { // Switch has been in the new state long enough for the contacts // to have stopped bouncing: report its state change to outsiders. report_ss(row, col, ss, pss); } // else, switch was in the new state both this time and the one prior, // but it hasn't been there long enough to report it } //// read_switches ///////////////////////////////////////////////////// // Iterate through the switch GPIO pins, passing them to the debouncing // mechanism above for eventual reporting to the PDP-8 CPU thread. void read_switches (ns_time_t delay) { // Save current ms-since-epoch for debouncer. No point making it // retrieve this value for each switch. ms_time_t now_ms; ms_time(&now_ms); // Flip columns to input. Since the internal pull-ups are enabled, // this pulls all switch GPIO pins high that aren't shorted to the // row line by the switch. for (size_t i = 0; i < NCOLS; ++i) { INP_GPIO(cols[i]); } // Read the switch rows for (size_t i = 0; i < NROWS; ++i) { // Put 0V out on the switch row so that closed switches will // drag its column line down; give it time to settle. OUT_GPIO(rows[i]); GPIO_CLR = 1 << rows[i]; sleep_ns (delay); // Read all the switches in this row for (size_t j = 0; j < NCOLS; ++j) { int ss = GPIO_READ(cols[j]); debounce_switch(i, j, !!ss, now_ms); } // Stop sinking current from this row of switches INP_GPIO(rows[i]); } fflush(stdout); gss_initted = 1; } //// UNGROUPED FUNCTIONS /////////////////////////////////////////////// //// pi_type /////////////////////////////////////////////////////////// // Return a short string succinctly describing the type of Raspberry Pi // we're running on, or "cake" if it's not a pi. static const char* pi_type() { static char ac[60] = { '\0' }; static const char* prefix = "Raspberry Pi "; FILE* fp = fopen("/proc/device-tree/model", "r"); if (fp && fgets(ac, sizeof(ac), fp) && (strlen(ac) > 20) && (strstr(ac, prefix) == ac)) { const char* kind = ac + strlen(prefix); int series = 1; if (kind[0] == 'M') { // It's one of the "plus" models. const char* pm = kind + strlen("Model "); char model = *pm; model = (isalpha(model) && isupper(model)) ? tolower(model) : 'x'; snprintf(ac, sizeof(ac), "pi%d%c", series, model); } else if (kind[0] == 'C') { // It's one of the compute modules. We don't actually // support these, but we need to report them in case // someone tries it. const char* ps = kind + strlen("Compute Module"); char series = *ps; if (series) { // It's should be one of the later Compute Module series. series = isdigit(ps[1]) ? ps[1] : 'x'; snprintf(ac, sizeof(ac), "picm%c", series); } else { // We're at the end of the string, so it's the original // Compute Module. return "picm1"; } } else if (kind[0] == 'Z') { // It's a Pi Zero return "pi0"; } else if ((series = atoi(kind)) > 1) { // Pi 2 and newer have a number after the "Pi" char* pm = strstr(kind, " Model "); snprintf(ac, sizeof(ac), "pi%d%c", series, pm ? tolower(pm[7]) : 'x'); } else { // Not a model string we can parse, but it's some kind of // RPi. Two 'x's stand for unknown series and model. return "pixx"; } } else { return "cake"; // not pi } return ac; } //// update_led_states ///////////////////////////////////////////////// // Generic front panel LED updater used by NLS full time and by ILS // while the CPU is in STOP mode. Just uses the paint-from display's // bitfields to turn the LEDs on full-brightness. void update_led_states (const us_time_t delay) { uint16_t *pcurr = pdis_paint->curr; #if 0 // debugging static time_t last = 0, now; if (time(&now) != last) { printf("\r\nLED: [PC:%04o] [MA:%04o] [MB:%04o] [AC:%04o] [MQ:%04o]", pcurr[0], pcurr[1], pcurr[2], pcurr[3], pcurr[4]); last = now; } #endif // Override Execute and Run LEDs if the CPU is currently stopped, // since we only get set_pidp8i_leds calls while the CPU's running. if (swStop || swSingInst) { pdis_paint->curr[5] &= ~(1 << 2); pdis_paint->curr[6] &= ~(1 << 7); } for (size_t row = 0; row < NLEDROWS; ++row) { for (size_t col = 0; col < NCOLS; ++col) { if ((pcurr[row] & (1 << col)) == 0) { GPIO_SET = 1 << cols[col]; } else { GPIO_CLR = 1 << cols[col]; } } // Toggle this LED row on INP_GPIO (ledrows[row]); GPIO_SET = 1 << ledrows[row]; OUT_GPIO (ledrows[row]); sleep_us (delay); // Toggle this LED row off GPIO_CLR = 1 << ledrows[row]; // superstition INP_GPIO (ledrows[row]); // Small delay to reduce UDN2981 ghosting sleep_us (10); } } //// turn_off_pidp8i_leds ////////////////////////////////////////////// // Set GPIO pins into a state that disconnects all the LEDs from power. // Doesn't pay any attention to the panel values. void turn_off_pidp8i_leds () { for (size_t i = 0; i < NCOLS; ++i) { OUT_GPIO(cols[i]); } for (size_t row = 0; row < NLEDROWS; ++row) { INP_GPIO (ledrows[row]); } } //// gpio_thread /////////////////////////////////////////////////////// // The GPIO thread entry point: initializes GPIO and then calls // the gpio_core () implementation linked to this program. static void *gpio_thread (void *terminate) { // Set thread to real time priority struct sched_param sp; sp.sched_priority = 4; // not high, just above the minimum of 1 int rt = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp) == 0; // Tell the user about our configuration, succinctly const char* pt = pi_type(); printf( "PiDP-8/I @VERSION@ [%s] [%cls] [%spcb] [%sgpio]" #ifdef DEBUG " [debug]" #endif "%s", pt, ILS_MODE ? 'i' : 'n', pt[0] == 'p' ? #ifdef PCB_SERIAL_MOD_OV "sermod" : #elif PCB_SERIAL_MOD_JLW "altser" : #else "std" : #endif "no", (pidp8i_gpio_present ? "" : "no"), (rt ? " [rt]" : "") ); // It's okay for our caller to resume executing, if it's locked // waiting for us to finish the initialization bits that can only // happen in this thread. pthread_mutex_unlock (&gpio_start_mutex); // If we didn't map the GPIO peripheral and get here, it was // optional, and we've done all we can without it. if (!pidp8i_gpio_present) return (void*)-1; // initialise GPIO (all pins used as inputs, with pull-ups enabled on cols) int i; for (i = 0; i < NLEDROWS; i++) { // Define ledrows as input INP_GPIO(ledrows[i]); GPIO_CLR = 1 << ledrows[i]; // so go to Low when switched to output } for (i = 0; i < NCOLS; i++) { // Define cols as input INP_GPIO(cols[i]); } for (i = 0; i < NROWS; i++) { // Define rows as input INP_GPIO(rows[i]); } // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs GPIO_PULL = 2; // pull-up usleep(1); // must wait 150 cycles #ifdef PCB_SERIAL_MOD_OV // Oscar Vermeulen's serial mod the PiDP-8/I board rearranges the // GPIO matrix to use Pi GPIO pins 2..13, freeing up the hardware // serial port on GPIO pins 14 & 15. GPIO_PULLCLK0 = 0x03ffc; #else // The standard PiDP-8/I board drive scheme uses Pi GPIO pins 4..15. // (James L-W's alternative serial mod also uses this scheme.) GPIO_PULLCLK0 = 0x0fff0; #endif usleep(1); GPIO_PULL = 0; // reset GPPUD register usleep(1); GPIO_PULLCLK0 = 0; // remove clock usleep(1); // probably unnecessary // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs GPIO_PULL = 1; // pull-down to avoid ghosting (dec2015) usleep(1); // must wait 150 cycles GPIO_PULLCLK0 = 0x0ff00000; // selects GPIO pins 20..27 usleep(1); GPIO_PULL = 0; // reset GPPUD register usleep(1); GPIO_PULLCLK0 = 0; // remove clock usleep(1); // probably unnecessary // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs GPIO_PULL = 0; // no pull-up no pull down just float usleep(1); // must wait 150 cycles GPIO_PULLCLK0 = 0x070000; // selects GPIO pins 16..18 usleep(1); GPIO_PULL = 0; // reset GPPUD register usleep(1); GPIO_PULLCLK0 = 0; // remove clock usleep(1); // probably unnecessary // Hand off control to the gpio_core () variant linked to this // program: either the new incandescent lamp simulator or the old // stock version. extern void gpio_core (struct bcm2835_peripheral*, int* terminate); gpio_core (&gpio, (int*)terminate); // gpio_core () leaves all cols, rows, ledrows are set to input, and // it's safe to leave them in that state. No need to de-init GPIO. gss_initted = 0; return 0; } //// start/stop_pidp8i_gpio_thread ///////////////////////////////////// // Start and stop gpio_thread(). We export these functions rather than // export gpio_thread() directly so this module's users don't have to // know anything about pthreads and such. int start_pidp8i_gpio_thread (const char* must_map) { char errs[100]; // Find GPIO address (it varies by Pi model) unsigned int gpio_base_addr = bcm_host_get_peripheral_address(); gpio.addr_p = gpio_base_addr + 0x200000; // Attempt to map the GPIO peripheral for our exclusive use. Some // callers care if this fails, and some don't. map_peripheral (&gpio, 1); if (must_map && !pidp8i_gpio_present) return EFAULT; #ifdef PCB_SERIAL_MOD_JLW // James L-W's alternative serial mods were declared to be done here // at configure time, so disable the hysteresis on the GPIO inputs. map_peripheral (&gpio2, 0); // assume success since prior mapping worked gpio2.addr_p = gpio_base_addr + 0x100000; gpio2.addr[0x0B] = (gpio2.addr[0x0B] & 0xF7) | (0x5A << 24); #endif // Until gpio_core () reads the switches for the first time, we need // to mark them as all-open, lest we have a race condition with the // simulator where it interprets the all-0 initial switchstatus[] // value as "all switches closed," which includes the shutdown seq! memset (switchstatus, 0xFF, sizeof (switchstatus)); // Create the startup sequencing mutex and lock it once to block the // GPIO thread after it's sufficiently initialized. int pcerr; if ( ((pcerr = pthread_mutex_init (&gpio_start_mutex, NULL)) != 0) || ((pcerr = pthread_mutex_lock (&gpio_start_mutex)) != 0)) { perror ("GPIO startup sequence mutex creation failed"); return errno; } // Create the actual GPIO handler thread pcerr = pthread_create (&gpio_thread_info, NULL, gpio_thread, &terminate_gpio_thread); if (pcerr != 0) { int errlen = snprintf (errs, sizeof(errs), "Error creating " "PiDP-8/I GPIO thread: %s\n", strerror (pcerr)); if (errlen > 0 && errlen < sizeof(errs)) write (2, errs, errlen); } else if (must_map && !pidp8i_gpio_present) { int errlen = snprintf (errs, sizeof(errs), "Cannot run the %s " "while another PiDP-8/I program runs.\r\n", must_map); if (errlen > 0 && errlen < sizeof(errs)) write (2, errs, errlen); pcerr = EACCES; } else { // Don't return until GPIO thread is sufficiently initted. // // There are two possible sequences: // // 1. We get here before the GPIO thread gets to its "unlock" // call, so our back-to-back locks in this thread stall this // thread until the GPIO thread gets to its unlock condition, // which removes the first lock taken above, and our second // unlock call below removes the second lock. // // 2. The GPIO thread hits its "unlock" call before we get here, // so it unlocks the lock we made above, so that these two // calls happen back to back, with no real effect. We got // here too late to cause any problem that this interlock // solves, so it just locks and immediately unlocks. pthread_mutex_lock (&gpio_start_mutex); pthread_mutex_unlock (&gpio_start_mutex); } return pcerr; } void stop_pidp8i_gpio_thread () { terminate_gpio_thread = 1; if (pthread_join (gpio_thread_info, NULL)) { printf("\r\nError joining multiplex thread\r\n"); } unmap_peripheral (&gpio); #ifdef PCB_SERIAL_MOD_JLW unmap_peripheral (&gpio2); #endif pthread_mutex_destroy (&gpio_start_mutex); } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | /* * gpio-common.h: public interface for the PiDP-8/I's GPIO module * * Copyright © 2015-2017 Oscar Vermeulen and Warren Young * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the names of the authors above shall * not be used in advertising or otherwise to promote the sale, use or other * dealings in this Software without prior written authorization from those * authors. */ #if !defined(PIDP8I_GPIO_H) #define PIDP8I_GPIO_H #include <unistd.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdint.h> // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) #define INP_GPIO(g) *(pgpio->addr + ((g)/10)) &= ~(7<<(((g)%10)*3)) #define OUT_GPIO(g) *(pgpio->addr + ((g)/10)) |= (1<<(((g)%10)*3)) #define SET_GPIO_ALT(g,a) *(pgpio->addr + (((g)/10))) |= (((a)<=3?(a) + 4:(a)==4?3:2)<<(((g)%10)*3)) #define GPIO_SET *(pgpio->addr + 7) // sets bits which are 1 ignores bits which are 0 #define GPIO_CLR *(pgpio->addr + 10) // clears bits which are 1 ignores bits which are 0 #define GPIO_READ(g) *(pgpio->addr + 13) &= (1<<(g)) #define GPIO_PULL *(pgpio->addr + 37) // pull up/pull down #define GPIO_PULLCLK0 *(pgpio->addr + 38) // pull up/pull down clock // Switch masks, SSn, used against switchstatus[n] #define SS0_SR_B11 04000 #define SS0_SR_B10 02000 #define SS0_SR_B09 01000 #define SS0_SR_B08 00400 #define SS0_SR_B07 00200 #define SS0_SR_B06 00100 #define SS0_SR_B05 00040 #define SS0_SR_B04 00020 #define SS0_SR_B03 00010 #define SS0_SR_B02 00004 #define SS0_SR_B01 00002 #define SS0_SR_B00 00001 #define SS1_DF_B2 04000 #define SS1_DF_B1 02000 #define SS1_DF_B0 01000 #define SS1_DF_ALL (SS1_DF_B2 | SS1_DF_B1 | SS1_DF_B0) #define SS1_IF_B2 00400 #define SS1_IF_B1 00200 #define SS1_IF_B0 00100 #define SS1_IF_ALL (SS1_IF_B2 | SS1_IF_B1 | SS1_IF_B0) #define SS2_START 04000 #define SS2_L_ADD 02000 #define SS2_DEP 01000 #define SS2_EXAM 00400 #define SS2_CONT 00200 #define SS2_STOP 00100 #define SS2_S_STEP 00040 #define SS2_S_INST 00020 // Number of LED and switch rows and columns on the PiDP-8/I PCB #define NCOLS 12 #define NLEDROWS 8 #define NROWS 3 // Info for accessing the GPIO peripheral on the SoC struct bcm2835_peripheral { uint32_t addr_p; int mem_fd; void *map; volatile unsigned int *addr; }; typedef uint64_t ns_time_t; typedef useconds_t us_time_t; typedef uint64_t ms_time_t; typedef struct display { // Counters incremented each time the LED is known to be turned on, // in instructions since the last display paint. size_t on[NLEDROWS][NCOLS]; // Most recent state for each LED, for use by NLS full-time and by // ILS in STOP mode. (One bitfield per row.) uint16_t curr[NLEDROWS]; // Number of instructions executed since this display was cleared int inst_count; } display; extern display* pdis_update, *pdis_paint; // Compatibility interface for programs like src/test.c that depend on // being able to modify the LED values directly. #define ledstatus (pdis_update->curr) extern int pidp8i_simple_gpio_mode; extern uint16_t switchstatus[]; extern uint8_t cols[]; extern uint8_t ledrows[]; extern uint8_t rows[]; extern uint8_t pidp8i_gpio_present; extern int start_pidp8i_gpio_thread (const char* must_map); extern void stop_pidp8i_gpio_thread (); extern void turn_off_pidp8i_leds (); extern void update_led_states (const us_time_t delay); extern unsigned bcm_host_get_peripheral_address(void); extern int map_peripheral(struct bcm2835_peripheral *p, int exclusive); extern void unmap_peripheral(struct bcm2835_peripheral *p); extern void read_switches (ns_time_t delay); extern void swap_displays (); extern void sleep_ns(ns_time_t ns); #define sleep_us(us) usleep(us) #define sleep_ms(ms) sleep_us(ms * 1000) extern ms_time_t ms_time(ms_time_t* pt); #endif // !defined(PIDP8I_GPIO_H) |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | /* * gpio-ils.c: implements gpio_core () for Ian Schofield's incandescent * lamp simulator * * Copyright © 2015-2017 Oscar Vermeulen, Ian Schofield, and Warren Young * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the names of the authors above shall * not be used in advertising or otherwise to promote the sale, use or other * dealings in this Software without prior written authorization from those * authors. * * www.obsolescenceguaranteed.blogspot.com */ #include "gpio-common.h" #include "sim_defs.h" #include "PDP8/pidp8i.h" //// CONSTANTS ///////////////////////////////////////////////////////// // Brightness range is [0, MAX_BRIGHTNESS) truncated. #define MAX_BRIGHTNESS 32 // On each iteration, we add or subtract a proportion of the LED's "on" // time back to it as its new brightness, so that it takes several // iterations at that same "on" time for the LED to achieve that // brightness level. Because the delta is based on the prior value, we // get nonlinear asymptotic increase/decrease behavior. // // We use an asymmetric function depending on whether the LED is turning // on or off to better mimic the behavior of an incandescent lamp, which // reaches full brightness faster than it turns fully off. #define RISING_FACTOR 0.012 #define FALLING_FACTOR 0.005 //// gpio_core //////////////////////////////////////////////////////// // The GPIO module's main loop core, called from thread entry point in // gpio-common.c. void gpio_core (struct bcm2835_peripheral* pgpio, int* terminate) { // The ILS version uses an iteration rate 60x faster than the NLS // version because we have to get through 32 PWM steps, each of // which takes roughly 2 * intervl µs. There's a bit of extra delay // over intervl in the NLS version, so the while loop iteration time // is about the same for both versions. const us_time_t intervl = 20; // Current brightness level for each LED. It goes from 0 to // MAX_BRIGHTNESS, but we keep it as a float because the decay // function smoothly ramps from the current value to the ever- // changing target value. float brightness[NLEDROWS][NCOLS]; memset(brightness, 0, sizeof (brightness)); // Brightness target for each LED, updated at the start of each PWM // cycle when we get fresh "on" counts from the CPU thread. uint8 br_targets[NLEDROWS][NCOLS]; memset(br_targets, 0, sizeof (br_targets)); // Current PWM brightness step uint8 step = MAX_BRIGHTNESS; while (*terminate == 0) { // Prepare for lighting LEDs by setting col pins to output for (size_t i = 0; i < NCOLS; ++i) OUT_GPIO(cols[i]); // Restart PWM cycle if prior one is complete if (step == MAX_BRIGHTNESS) { // Reset PWM step counter step = 0; // Go get the current LED "on" times, and give the SIMH // CPU thread a blank copy to begin updating. Because we're // in control of the swap timing, we don't need to copy the // pdis_paint pointer: it points to the same thing between // these swap_displays() calls. swap_displays(); // Recalculate the brightness target values based on the // "on" counts in *pdis_paint and the quantized brightness // level, which is based on the number of instructions // executed for this display update. // // Handle the cases where inst_count is < 32 specially // because we don't want all LEDs to go out when the // simulator is heavily throttled. const size_t inst_count = pdis_paint->inst_count; size_t br_quant = inst_count >= 32 ? (inst_count >> 5) : 1; for (int row = 0; row < NLEDROWS; ++row) { size_t *prow = pdis_paint->on[row]; for (int col = 0; col < NCOLS; ++col) { br_targets[row][col] = prow[col] / br_quant; } } // Hard-code the Fetch and Execute brightnesses; in running // mode, they're both on half the instruction time, so we // just set them to 50% brightness. Execute differs in STOP // mode, but that's handled in update_led_states () because // we fall back to NLS in STOP mode. br_targets[5][2] = br_targets[5][3] = MAX_BRIGHTNESS / 2; } ++step; // Update the brightness values. for (int row = 0; row < NLEDROWS; ++row) { size_t *prow = pdis_paint->on[row]; for (int col = 0; col < NCOLS; ++col) { uint8 br_target = br_targets[row][col]; float *p = brightness[row] + col; if (*p <= br_target) { *p += (br_target - *p) * RISING_FACTOR; } else { *p -= *p * FALLING_FACTOR; } } } // Light up LEDs extern int swStop, swSingInst; if (swStop || swSingInst) { // The CPU is in STOP mode, so show the current LED states // full-brightness using the same mechanism NLS uses. update_led_states (intervl * 60); } else { // Normal case: PWM display using the on-count values for (size_t row = 0; row < NLEDROWS; ++row) { // Output 0 (CLR) for LEDs in this row which should be on size_t *prow = pdis_paint->on[row]; for (size_t col = 0; col < NCOLS; ++col) { if (brightness[row][col] >= step) { GPIO_CLR = 1 << cols[col]; } else { GPIO_SET = 1 << cols[col]; } } // Toggle this LED row on INP_GPIO(ledrows[row]); GPIO_SET = 1 << ledrows[row]; OUT_GPIO(ledrows[row]); sleep_us(intervl); // Toggle this LED row off GPIO_CLR = 1 << ledrows[row]; // superstition INP_GPIO(ledrows[row]); sleep_ns(5); } } #if 0 // debugging static time_t last = 0, now; if (time(&now) != last) { float* p = brightness[0]; #define B(n) (p[n] / MAX_BRIGHTNESS * 100.0) printf("\r\nPC:" " [%3.0f%%][%3.0f%%][%3.0f%%]" " [%3.0f%%][%3.0f%%][%3.0f%%]" " [%3.0f%%][%3.0f%%][%3.0f%%]" " [%3.0f%%][%3.0f%%][%3.0f%%]", B(11), B(10), B(9), B(8), B(7), B(6), B(5), B(4), B(3), B(2), B(1), B(0)); last = now; } #endif // 625 = * 1000 / (100 / 60) where 60 is the difference in // iteration rate between ILS and NLS. See the same call // in gpio-nls.c. read_switches(intervl * 625); #if defined(HAVE_SCHED_YIELD) sched_yield(); #endif } } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | /* * gpio-nls.c: implements gpio_core () with the original simple LED driver * * This file differs from gpio.c in that it does not include the * incandescent lamp simulator feature by Ian Schofield. It is * more directly descended from the original gpio.c by Oscar Vermeulen. * * Copyright © 2015-2017 Oscar Vermeulen and Warren Young * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the names of the authors above shall * not be used in advertising or otherwise to promote the sale, use or other * dealings in this Software without prior written authorization from those * authors. * * www.obsolescenceguaranteed.blogspot.com */ #include "gpio-common.h" #include "PDP8/pidp8i.h" //// gpio_core //////////////////////////////////////////////////////// // The GPIO module's main loop core, called from thread entry point in // gpio-common.c. void gpio_core (struct bcm2835_peripheral* pgpio, int* terminate) { // Light each row of LEDs 1.2 ms. With 8 rows, that's an update // rate of ~100x per second. Not coincidentally, this is the human // persistence of vision limit: changes faster than this are // difficult for humans to perceive visually. const us_time_t intervl = 1200; // This is a simplified version of what's in the gpio-ils.c version // of this function, so if you want more comments, read them there. while (*terminate == 0) { for (size_t i = 0; i < NCOLS; ++i) OUT_GPIO(cols[i]); swap_displays (); update_led_states (intervl); read_switches (intervl * 1000 / 100); #if defined(HAVE_SCHED_YIELD) sched_yield (); #endif } } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | /* * Scan switches for PiDP-8/I front panel * * www.obsolescenceguaranteed.blogspot.com * * Copyright (c) 2015-2016 Oscar Vermeulen * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the names of the authors above shall * not be used in advertising or otherwise to promote the sale, use or other * dealings in this Software without prior written authorization from those * authors. * */ #include "gpio-common.h" #define short_wait() sleep_us(100000) #define pgpio (&gpio) int main() { int i,j,k,switchscan[2], tmp; struct bcm2835_peripheral gpio; // ------------ Find gpio address (different for Pi 2) ------------- gpio.addr_p = bcm_host_get_peripheral_address() + 0x200000; if (gpio.addr_p== 0x20200000) printf("scanswitch - RPi Plus\n"); else printf("scanswitch - RPi 2\n"); if (map_peripheral(&gpio, 0) != 0) { printf("Failed to map the physical GPIO registers into the virtual memory space.\n"); return -1; } // initialise GPIO (all pins used as inputs, with pull-ups enabled on cols) for (i=0;i<NLEDROWS;i++) // Define ledrows as input INP_GPIO(ledrows[i]); for (i=0;i<NCOLS;i++) // Define cols as input INP_GPIO(cols[i]); for (i=0;i<NROWS;i++) // Define rows as input INP_GPIO(rows[i]); // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs GPIO_PULL = 2; // pull-up short_wait(); // must wait 150 cycles GPIO_PULLCLK0 = 0x0fff0; // selects GPIO pins 4..15 (assumes we avoid pins 2 and 3!) short_wait(); GPIO_PULL = 0; // reset GPPUD register short_wait(); GPIO_PULLCLK0 = 0; // remove clock short_wait(); // probably unnecessary // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs GPIO_PULL = 0; // no pull-up no pull-down just float short_wait(); // must wait 150 cycles GPIO_PULLCLK0 = 0x0ff00000; // selects GPIO pins 20..27 short_wait(); GPIO_PULL = 0; // reset GPPUD register short_wait(); GPIO_PULLCLK0 = 0; // remove clock short_wait(); // probably unnecessary // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs GPIO_PULL = 0; // no pull-up no pull down just float short_wait(); // must wait 150 cycles GPIO_PULLCLK0 = 0x070000; // selects GPIO pins 16..18 short_wait(); GPIO_PULL = 0; // reset GPPUD register short_wait(); GPIO_PULLCLK0 = 0; // remove clock short_wait(); // probably unnecessary // -------------------------------------------------- // prepare for reading switches for (uint8_t row=1;row<=2;row++) // do rows 2 (for IF switches) and 3 (for STOP switch) { INP_GPIO(rows[row]); OUT_GPIO(rows[row]); // turn on one switch row GPIO_CLR = 1 << rows[row]; // and output 0V to overrule built-in pull-up from column input pin sleep_us(10); // unnecessarily long? switchscan[row-1]=0; for (j=0;j<NCOLS;j++) // 12 switches in each row { tmp = GPIO_READ(cols[j]); if (tmp==0) switchscan[row-1] += 1<<j; } INP_GPIO(rows[row]); // stop sinking current from this row of switches } unmap_peripheral(&gpio); if ( ((switchscan[1] >> 6) & 1) == 1 ) // STOP switch enabled, return 8; // 8: STOP enabled, no bootscript else return (switchscan[0] >> 6) & 07; // 0-7: x.script to be used in PiDP-8/I } |
more than 10,000 changes
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 | /* scp.h: simulator control program headers Copyright (c) 1993-2009, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 05-Dec-10 MP Added macro invocation of sim_debug 09-Aug-06 JDB Added assign_device and deassign_device 14-Jul-06 RMS Added sim_activate_abs 06-Jan-06 RMS Added fprint_stopped_gen Changed arg type in sim_brk_test 07-Feb-05 RMS Added ASSERT command 09-Sep-04 RMS Added reset_all_p 14-Feb-04 RMS Added debug prototypes (from Dave Hittner) 02-Jan-04 RMS Split out from SCP */ #ifndef SIM_SCP_H_ #define SIM_SCP_H_ 0 #ifdef __cplusplus extern "C" { #endif /* run_cmd parameters */ #define RU_RUN 0 /* run */ #define RU_GO 1 /* go */ #define RU_STEP 2 /* step */ #define RU_NEXT 3 /* step or step/over */ #define RU_CONT 4 /* continue */ #define RU_BOOT 5 /* boot */ /* exdep_cmd parameters */ #define EX_D 0 /* deposit */ #define EX_E 1 /* examine */ #define EX_I 2 /* interactive */ /* brk_cmd parameters */ #define SSH_ST 0 /* set */ #define SSH_SH 1 /* show */ #define SSH_CL 2 /* clear */ /* get_sim_opt parameters */ #define CMD_OPT_SW 001 /* switches */ #define CMD_OPT_OF 002 /* output file */ #define CMD_OPT_SCH 004 /* search */ #define CMD_OPT_DFT 010 /* defaults */ /* Command processors */ t_stat reset_cmd (int32 flag, CONST char *ptr); t_stat exdep_cmd (int32 flag, CONST char *ptr); t_stat eval_cmd (int32 flag, CONST char *ptr); t_stat load_cmd (int32 flag, CONST char *ptr); t_stat run_cmd (int32 flag, CONST char *ptr); void run_cmd_message (const char *unechod_cmdline, t_stat r); t_stat attach_cmd (int32 flag, CONST char *ptr); t_stat detach_cmd (int32 flag, CONST char *ptr); t_stat assign_cmd (int32 flag, CONST char *ptr); t_stat deassign_cmd (int32 flag, CONST char *ptr); t_stat save_cmd (int32 flag, CONST char *ptr); t_stat restore_cmd (int32 flag, CONST char *ptr); t_stat exit_cmd (int32 flag, CONST char *ptr); t_stat set_cmd (int32 flag, CONST char *ptr); t_stat show_cmd (int32 flag, CONST char *ptr); t_stat set_default_cmd (int32 flg, CONST char *cptr); t_stat pwd_cmd (int32 flg, CONST char *cptr); t_stat dir_cmd (int32 flg, CONST char *cptr); t_stat type_cmd (int32 flg, CONST char *cptr); t_stat delete_cmd (int32 flg, CONST char *cptr); t_stat brk_cmd (int32 flag, CONST char *ptr); t_stat do_cmd (int32 flag, CONST char *ptr); t_stat goto_cmd (int32 flag, CONST char *ptr); t_stat return_cmd (int32 flag, CONST char *ptr); t_stat shift_cmd (int32 flag, CONST char *ptr); t_stat call_cmd (int32 flag, CONST char *ptr); t_stat on_cmd (int32 flag, CONST char *ptr); t_stat noop_cmd (int32 flag, CONST char *ptr); t_stat assert_cmd (int32 flag, CONST char *ptr); t_stat send_cmd (int32 flag, CONST char *ptr); t_stat expect_cmd (int32 flag, CONST char *ptr); t_stat help_cmd (int32 flag, CONST char *ptr); t_stat screenshot_cmd (int32 flag, CONST char *ptr); t_stat spawn_cmd (int32 flag, CONST char *ptr); t_stat echo_cmd (int32 flag, CONST char *ptr); /* Allow compiler to help validate printf style format arguments */ #if !defined __GNUC__ #define GCC_FMT_ATTR(n, m) #endif #if !defined(GCC_FMT_ATTR) #define GCC_FMT_ATTR(n, m) __attribute__ ((format (__printf__, n, m))) #endif /* Utility routines */ t_stat sim_process_event (void); t_stat sim_activate (UNIT *uptr, int32 interval); t_stat _sim_activate (UNIT *uptr, int32 interval); t_stat sim_activate_abs (UNIT *uptr, int32 interval); t_stat sim_activate_notbefore (UNIT *uptr, int32 rtime); t_stat sim_activate_after (UNIT *uptr, uint32 usecs_walltime); t_stat sim_activate_after_d (UNIT *uptr, double usecs_walltime); t_stat _sim_activate_after (UNIT *uptr, double usecs_walltime); t_stat sim_activate_after_abs (UNIT *uptr, uint32 usecs_walltime); t_stat sim_activate_after_abs_d (UNIT *uptr, double usecs_walltime); t_stat _sim_activate_after_abs (UNIT *uptr, double usecs_walltime); t_stat sim_cancel (UNIT *uptr); t_bool sim_is_active (UNIT *uptr); int32 sim_activate_time (UNIT *uptr); int32 _sim_activate_time (UNIT *uptr); double sim_activate_time_usecs (UNIT *uptr); t_stat sim_run_boot_prep (int32 flag); double sim_gtime (void); uint32 sim_grtime (void); int32 sim_qcount (void); t_stat attach_unit (UNIT *uptr, CONST char *cptr); t_stat detach_unit (UNIT *uptr); t_stat assign_device (DEVICE *dptr, const char *cptr); t_stat deassign_device (DEVICE *dptr); t_stat reset_all (uint32 start_device); t_stat reset_all_p (uint32 start_device); const char *sim_dname (DEVICE *dptr); const char *sim_uname (UNIT *dptr); const char *sim_set_uname (UNIT *uptr, const char *uname); t_stat get_yn (const char *ques, t_stat deflt); char *sim_trim_endspc (char *cptr); int sim_isspace (char c); int sim_islower (char c); int sim_isalpha (char c); int sim_isprint (char c); int sim_isdigit (char c); int sim_isgraph (char c); int sim_isalnum (char c); int sim_strncasecmp (const char *string1, const char *string2, size_t len); int sim_strcasecmp (const char *string1, const char *string2); size_t sim_strlcat (char *dst, const char *src, size_t size); size_t sim_strlcpy (char *dst, const char *src, size_t size); CONST char *get_sim_opt (int32 opt, CONST char *cptr, t_stat *st); const char *put_switches (char *buf, size_t bufsize, uint32 sw); CONST char *get_glyph (const char *iptr, char *optr, char mchar); CONST char *get_glyph_nc (const char *iptr, char *optr, char mchar); CONST char *get_glyph_quoted (const char *iptr, char *optr, char mchar); CONST char *get_glyph_cmd (const char *iptr, char *optr); t_value get_uint (const char *cptr, uint32 radix, t_value max, t_stat *status); CONST char *get_range (DEVICE *dptr, CONST char *cptr, t_addr *lo, t_addr *hi, uint32 rdx, t_addr max, char term); t_stat sim_decode_quoted_string (const char *iptr, uint8 *optr, uint32 *osize); char *sim_encode_quoted_string (const uint8 *iptr, uint32 size); void fprint_buffer_string (FILE *st, const uint8 *buf, uint32 size); t_value strtotv (CONST char *cptr, CONST char **endptr, uint32 radix); int Fprintf (FILE *f, const char *fmt, ...) GCC_FMT_ATTR(2, 3); /* Use scp.c provided fprintf function */ #define fprintf Fprintf #define fputs(_s,_f) Fprintf(_f,"%s",_s) #define fputc(_c,_f) Fprintf(_f,"%c",_c) t_stat sim_set_memory_load_file (const unsigned char *data, size_t size); int Fgetc (FILE *f); t_stat fprint_val (FILE *stream, t_value val, uint32 rdx, uint32 wid, uint32 fmt); t_stat sprint_val (char *buf, t_value val, uint32 rdx, uint32 wid, uint32 fmt); t_stat sim_print_val (t_value val, uint32 radix, uint32 width, uint32 format); const char *sim_fmt_secs (double seconds); const char *sim_fmt_numeric (double number); const char *sprint_capac (DEVICE *dptr, UNIT *uptr); char *read_line (char *cptr, int32 size, FILE *stream); void fprint_reg_help (FILE *st, DEVICE *dptr); void fprint_set_help (FILE *st, DEVICE *dptr); void fprint_show_help (FILE *st, DEVICE *dptr); CTAB *find_cmd (const char *gbuf); DEVICE *find_dev (const char *ptr); DEVICE *find_unit (const char *ptr, UNIT **uptr); DEVICE *find_dev_from_unit (UNIT *uptr); t_stat sim_register_internal_device (DEVICE *dptr); void sim_sub_args (char *in_str, size_t in_str_size, char *do_arg[]); REG *find_reg (CONST char *ptr, CONST char **optr, DEVICE *dptr); CTAB *find_ctab (CTAB *tab, const char *gbuf); C1TAB *find_c1tab (C1TAB *tab, const char *gbuf); SHTAB *find_shtab (SHTAB *tab, const char *gbuf); t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr); t_value get_rval (REG *rptr, uint32 idx); BRKTAB *sim_brk_fnd (t_addr loc); uint32 sim_brk_test (t_addr bloc, uint32 btyp); void sim_brk_clrspc (uint32 spc, uint32 btyp); void sim_brk_npc (uint32 cnt); void sim_brk_setact (const char *action); const char *sim_brk_message(void); t_stat sim_send_input (SEND *snd, uint8 *data, size_t size, uint32 after, uint32 delay); t_stat sim_show_send_input (FILE *st, const SEND *snd); t_bool sim_send_poll_data (SEND *snd, t_stat *stat); t_stat sim_send_clear (SEND *snd); t_stat sim_set_expect (EXPECT *exp, CONST char *cptr); t_stat sim_set_noexpect (EXPECT *exp, const char *cptr); t_stat sim_exp_set (EXPECT *exp, const char *match, int32 cnt, uint32 after, int32 switches, const char *act); t_stat sim_exp_clr (EXPECT *exp, const char *match); t_stat sim_exp_clrall (EXPECT *exp); t_stat sim_exp_show (FILE *st, CONST EXPECT *exp, const char *match); t_stat sim_exp_showall (FILE *st, const EXPECT *exp); t_stat sim_exp_check (EXPECT *exp, uint8 data); CONST char *match_ext (CONST char *fnam, const char *ext); t_stat show_version (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat set_dev_debug (DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat show_dev_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); const char *sim_error_text (t_stat stat); t_stat sim_string_to_stat (const char *cptr, t_stat *cond); t_stat sim_cancel_step (void); void sim_printf (const char *fmt, ...) GCC_FMT_ATTR(1, 2); void sim_perror (const char *msg); t_stat sim_messagef (t_stat stat, const char *fmt, ...) GCC_FMT_ATTR(2, 3); void sim_data_trace(DEVICE *dptr, UNIT *uptr, const uint8 *data, const char *position, size_t len, const char *txt, uint32 reason); void sim_debug_bits_hdr (uint32 dbits, DEVICE* dptr, const char *header, BITFIELD* bitdefs, uint32 before, uint32 after, int terminate); void sim_debug_bits (uint32 dbits, DEVICE* dptr, BITFIELD* bitdefs, uint32 before, uint32 after, int terminate); #if defined (__DECC) && defined (__VMS) && (defined (__VAX) || (__DECC_VER < 60590001)) #define CANT_USE_MACRO_VA_ARGS 1 #endif #if defined(__cplusplus) #ifdef CANT_USE_MACRO_VA_ARGS #define _sim_debug sim_debug void sim_debug (uint32 dbits, void* dptr, const char *fmt, ...) GCC_FMT_ATTR(3, 4); #else void _sim_debug (uint32 dbits, void* dptr, const char *fmt, ...) GCC_FMT_ATTR(3, 4); #define sim_debug(dbits, dptr, ...) do { if (sim_deb && dptr && ((dptr)->dctrl & dbits)) _sim_debug (dbits, dptr, __VA_ARGS__);} while (0) #endif #else #ifdef CANT_USE_MACRO_VA_ARGS #define _sim_debug sim_debug void sim_debug (uint32 dbits, DEVICE* dptr, const char *fmt, ...) GCC_FMT_ATTR(3, 4); #else void _sim_debug (uint32 dbits, DEVICE* dptr, const char *fmt, ...) GCC_FMT_ATTR(3, 4); #define sim_debug(dbits, dptr, ...) do { if (sim_deb && dptr && ((dptr)->dctrl & dbits)) _sim_debug (dbits, dptr, __VA_ARGS__);} while (0) #endif #endif void fprint_stopped_gen (FILE *st, t_stat v, REG *pc, DEVICE *dptr); #define SCP_HELP_FLAT (1u << 31) /* Force flat help when prompting is not possible */ #define SCP_HELP_ONECMD (1u << 30) /* Display one topic, do not prompt */ #define SCP_HELP_ATTACH (1u << 29) /* Top level topic is ATTACH help */ t_stat scp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *help, const char *cptr, ...); t_stat scp_vhelp (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *help, const char *cptr, va_list ap); t_stat scp_helpFromFile (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *help, const char *cptr, ...); t_stat scp_vhelpFromFile (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *help, const char *cptr, va_list ap); /* Global data */ extern DEVICE *sim_dflt_dev; extern DEVICE *sim_dfdev; extern UNIT *sim_dfunit; extern int32 sim_interval; extern int32 sim_switches; extern int32 sim_quiet; extern int32 sim_step; extern t_stat sim_last_cmd_stat; /* Command Status */ extern FILE *sim_log; /* log file */ extern FILEREF *sim_log_ref; /* log file file reference */ extern FILE *sim_deb; /* debug file */ extern FILEREF *sim_deb_ref; /* debug file file reference */ extern int32 sim_deb_switches; /* debug display flags */ extern struct timespec sim_deb_basetime; /* debug base time for relative time output */ extern DEVICE **sim_internal_devices; extern uint32 sim_internal_device_count; extern UNIT *sim_clock_queue; extern int32 sim_is_running; extern t_bool sim_processing_event; /* Called from sim_process_event */ extern char *sim_prompt; /* prompt string */ extern const char *sim_savename; /* Simulator Name used in Save/Restore files */ extern t_value *sim_eval; extern volatile int32 stop_cpu; extern uint32 sim_brk_types; /* breakpoint info */ extern uint32 sim_brk_dflt; extern uint32 sim_brk_summ; extern uint32 sim_brk_match_type; extern t_addr sim_brk_match_addr; extern BRKTYPTAB *sim_brk_type_desc; /* type descriptions */ extern FILE *stdnul; extern t_bool sim_asynch_enabled; #if defined(SIM_ASYNCH_IO) int sim_aio_update_queue (void); void sim_aio_activate (ACTIVATE_API caller, UNIT *uptr, int32 event_time); #endif /* VM interface */ extern char sim_name[64]; extern DEVICE *sim_devices[]; extern REG *sim_PC; extern const char *sim_stop_messages[SCPE_BASE]; extern t_stat sim_instr (void); extern t_stat sim_load (FILE *ptr, CONST char *cptr, CONST char *fnam, int flag); extern int32 sim_emax; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw); extern t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw); /* The per-simulator init routine is a weak global that defaults to NULL The other per-simulator pointers can be overrriden by the init routine */ WEAK extern void (*sim_vm_init) (void); extern char *(*sim_vm_read) (char *ptr, int32 size, FILE *stream); extern void (*sim_vm_post) (t_bool from_scp); extern CTAB *sim_vm_cmd; extern void (*sim_vm_sprint_addr) (char *buf, DEVICE *dptr, t_addr addr); extern void (*sim_vm_fprint_addr) (FILE *st, DEVICE *dptr, t_addr addr); extern t_addr (*sim_vm_parse_addr) (DEVICE *dptr, CONST char *cptr, CONST char **tptr); extern t_bool (*sim_vm_fprint_stopped) (FILE *st, t_stat reason); extern t_value (*sim_vm_pc_value) (void); extern t_bool (*sim_vm_is_subroutine_call) (t_addr **ret_addrs); #ifdef __cplusplus } #endif #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 | /* sim_console.c: simulator console I/O library Copyright (c) 1993-2014, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 02-Jan-14 RMS Added tab stop routines 18-Mar-12 RMS Removed unused reference to sim_switches (Dave Bryan) 07-Dec-11 MP Added sim_ttisatty to support reasonable behaviour (i.e. avoid in infinite loop) in the main command input loop when EOF is detected and input is coming from a file (or a null device: /dev/null or NUL:) This may happen when a simulator is running in a background process. 17-Apr-11 MP Cleaned up to support running in a background/detached process 20-Jan-11 MP Fixed support for BREAK key on Windows to account for/ignore other keyboard Meta characters. 18-Jan-11 MP Added log file reference count support 17-Jan-11 MP Added support for a "Buffered" behaviors which include: - If Buffering is enabled and Telnet is enabled, a telnet connection is not required for simulator operation (instruction execution). - If Buffering is enabled, all console output is written to the buffer at all times (deleting the oldest buffer contents on overflow). - when a connection is established on the console telnet port, the whole contents of the Buffer is presented on the telnet session and connection will then proceed as if the connection had always been there. This concept allows a simulator to run in the background and when needed a console session to be established. The "when needed" case usually will be interested in what already happened before looking to address what to do, hence the buffer contents being presented. 28-Dec-10 MP Added support for BREAK key on Windows 30-Sep-06 RMS Fixed non-printable characters in KSR mode 22-Jun-06 RMS Implemented SET/SHOW PCHAR 31-May-06 JDB Fixed bug if SET CONSOLE DEBUG with no argument 22-Nov-05 RMS Added central input/output conversion support 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy 28-Oct-04 JDB Fixed SET CONSOLE to allow comma-separated parameters 20-Aug-04 RMS Added OS/2 EMX fixes (Holger Veit) 14-Jul-04 RMS Revised Windows console code (Dave Bryan) 28-May-04 RMS Added SET/SHOW CONSOLE RMS Added break, delete character maps 02-Jan-04 RMS Removed timer routines, added Telnet console routines RMS Moved console logging to OS-independent code 25-Apr-03 RMS Added long seek support (Mark Pizzolato) Added Unix priority control (Mark Pizzolato) 24-Sep-02 RMS Removed VT support, added Telnet console support Added CGI support (Brian Knittel) Added MacOS sleep (Peter Schorn) 14-Jul-02 RMS Added Windows priority control (Mark Pizzolato) 20-May-02 RMS Added Windows VT support (Fischer Franz) 01-Feb-02 RMS Added VAX fix (Robert Alan Byer) 19-Sep-01 RMS More MacOS changes 31-Aug-01 RMS Changed int64 to t_int64 for Windoze 20-Jul-01 RMS Added MacOS support (Louis Chretien, Peter Schorn, Ben Supnik) 15-May-01 RMS Added logging support 05-Mar-01 RMS Added clock calibration support 08-Dec-00 BKR Added OS/2 support (Bruce Ray) 18-Aug-98 RMS Added BeOS support 13-Oct-97 RMS Added NetBSD terminal support 25-Jan-97 RMS Added POSIX terminal I/O support 02-Jan-97 RMS Fixed bug in sim_poll_kbd This module implements the following routines to support terminal and Remote Console I/O: sim_poll_kbd poll for keyboard input sim_putchar output character to console sim_putchar_s output character to console, stall if congested sim_set_console set console parameters sim_show_console show console parameters sim_set_remote_console set remote console parameters sim_show_remote_console show remote console parameters sim_set_cons_buff set console buffered sim_set_cons_unbuff set console unbuffered sim_set_cons_log set console log sim_set_cons_nolog set console nolog sim_show_cons_buff show console buffered sim_show_cons_log show console log sim_tt_inpcvt convert input character per mode sim_tt_outcvt convert output character per mode sim_cons_get_send get console send structure address sim_cons_get_expect get console expect structure address sim_show_cons_send_input show pending input data sim_show_cons_expect show expect rules and state sim_ttinit called once to get initial terminal state sim_ttrun called to put terminal into run state sim_ttcmd called to return terminal to command state sim_ttclose called once before the simulator exits sim_ttisatty called to determine if running interactively sim_os_poll_kbd poll for keyboard input sim_os_putchar output character to console sim_set_noconsole_port Enable automatic WRU console polling sim_set_stable_registers_state Declare that all registers are always stable The first group is OS-independent; the second group is OS-dependent. The following routines are exposed but deprecated: sim_set_telnet set console to Telnet port sim_set_notelnet close console Telnet port sim_show_telnet show console status */ #include "sim_defs.h" #include "sim_tmxr.h" #include "sim_serial.h" #include "sim_timer.h" #include <ctype.h> #include <math.h> #ifdef __HAIKU__ #define nice(n) ({}) #endif /* Forward Declaraations of Platform specific routines */ static t_stat sim_os_poll_kbd (void); static t_bool sim_os_poll_kbd_ready (int ms_timeout); static t_stat sim_os_putchar (int32 out); static t_stat sim_os_ttinit (void); static t_stat sim_os_ttrun (void); static t_stat sim_os_ttcmd (void); static t_stat sim_os_ttclose (void); static t_bool sim_os_ttisatty (void); static t_stat sim_set_rem_telnet (int32 flag, CONST char *cptr); static t_stat sim_set_rem_bufsize (int32 flag, CONST char *cptr); static t_stat sim_set_rem_connections (int32 flag, CONST char *cptr); static t_stat sim_set_rem_timeout (int32 flag, CONST char *cptr); static t_stat sim_set_rem_master (int32 flag, CONST char *cptr); /* Deprecated CONSOLE HALT, CONSOLE RESPONSE and CONSOLE DELAY support */ static t_stat sim_set_halt (int32 flag, CONST char *cptr); static t_stat sim_set_response (int32 flag, CONST char *cptr); static t_stat sim_set_delay (int32 flag, CONST char *cptr); #define KMAP_WRU 0 #define KMAP_BRK 1 #define KMAP_DEL 2 #define KMAP_MASK 0377 #define KMAP_NZ 0400 int32 sim_int_char = 005; /* interrupt character */ int32 sim_brk_char = 000; /* break character */ int32 sim_tt_pchar = 0x00002780; #if defined (_WIN32) || defined (__OS2__) || (defined (__MWERKS__) && defined (macintosh)) int32 sim_del_char = '\b'; /* delete character */ #else int32 sim_del_char = 0177; #endif extern TMLN *sim_oline; /* global output socket */ static t_stat sim_con_poll_svc (UNIT *uptr); /* console connection poll routine */ static t_stat sim_con_reset (DEVICE *dptr); /* console reset routine */ static t_stat sim_con_attach (UNIT *uptr, CONST char *ptr); /* console attach routine (save,restore) */ static t_stat sim_con_detach (UNIT *uptr); /* console detach routine (save,restore) */ UNIT sim_con_units[2] = {{ UDATA (&sim_con_poll_svc, UNIT_ATTABLE, 0)}}; /* console connection unit */ #define sim_con_unit sim_con_units[0] /* debugging bitmaps */ #define DBG_TRC TMXR_DBG_TRC /* trace routine calls */ #define DBG_XMT TMXR_DBG_XMT /* display Transmitted Data */ #define DBG_RCV TMXR_DBG_RCV /* display Received Data */ #define DBG_RET TMXR_DBG_RET /* display Returned Received Data */ #define DBG_ASY TMXR_DBG_ASY /* asynchronous thread activity */ #define DBG_CON TMXR_DBG_CON /* display connection activity */ #define DBG_EXP 0x00000001 /* Expect match activity */ #define DBG_SND 0x00000002 /* Send (Inject) data activity */ static DEBTAB sim_con_debug[] = { {"TRC", DBG_TRC, "routine calls"}, {"XMT", DBG_XMT, "Transmitted Data"}, {"RCV", DBG_RCV, "Received Data"}, {"RET", DBG_RET, "Returned Received Data"}, {"ASY", DBG_ASY, "asynchronous activity"}, {"CON", DBG_CON, "connection activity"}, {"EXP", DBG_EXP, "Expect match activity"}, {"SND", DBG_SND, "Send (Inject) data activity"}, {0} }; static REG sim_con_reg[] = { { ORDATAD (WRU, sim_int_char, 8, "interrupt character") }, { ORDATAD (BRK, sim_brk_char, 8, "break character") }, { ORDATAD (DEL, sim_del_char, 8, "delete character ") }, { ORDATAD (PCHAR, sim_tt_pchar, 32, "printable character mask") }, { 0 }, }; static MTAB sim_con_mod[] = { { 0 }, }; static const char *sim_con_telnet_description (DEVICE *dptr) { return "Console telnet support"; } DEVICE sim_con_telnet = { "CON-TELNET", sim_con_units, sim_con_reg, sim_con_mod, 2, 0, 0, 0, 0, 0, NULL, NULL, sim_con_reset, NULL, sim_con_attach, sim_con_detach, NULL, DEV_DEBUG, 0, sim_con_debug, NULL, NULL, NULL, NULL, NULL, sim_con_telnet_description}; TMLN sim_con_ldsc = { 0 }; /* console line descr */ TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc, NULL, &sim_con_telnet };/* console line mux */ SEND sim_con_send = {SEND_DEFAULT_DELAY, &sim_con_telnet, DBG_SND}; EXPECT sim_con_expect = {&sim_con_telnet, DBG_EXP}; static t_bool sim_con_console_port = TRUE; /* Enable automatic WRU console polling */ t_stat sim_set_noconsole_port (void) { sim_con_console_port = FALSE; return SCPE_OK; } static t_bool sim_con_stable_registers = FALSE; /* Enable automatic WRU console polling */ t_stat sim_set_stable_registers_state (void) { sim_con_stable_registers = TRUE; return SCPE_OK; } /* Unit service for console connection polling */ static t_stat sim_con_poll_svc (UNIT *uptr) { if ((sim_con_tmxr.master == 0) && /* not Telnet and not serial and not WRU polling? */ (sim_con_ldsc.serport == 0) && (sim_con_console_port)) return SCPE_OK; /* done */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */ sim_con_ldsc.rcve = 1; /* rcv enabled */ sim_activate_after(uptr, 1000000); /* check again in 1 second */ if (!sim_con_console_port) /* WRU poll needed */ sim_poll_kbd(); /* sets global stop_cpu when WRU received */ if (sim_con_ldsc.conn) tmxr_send_buffered_data (&sim_con_ldsc); /* try to flush any buffered data */ return SCPE_OK; } static t_stat sim_con_reset (DEVICE *dptr) { dptr->units[1].flags = UNIT_DIS; return sim_con_poll_svc (&dptr->units[0]); /* establish polling as needed */ } /* Console Attach/Detach - only used indirectly in restore */ static t_stat sim_con_attach (UNIT *uptr, CONST char *ptr) { return tmxr_attach (&sim_con_tmxr, &sim_con_unit, ptr); } static t_stat sim_con_detach (UNIT *uptr) { return sim_set_notelnet (0, NULL); } /* Set/show data structures */ static CTAB set_con_tab[] = { { "WRU", &sim_set_kmap, KMAP_WRU | KMAP_NZ }, { "BRK", &sim_set_kmap, KMAP_BRK }, { "DEL", &sim_set_kmap, KMAP_DEL |KMAP_NZ }, { "PCHAR", &sim_set_pchar, 0 }, { "SPEED", &sim_set_cons_speed, 0 }, { "TELNET", &sim_set_telnet, 0 }, { "NOTELNET", &sim_set_notelnet, 0 }, { "SERIAL", &sim_set_serial, 0 }, { "NOSERIAL", &sim_set_noserial, 0 }, { "LOG", &sim_set_logon, 0 }, { "NOLOG", &sim_set_logoff, 0 }, { "DEBUG", &sim_set_debon, 0 }, { "NODEBUG", &sim_set_deboff, 0 }, #define CMD_WANTSTR 0100000 { "HALT", &sim_set_halt, 1 | CMD_WANTSTR }, { "NOHALT", &sim_set_halt, 0 }, { "DELAY", &sim_set_delay, 0 }, { "RESPONSE", &sim_set_response, 1 | CMD_WANTSTR }, { "NORESPONSE", &sim_set_response, 0 }, { NULL, NULL, 0 } }; static CTAB set_rem_con_tab[] = { { "CONNECTIONS", &sim_set_rem_connections, 0 }, { "TELNET", &sim_set_rem_telnet, 1 }, { "BUFFERSIZE", &sim_set_rem_bufsize, 1 }, { "NOTELNET", &sim_set_rem_telnet, 0 }, { "TIMEOUT", &sim_set_rem_timeout, 0 }, { "MASTER", &sim_set_rem_master, 1 }, { "NOMASTER", &sim_set_rem_master, 0 }, { NULL, NULL, 0 } }; static SHTAB show_con_tab[] = { { "WRU", &sim_show_kmap, KMAP_WRU }, { "BRK", &sim_show_kmap, KMAP_BRK }, { "DEL", &sim_show_kmap, KMAP_DEL }, { "PCHAR", &sim_show_pchar, 0 }, { "SPEED", &sim_show_cons_speed, 0 }, { "LOG", &sim_show_cons_log, 0 }, { "TELNET", &sim_show_telnet, 0 }, { "DEBUG", &sim_show_cons_debug, 0 }, { "BUFFERED", &sim_show_cons_buff, 0 }, { "EXPECT", &sim_show_cons_expect, 0 }, { "HALT", &sim_show_cons_expect, 0 }, { "INPUT", &sim_show_cons_send_input, 0 }, { "RESPONSE", &sim_show_cons_send_input, 0 }, { "DELAY", &sim_show_cons_expect, 0 }, { NULL, NULL, 0 } }; static CTAB set_con_telnet_tab[] = { { "LOG", &sim_set_cons_log, 0 }, { "NOLOG", &sim_set_cons_nolog, 0 }, { "BUFFERED", &sim_set_cons_buff, 0 }, { "NOBUFFERED", &sim_set_cons_unbuff, 0 }, { "UNBUFFERED", &sim_set_cons_unbuff, 0 }, { NULL, NULL, 0 } }; static CTAB set_con_serial_tab[] = { { "LOG", &sim_set_cons_log, 0 }, { "NOLOG", &sim_set_cons_nolog, 0 }, { NULL, NULL, 0 } }; static int32 *cons_kmap[] = { &sim_int_char, &sim_brk_char, &sim_del_char }; /* Console I/O package. The console terminal can be attached to the controlling window or to a Telnet connection. If attached to a Telnet connection, the console is described by internal terminal multiplexor sim_con_tmxr and internal terminal line description sim_con_ldsc. */ /* SET CONSOLE command */ t_stat sim_set_console (int32 flag, CONST char *cptr) { char *cvptr, gbuf[CBUFSIZE]; CTAB *ctptr; t_stat r; if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; while (*cptr != 0) { /* do all mods */ cptr = get_glyph_nc (cptr, gbuf, ','); /* get modifier */ if ((cvptr = strchr (gbuf, '='))) /* = value? */ *cvptr++ = 0; get_glyph (gbuf, gbuf, 0); /* modifier to UC */ if ((ctptr = find_ctab (set_con_tab, gbuf))) { /* match? */ r = ctptr->action (ctptr->arg, cvptr); /* do the rest */ if (r != SCPE_OK) return r; } else return SCPE_NOPARAM; } return SCPE_OK; } /* SHOW CONSOLE command */ t_stat sim_show_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { char gbuf[CBUFSIZE]; SHTAB *shptr; int32 i; if (*cptr == 0) { /* show all */ for (i = 0; show_con_tab[i].name; i++) show_con_tab[i].action (st, dptr, uptr, show_con_tab[i].arg, cptr); return SCPE_OK; } while (*cptr != 0) { cptr = get_glyph (cptr, gbuf, ','); /* get modifier */ if ((shptr = find_shtab (show_con_tab, gbuf))) shptr->action (st, dptr, uptr, shptr->arg, cptr); else return SCPE_NOPARAM; } return SCPE_OK; } #define MAX_REMOTE_SESSIONS 40 /* Arbitrary Session Limit */ t_stat sim_rem_con_poll_svc (UNIT *uptr); /* remote console connection poll routine */ t_stat sim_rem_con_data_svc (UNIT *uptr); /* remote console connection data routine */ t_stat sim_rem_con_repeat_svc (UNIT *uptr); /* remote auto repeat command console timing routine */ t_stat sim_rem_con_smp_collect_svc (UNIT *uptr); /* remote remote register data sampling routine */ t_stat sim_rem_con_reset (DEVICE *dptr); /* remote console reset routine */ #define rem_con_poll_unit (&sim_remote_console.units[0]) #define rem_con_data_unit (&sim_remote_console.units[1]) #define REM_CON_BASE_UNITS 2 #define rem_con_repeat_units (&sim_remote_console.units[REM_CON_BASE_UNITS]) #define rem_con_smp_smpl_units (&sim_remote_console.units[REM_CON_BASE_UNITS+sim_rem_con_tmxr.lines]) #define DBG_MOD 0x00000004 /* Remote Console Mode activities */ #define DBG_REP 0x00000008 /* Remote Console Repeat activities */ #define DBG_SAM 0x00000010 /* Remote Console Sample activities */ #define DBG_CMD 0x00000020 /* Remote Console Command activities */ DEBTAB sim_rem_con_debug[] = { {"TRC", DBG_TRC, "routine calls"}, {"XMT", DBG_XMT, "Transmitted Data"}, {"RCV", DBG_RCV, "Received Data"}, {"CON", DBG_CON, "connection activity"}, {"CMD", DBG_CMD, "Remote Console Command activity"}, {"MODE", DBG_MOD, "Remote Console Mode activity"}, {"REPEAT", DBG_REP, "Remote Console Repeat activity"}, {"SAMPLE", DBG_SAM, "Remote Console Sample activity"}, {0} }; MTAB sim_rem_con_mod[] = { { 0 }, }; static const char *sim_rem_con_description (DEVICE *dptr) { return "Remote Console Facility"; } DEVICE sim_remote_console = { "REM-CON", NULL, NULL, sim_rem_con_mod, 0, 0, 0, 0, 0, 0, NULL, NULL, sim_rem_con_reset, NULL, NULL, NULL, NULL, DEV_DEBUG | DEV_NOSAVE, 0, sim_rem_con_debug, NULL, NULL, NULL, NULL, NULL, sim_rem_con_description}; typedef struct BITSAMPLE BITSAMPLE; struct BITSAMPLE { int tot; /* total of all values */ int ptr; /* pointer to next value cell */ int depth; /* number of values */ int *vals; /* values */ }; typedef struct BITSAMPLE_REG BITSAMPLE_REG; struct BITSAMPLE_REG { REG *reg; /* Register to be sampled */ t_bool indirect; /* Register value points at memory */ DEVICE *dptr; /* Device register is part of */ UNIT *uptr; /* Unit Register is related to */ uint32 width; /* number of bits to sample */ BITSAMPLE *bits; }; typedef struct REMOTE REMOTE; struct REMOTE { int32 buf_size; int32 buf_ptr; char *buf; char *act_buf; size_t act_buf_size; char *act; t_bool single_mode; uint32 read_timeout; int line; /* remote console line number */ TMLN *lp; /* mux line/socket for remote session */ UNIT *uptr; /* remote console unit */ uint32 repeat_interval; /* usecs between repeat execution */ t_bool repeat_pending; /* repeat delivery pending */ char *repeat_action; /* command(s) to repeatedly execute */ int smp_sample_interval; /* cycles between samples */ uint32 smp_reg_count; /* sample register count */ BITSAMPLE_REG *smp_regs; /* registers being sampled */ }; REMOTE *sim_rem_consoles = NULL; static TMXR sim_rem_con_tmxr = { 0, 0, 0, NULL, NULL, &sim_remote_console };/* remote console line mux */ static uint32 sim_rem_read_timeout = 30; /* seconds before automatic continue */ static uint32 *sim_rem_read_timeouts = NULL;/* per line read timeout (default from sim_rem_read_timeout) */ static int32 sim_rem_active_number = -1; /* -1 - not active, >= 0 is index of active console */ int32 sim_rem_cmd_active_line = -1; /* step in progress on line # */ static CTAB *sim_rem_active_command = NULL; /* active command */ static char *sim_rem_command_buf; /* active command buffer */ static t_bool sim_log_temp = FALSE; /* temporary log file active */ static char sim_rem_con_temp_name[PATH_MAX+1]; static t_bool sim_rem_master_mode = FALSE; /* Master Mode Enabled Flag */ static t_bool sim_rem_master_was_enabled = FALSE; /* Master was Enabled */ static t_bool sim_rem_master_was_connected = FALSE; /* Master Mode has been connected */ static t_offset sim_rem_cmd_log_start = 0; /* Log File saved position */ static t_stat sim_rem_sample_output (FILE *st, int32 line) { REMOTE *rem = &sim_rem_consoles[line]; uint32 reg; if (rem->smp_reg_count == 0) { fprintf (st, "Samples are not being collected\n"); return SCPE_OK; } for (reg = 0; reg < rem->smp_reg_count; reg++) { uint32 bit; fprintf (st, "}%s %s%s %d:", rem->smp_regs[reg].dptr->name, rem->smp_regs[reg].reg->name, rem->smp_regs[reg].indirect ? " -I" : "", rem->smp_regs[reg].bits[0].depth); for (bit = 0; bit < rem->smp_regs[reg].width; bit++) fprintf (st, "%s%d", (bit != 0) ? "," : "", rem->smp_regs[reg].bits[bit].tot); fprintf (st, "\n"); } return SCPE_OK; } /* SET REMOTE CONSOLE command */ t_stat sim_set_remote_console (int32 flag, CONST char *cptr) { char *cvptr, gbuf[CBUFSIZE]; CTAB *ctptr; t_stat r; if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; while (*cptr != 0) { /* do all mods */ cptr = get_glyph_nc (cptr, gbuf, ','); /* get modifier */ if ((cvptr = strchr (gbuf, '='))) /* = value? */ *cvptr++ = 0; get_glyph (gbuf, gbuf, 0); /* modifier to UC */ if ((ctptr = find_ctab (set_rem_con_tab, gbuf))) { /* match? */ r = ctptr->action (ctptr->arg, cvptr); /* do the rest */ if (r != SCPE_OK) return r; } else return SCPE_NOPARAM; } return SCPE_OK; } /* SHOW REMOTE CONSOLE command */ t_stat sim_show_remote_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { int32 i, connections; REMOTE *rem; if (*cptr != 0) return SCPE_NOPARAM; if (sim_rem_active_number >= 0) { if (sim_rem_master_mode && (sim_rem_active_number == 0)) fprintf (st, "Running from Master Mode Remote Console Connection\n"); else fprintf (st, "Running from Remote Console Connection %d\n", sim_rem_active_number); } if (sim_rem_con_tmxr.lines > 1) fprintf (st, "Remote Console Input Connections from %d sources are supported concurrently\n", sim_rem_con_tmxr.lines); if (sim_rem_read_timeout) fprintf (st, "Remote Console Input automatically continues after %d seconds\n", sim_rem_read_timeout); if (!sim_rem_con_tmxr.master) fprintf (st, "Remote Console Command input is disabled\n"); else { fprintf (st, "Remote Console Command Input listening on TCP port: %s\n", rem_con_poll_unit->filename); fprintf (st, "Remote Console Per Command Output buffer size: %d bytes\n", sim_rem_con_tmxr.buffered); } for (i=connections=0; i<sim_rem_con_tmxr.lines; i++) { rem = &sim_rem_consoles[i]; if (!rem->lp->conn) continue; ++connections; if (connections == 1) fprintf (st, "Remote Console Connections:\n"); tmxr_fconns (st, rem->lp, i); if (rem->read_timeout != sim_rem_read_timeout) { if (rem->read_timeout) fprintf (st, "Remote Console Input on connection %d automatically continues after %d seconds\n", i, rem->read_timeout); else fprintf (st, "Remote Console Input on connection %d does not continue automatically\n", i); } if (rem->repeat_action) { fprintf (st, "The Command: %s\n", rem->repeat_action); fprintf (st, " is repeated every %s\n", sim_fmt_secs (rem->repeat_interval / 1000000.0)); } if (rem->smp_reg_count) { uint32 reg; DEVICE *dptr = NULL; fprintf (st, "Register Bit Sampling is occurring every %d cycles\n", rem->smp_sample_interval); fprintf (st, " Registers being sampled are: "); for (reg = 0; reg < rem->smp_reg_count; reg++) { if (rem->smp_regs[reg].indirect) fprintf (st, " indirect "); if (dptr != rem->smp_regs[reg].dptr) fprintf (st, "%s ", rem->smp_regs[reg].dptr->name); fprintf (st, "%s%s", rem->smp_regs[reg].reg->name, ((reg + 1) < rem->smp_reg_count) ? ", " : ""); dptr = rem->smp_regs[reg].dptr; } fprintf (st, "\n"); if (sim_switches & SWMASK ('D')) sim_rem_sample_output (st, rem->line); } } return SCPE_OK; } /* Unit service for remote console connection polling */ t_stat sim_rem_con_poll_svc (UNIT *uptr) { int32 c; c = tmxr_poll_conn (&sim_rem_con_tmxr); if (c >= 0) { /* poll connect */ REMOTE *rem = &sim_rem_consoles[c]; TMLN *lp = rem->lp; char wru_name[8]; sim_activate_after(uptr+1, 1000000); /* start data poll after 1 second */ lp->rcve = 1; /* rcv enabled */ rem->buf_ptr = 0; /* start with empty command buffer */ rem->single_mode = TRUE; /* start in single command mode */ rem->read_timeout = sim_rem_read_timeout; /* Start with default timeout */ if (isprint(sim_int_char&0xFF)) sprintf(wru_name, "'%c'", sim_int_char&0xFF); else if (sim_int_char <= 26) sprintf(wru_name, "^%c", '@' + (sim_int_char&0xFF)); else sprintf(wru_name, "'\\%03o'", sim_int_char&0xFF); tmxr_linemsgf (lp, "%s Remote Console\r\n" "Enter single commands or to enter multiple command mode enter the %s character\r" "%s", sim_name, wru_name, ((sim_rem_master_mode && (c == 0)) ? "" : "\nSimulator Running...")); if (sim_rem_master_mode && (c == 0)) /* Master Mode session? */ rem->single_mode = FALSE; /* start in multi-command mode */ tmxr_send_buffered_data (lp); /* flush buffered data */ } sim_activate_after(uptr, 1000000); /* check again in 1 second */ if (sim_con_ldsc.conn) tmxr_send_buffered_data (&sim_con_ldsc); /* try to flush any buffered data */ return SCPE_OK; } static t_stat x_continue_cmd (int32 flag, CONST char *cptr) { return 1+SCPE_IERR; /* This routine should never be called */ } static t_stat x_repeat_cmd (int32 flag, CONST char *cptr) { return 2+SCPE_IERR; /* This routine should never be called */ } static t_stat x_collect_cmd (int32 flag, CONST char *cptr) { return 3+SCPE_IERR; /* This routine should never be called */ } static t_stat x_sampleout_cmd (int32 flag, CONST char *cptr) { return 4+SCPE_IERR; /* This routine should never be called */ } static t_stat x_step_cmd (int32 flag, CONST char *cptr) { return 5+SCPE_IERR; /* This routine should never be called */ } static t_stat x_run_cmd (int32 flag, CONST char *cptr) { return 6+SCPE_IERR; /* This routine should never be called */ } static t_stat x_help_cmd (int32 flag, CONST char *cptr); static CTAB allowed_remote_cmds[] = { { "EXAMINE", &exdep_cmd, EX_E }, { "DEPOSIT", &exdep_cmd, EX_D }, { "EVALUATE", &eval_cmd, 0 }, { "ATTACH", &attach_cmd, 0 }, { "DETACH", &detach_cmd, 0 }, { "ASSIGN", &assign_cmd, 0 }, { "DEASSIGN", &deassign_cmd, 0 }, { "CONTINUE", &x_continue_cmd, 0 }, { "REPEAT", &x_repeat_cmd, 0 }, { "COLLECT", &x_collect_cmd, 0 }, { "SAMPLEOUT",&x_sampleout_cmd, 0 }, { "STEP", &x_step_cmd, 0 }, { "PWD", &pwd_cmd, 0 }, { "SAVE", &save_cmd, 0 }, { "DIR", &dir_cmd, 0 }, { "LS", &dir_cmd, 0 }, { "ECHO", &echo_cmd, 0 }, { "SET", &set_cmd, 0 }, { "SHOW", &show_cmd, 0 }, { "HELP", &x_help_cmd, 0 }, { NULL, NULL } }; static CTAB allowed_master_remote_cmds[] = { { "EXAMINE", &exdep_cmd, EX_E }, { "DEPOSIT", &exdep_cmd, EX_D }, { "EVALUATE", &eval_cmd, 0 }, { "ATTACH", &attach_cmd, 0 }, { "DETACH", &detach_cmd, 0 }, { "ASSIGN", &assign_cmd, 0 }, { "DEASSIGN", &deassign_cmd, 0 }, { "CONTINUE", &x_continue_cmd, 0 }, { "REPEAT", &x_repeat_cmd, 0 }, { "COLLECT", &x_collect_cmd, 0 }, { "SAMPLEOUT",&x_sampleout_cmd, 0 }, { "STEP", &x_step_cmd, 0 }, { "PWD", &pwd_cmd, 0 }, { "SAVE", &save_cmd, 0 }, { "CD", &set_default_cmd, 0 }, { "DIR", &dir_cmd, 0 }, { "LS", &dir_cmd, 0 }, { "ECHO", &echo_cmd, 0 }, { "SET", &set_cmd, 0 }, { "SHOW", &show_cmd, 0 }, { "HELP", &x_help_cmd, 0 }, { "EXIT", &exit_cmd, 0 }, { "QUIT", &exit_cmd, 0 }, { "RUN", &x_run_cmd, RU_RUN }, { "GO", &x_run_cmd, RU_GO }, { "BOOT", &x_run_cmd, RU_BOOT }, { "BREAK", &brk_cmd, SSH_ST }, { "NOBREAK", &brk_cmd, SSH_CL }, { "EXPECT", &expect_cmd, 1 }, { "NOEXPECT", &expect_cmd, 0 }, { "SEND", &send_cmd, 0 }, { NULL, NULL } }; static CTAB allowed_single_remote_cmds[] = { { "ATTACH", &attach_cmd, 0 }, { "DETACH", &detach_cmd, 0 }, { "EXAMINE", &exdep_cmd, EX_E }, { "EVALUATE", &eval_cmd, 0 }, { "REPEAT", &x_repeat_cmd, 0 }, { "COLLECT", &x_collect_cmd, 0 }, { "SAMPLEOUT",&x_sampleout_cmd, 0 }, { "PWD", &pwd_cmd, 0 }, { "DIR", &dir_cmd, 0 }, { "LS", &dir_cmd, 0 }, { "ECHO", &echo_cmd, 0 }, { "SHOW", &show_cmd, 0 }, { "HELP", &x_help_cmd, 0 }, { NULL, NULL } }; static CTAB remote_only_cmds[] = { { "REPEAT", &x_repeat_cmd, 0 }, { "COLLECT", &x_collect_cmd, 0 }, { "SAMPLEOUT",&x_sampleout_cmd, 0 }, { NULL, NULL } }; static t_stat x_help_cmd (int32 flag, CONST char *cptr) { CTAB *cmdp, *cmdph; if (*cptr) { int32 saved_switches = sim_switches; t_stat r; sim_switches |= SWMASK ('F'); r = help_cmd (flag, cptr); sim_switches = saved_switches; return r; } sim_printf ("Help is available for the following Remote Console commands:\r\n"); for (cmdp=allowed_remote_cmds; cmdp->name != NULL; ++cmdp) { cmdph = find_cmd (cmdp->name); if (cmdph && cmdph->help) sim_printf (" %s\r\n", cmdp->name); } sim_printf ("Enter \"HELP cmd\" for detailed help on a command\r\n"); return SCPE_OK; } static t_stat _sim_rem_message (const char *cmd, t_stat stat) { CTAB *cmdp = NULL; t_stat stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */ cmdp = find_cmd (cmd); stat = SCPE_BARE_STATUS(stat); /* remove possible flag */ if (!stat_nomessage) { if (cmdp && (cmdp->message)) /* special message handler? */ cmdp->message (NULL, stat); /* let it deal with display */ else { if (stat >= SCPE_BASE) /* error? */ sim_printf ("%s\r\n", sim_error_text (stat)); } } return stat; } static void _sim_rem_log_out (TMLN *lp) { char cbuf[4*CBUFSIZE]; REMOTE *rem = &sim_rem_consoles[(int)(lp - sim_rem_con_tmxr.ldsc)]; int line = rem->line; if ((!sim_oline) && (sim_log)) { fflush (sim_log); sim_fseeko (sim_log, sim_rem_cmd_log_start, SEEK_SET); cbuf[sizeof(cbuf)-1] = '\0'; while (fgets (cbuf, sizeof(cbuf)-1, sim_log)) tmxr_linemsgf (lp, "%s", cbuf); } sim_oline = NULL; if ((rem->act == NULL) && (!tmxr_input_pending_ln (lp))) { int32 unwritten; do { unwritten = tmxr_send_buffered_data (lp); if (unwritten == lp->txbsz) sim_os_ms_sleep (100); } while (unwritten == lp->txbsz); } } void sim_remote_process_command (void) { char cbuf[4*CBUFSIZE], gbuf[CBUFSIZE], *argv[1] = {NULL}; CONST char *cptr; int32 saved_switches = sim_switches; t_stat stat; sim_strlcpy (cbuf, sim_rem_command_buf, sizeof (cbuf)); while (isspace(cbuf[0])) memmove (cbuf, cbuf+1, strlen(cbuf+1)+1); /* skip leading whitespace */ sim_sub_args (cbuf, sizeof(cbuf), argv); cptr = cbuf; cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ sim_rem_active_command = find_cmd (gbuf); /* find command */ if (!sim_processing_event) sim_ttcmd (); /* restore console */ stat = sim_rem_active_command->action (sim_rem_active_command->arg, cptr);/* execute command */ if (stat != SCPE_OK) stat = _sim_rem_message (gbuf, stat); /* display results */ sim_last_cmd_stat = SCPE_BARE_STATUS(stat); if (!sim_processing_event) { sim_ttrun (); /* set console mode */ sim_cancel (rem_con_data_unit); /* force immediate activation of sim_rem_con_data_svc */ sim_activate (rem_con_data_unit, -1); } sim_switches = saved_switches; /* restore original switches */ } /* Clear pending actions */ static char *sim_rem_clract (int32 line) { REMOTE *rem = &sim_rem_consoles[line]; tmxr_send_buffered_data (rem->lp); /* flush any buffered data */ return rem->act = NULL; } /* Set up pending actions */ static void sim_rem_setact (int32 line, const char *action) { if (action) { size_t act_size = strlen (action) + 1; REMOTE *rem = &sim_rem_consoles[line]; if (act_size > rem->act_buf_size) { /* expand buffer if necessary */ rem->act_buf = (char *)realloc (rem->act_buf, act_size); rem->act_buf_size = act_size; } strcpy (rem->act_buf, action); /* populate buffer */ rem->act = rem->act_buf; /* start at beginning of buffer */ } else sim_rem_clract (line); } /* Get next pending action, if any */ static char *sim_rem_getact (int32 line, char *buf, int32 size) { char *ep; size_t lnt; REMOTE *rem = &sim_rem_consoles[line]; if (rem->act == NULL) /* any action? */ return NULL; while (sim_isspace (*rem->act)) /* skip spaces */ rem->act++; if (*rem->act == 0) /* now empty? */ return sim_rem_clract (line); if ((ep = strchr (rem->act, ';'))) { /* cmd delimiter? */ lnt = ep - rem->act; /* cmd length */ memcpy (buf, rem->act, lnt + 1); /* copy with ; */ buf[lnt] = 0; /* erase ; */ rem->act += lnt + 1; /* adv ptr */ } else { strncpy (buf, rem->act, size); /* copy action */ rem->act += strlen (rem->act); /* adv ptr to end */ } return buf; } /* Parse and setup Remote Console REPEAT command: REPEAT EVERY nnn USECS Command {; command...} */ static t_stat sim_rem_repeat_cmd_setup (int32 line, CONST char **iptr) { char gbuf[CBUFSIZE]; int32 val; t_bool all_stop = FALSE; t_stat stat = SCPE_OK; CONST char *cptr = *iptr; REMOTE *rem = &sim_rem_consoles[line]; sim_debug (DBG_REP, &sim_remote_console, "Repeat Setup: %s\n", cptr); if (*cptr == 0) /* required argument? */ stat = SCPE_2FARG; else { cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ if (MATCH_CMD (gbuf, "EVERY") == 0) { cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ val = (int32) get_uint (gbuf, 10, INT_MAX, &stat); if ((stat != SCPE_OK) || (val <= 0)) /* error? */ stat = SCPE_ARG; else { cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ if ((MATCH_CMD (gbuf, "USECS") != 0) || (*cptr == 0)) stat = SCPE_ARG; else rem->repeat_interval = val; } } else { if (MATCH_CMD (gbuf, "STOP") == 0) { if (*cptr) { /* more command arguments? */ cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ if ((MATCH_CMD (gbuf, "ALL") != 0) || /* */ (*cptr != 0) || /* */ (line != 0)) /* master line? */ stat = SCPE_ARG; else all_stop = TRUE; } else rem->repeat_interval = 0; } else stat = SCPE_ARG; } } if (stat == SCPE_OK) { if (all_stop) { for (line = 0; line < sim_rem_con_tmxr.lines; line++) { rem = &sim_rem_consoles[line]; free (rem->repeat_action); rem->repeat_action = NULL; sim_cancel (rem->uptr); rem->repeat_pending = FALSE; sim_rem_clract (line); } } else { if (rem->repeat_interval != 0) { rem->repeat_action = (char *)realloc (rem->repeat_action, 1 + strlen (cptr)); strcpy (rem->repeat_action, cptr); cptr += strlen (cptr); stat = sim_activate_after (rem->uptr, rem->repeat_interval); } else { free (rem->repeat_action); rem->repeat_action = NULL; sim_cancel (rem->uptr); } rem->repeat_pending = FALSE; sim_rem_clract (line); } } *iptr = cptr; return stat; } /* Parse and setup Remote Console REPEAT command: COLLECT nnn SAMPLES EVERY nnn CYCLES reg{,reg...} */ static t_stat sim_rem_collect_cmd_setup (int32 line, CONST char **iptr) { char gbuf[CBUFSIZE]; int32 samples, cycles; t_bool all_stop = FALSE; t_stat stat = SCPE_OK; CONST char *cptr = *iptr; REMOTE *rem = &sim_rem_consoles[line]; sim_debug (DBG_SAM, &sim_remote_console, "Collect Setup: %s\n", cptr); if (*cptr == 0) /* required argument? */ return SCPE_2FARG; cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ samples = (int32) get_uint (gbuf, 10, INT_MAX, &stat); if ((stat != SCPE_OK) || (samples <= 0)) { /* error? */ if (MATCH_CMD (gbuf, "STOP") == 0) { stat = SCPE_OK; if (*cptr) { /* more command arguments? */ cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ if ((MATCH_CMD (gbuf, "ALL") != 0) || /* */ (*cptr != 0) || /* */ (line != 0)) /* master line? */ stat = SCPE_ARG; else all_stop = TRUE; } if (stat == SCPE_OK) { for (line = all_stop ? 0 : rem->line; line < (all_stop ? sim_rem_con_tmxr.lines : (rem->line + 1)); line++) { uint32 i, j; rem = &sim_rem_consoles[line]; for (i = 0; i< rem->smp_reg_count; i++) { for (j = 0; j < rem->smp_regs[i].width; j++) free (rem->smp_regs[i].bits[j].vals); free (rem->smp_regs[i].bits); } free (rem->smp_regs); rem->smp_regs = NULL; rem->smp_reg_count = 0; sim_cancel (&rem_con_smp_smpl_units[rem->line]); rem->smp_sample_interval = 0; } } } else stat = sim_messagef (SCPE_ARG, "Expected value or STOP found: %s\n", gbuf); } else { const char *tptr; cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ if (MATCH_CMD (gbuf, "SAMPLES") != 0) { *iptr = cptr; return sim_messagef (SCPE_ARG, "Expected SAMPLES found: %s\n", gbuf); } cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ if (MATCH_CMD (gbuf, "EVERY") != 0) { *iptr = cptr; return sim_messagef (SCPE_ARG, "Expected EVERY found: %s\n", gbuf); } cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ cycles = (int32) get_uint (gbuf, 10, INT_MAX, &stat); if ((stat != SCPE_OK) || (cycles <= 0)) { /* error? */ *iptr = cptr; return sim_messagef (SCPE_ARG, "Expected value found: %s\n", gbuf); } cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ if ((MATCH_CMD (gbuf, "CYCLES") != 0) || (*cptr == 0)) { *iptr = cptr; return sim_messagef (SCPE_ARG, "Expected CYCLES found: %s\n", gbuf); } tptr = strcpy (gbuf, "STOP"); /* Start from a clean slate */ sim_rem_collect_cmd_setup (rem->line, &tptr); rem->smp_sample_interval = cycles; rem->smp_reg_count = 0; while (cptr && *cptr) { const char *comma = strchr (cptr, ','); char tbuf[2*CBUFSIZE]; uint32 bit, width; REG *reg; int32 saved_switches = sim_switches; t_bool indirect = FALSE; BITSAMPLE_REG *smp_regs; if (comma) { strncpy (tbuf, cptr, comma - cptr); tbuf[comma - cptr] = '\0'; cptr = comma + 1; } else { strcpy (tbuf, cptr); cptr += strlen (cptr); } tptr = tbuf; if (strchr (tbuf, ' ')) { sim_switches = 0; tptr = get_sim_opt (CMD_OPT_SW|CMD_OPT_DFT, tbuf, &stat); /* get switches and device */ indirect = ((sim_switches & SWMASK('I')) != 0); sim_switches = saved_switches; } if (stat != SCPE_OK) break; tptr = get_glyph (tptr, gbuf, 0); /* get next glyph */ reg = find_reg (gbuf, &tptr, sim_dfdev); if (reg == NULL) { stat = sim_messagef (SCPE_NXREG, "Nonexistent Register: %s\n", gbuf); break; } smp_regs = (BITSAMPLE_REG *)realloc (rem->smp_regs, (rem->smp_reg_count + 1) * sizeof(*smp_regs)); if (smp_regs == NULL) { stat = SCPE_MEM; break; } rem->smp_regs = smp_regs; smp_regs[rem->smp_reg_count].reg = reg; smp_regs[rem->smp_reg_count].dptr = sim_dfdev; smp_regs[rem->smp_reg_count].uptr = sim_dfunit; smp_regs[rem->smp_reg_count].indirect = indirect; width = indirect ? sim_dfdev->dwidth : reg->width; smp_regs[rem->smp_reg_count].width = width; smp_regs[rem->smp_reg_count].bits = (BITSAMPLE *)calloc (width, sizeof (*smp_regs[rem->smp_reg_count - 1].bits)); if (smp_regs[rem->smp_reg_count].bits == NULL) { stat = SCPE_MEM; break; } rem->smp_reg_count += 1; for (bit = 0; bit < width; bit++) { smp_regs[rem->smp_reg_count - 1].bits[bit].depth = samples; smp_regs[rem->smp_reg_count - 1].bits[bit].vals = (int *)calloc (samples, sizeof (int)); if (smp_regs[rem->smp_reg_count - 1].bits[bit].vals == NULL) { stat = SCPE_MEM; break; } } if (stat != SCPE_OK) break; } if (stat != SCPE_OK) { /* Error? */ *iptr = cptr; cptr = strcpy (gbuf, "STOP"); sim_rem_collect_cmd_setup (line, &cptr);/* Cleanup mess */ return stat; } sim_activate (&rem_con_smp_smpl_units[rem->line], rem->smp_sample_interval); } *iptr = cptr; return stat; } t_stat sim_rem_con_repeat_svc (UNIT *uptr) { int line = uptr - rem_con_repeat_units; REMOTE *rem = &sim_rem_consoles[line]; sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_repeat_svc(line=%d) - interval=%d\n", line, rem->repeat_interval); if (rem->repeat_interval) { rem->repeat_pending = TRUE; sim_activate_after (uptr, rem->repeat_interval); /* reschedule */ sim_activate_abs (rem_con_data_unit, -1); /* wake up to process */ } return SCPE_OK; } static void sim_rem_record_reg_bit (BITSAMPLE *bit, int val) { bit->tot -= bit->vals[bit->ptr]; /* remove retired value */ bit->tot += val; /* accumulate new value */ bit->vals[bit->ptr] = val; /* save new value */ ++bit->ptr; /* increment next pointer */ if (bit->ptr >= bit->depth) /* if too big */ bit->ptr = 0; /* wrap around */ } static void sim_rem_set_reg_bit (BITSAMPLE *bit, int val) { int i; bit->tot = bit->depth * val; /* compute total */ for (i = 0; i < bit->depth; i++) /* set all value bits */ bit->vals[i] = val; } static void sim_rem_collect_reg_bits (BITSAMPLE_REG *reg) { uint32 i; t_value val = get_rval (reg->reg, 0); if (reg->indirect) val = get_aval ((t_addr)val, reg->dptr, reg->uptr); val = val >> reg->reg->offset; for (i = 0; i < reg->width; i++) { if (sim_is_running) sim_rem_record_reg_bit (®->bits[i], val&1); else sim_rem_set_reg_bit (®->bits[i], val&1); val = val >> 1; } } static void sim_rem_collect_registers (REMOTE *rem) { uint32 i; for (i = 0; i < rem->smp_reg_count; i++) sim_rem_collect_reg_bits (&rem->smp_regs[i]); } static void sim_rem_collect_all_registers (void) { int32 line; for (line = 0; line < sim_rem_con_tmxr.lines; line++) sim_rem_collect_registers (&sim_rem_consoles[line]); } t_stat sim_rem_con_smp_collect_svc (UNIT *uptr) { int line = uptr - rem_con_smp_smpl_units; REMOTE *rem = &sim_rem_consoles[line]; sim_debug (DBG_SAM, &sim_remote_console, "sim_rem_con_smp_collect_svc(line=%d) - interval=%d\n", line, rem->smp_sample_interval); if (rem->smp_sample_interval && (rem->smp_reg_count != 0)) { sim_rem_collect_registers (rem); sim_activate (uptr, rem->smp_sample_interval); /* reschedule */ } return SCPE_OK; } /* Unit service for remote console data polling */ t_stat sim_rem_con_data_svc (UNIT *uptr) { int32 i, j, c = 0; t_stat stat = SCPE_OK; t_bool active_command = FALSE; int32 steps = 0; t_bool was_active_command = (sim_rem_cmd_active_line != -1); t_bool got_command; t_bool close_session = FALSE; TMLN *lp; char cbuf[4*CBUFSIZE], gbuf[CBUFSIZE], *argv[1] = {NULL}; CONST char *cptr; CTAB *cmdp = NULL; CTAB *basecmdp = NULL; uint32 read_start_time = 0; tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */ for (i=(was_active_command ? sim_rem_cmd_active_line : 0); (i < sim_rem_con_tmxr.lines) && (!active_command); i++) { REMOTE *rem = &sim_rem_consoles[i]; t_bool master_session = (sim_rem_master_mode && (i == 0)); lp = rem->lp; if (!lp->conn) { if (rem->repeat_interval) { /* was repeated enabled? */ cptr = strcpy (gbuf, "STOP"); sim_rem_repeat_cmd_setup (i, &cptr); /* make sure it is now disabled */ } if (rem->smp_reg_count) { /* were bit samples being collected? */ cptr = strcpy (gbuf, "STOP"); sim_rem_collect_cmd_setup (i, &cptr); /* make sure it is now disabled */ } continue; } if (master_session && !sim_rem_master_was_connected) { tmxr_linemsgf (lp, "\nMaster Mode Session\r\n"); tmxr_send_buffered_data (lp); /* flush any buffered data */ } sim_rem_master_was_connected |= master_session; /* Remember if master ever connected */ stat = SCPE_OK; if ((was_active_command) || (master_session && !rem->single_mode)) { sim_debug (DBG_MOD, &sim_remote_console, "Session: %d %s %s\n", i, was_active_command ? "Was Active" : "", (master_session && !rem->single_mode) ? "master_session && !single_mode" : ""); if (was_active_command) { sim_rem_cmd_active_line = -1; /* Done with active command */ if (!sim_rem_active_command) { /* STEP command? */ stat = SCPE_STEP; _sim_rem_message ("STEP", stat); /* produce a STEP complete message */ } _sim_rem_log_out (lp); sim_rem_active_command = NULL; /* Restart loop to process available input */ was_active_command = FALSE; i = -1; continue; } else { sim_is_running = 0; sim_rem_collect_all_registers (); sim_stop_timer_services (); for (j=0; j < sim_rem_con_tmxr.lines; j++) { TMLN *lpj = &sim_rem_con_tmxr.ldsc[j]; if ((i == j) || (!lpj->conn)) continue; tmxr_linemsgf (lpj, "\nRemote Master Console(%s) Entering Commands\n", lp->ipad); tmxr_send_buffered_data (lpj); /* flush any buffered data */ } } } else { if ((!rem->repeat_pending) || (rem->buf_ptr != 0)) { c = tmxr_getc_ln (lp); if (!(TMXR_VALID & c)) continue; c = c & ~TMXR_VALID; if (rem->single_mode) { if (c == sim_int_char) { /* ^E (the interrupt character) must start continue mode console interaction */ rem->single_mode = FALSE; /* enter multi command mode */ sim_is_running = 0; sim_rem_collect_all_registers (); sim_stop_timer_services (); stat = SCPE_STOP; _sim_rem_message ("RUN", stat); _sim_rem_log_out (lp); for (j=0; j < sim_rem_con_tmxr.lines; j++) { TMLN *lpj = &sim_rem_con_tmxr.ldsc[j]; if ((i == j) || (!lpj->conn)) continue; tmxr_linemsgf (lpj, "\nRemote Console %d(%s) Entering Commands\n", i, lp->ipad); tmxr_send_buffered_data (lpj); /* flush any buffered data */ } lp = &sim_rem_con_tmxr.ldsc[i]; if (!master_session) tmxr_linemsg (lp, "\r\nSimulator paused.\r\n"); if (!master_session && rem->read_timeout) { tmxr_linemsgf (lp, "Simulation will resume automatically if input is not received in %d seconds\n", sim_rem_read_timeouts[i]); tmxr_linemsgf (lp, "\r\n"); tmxr_send_buffered_data (lp); /* flush any buffered data */ } } else { if ((rem->buf_ptr == 0) && /* At beginning of input line */ ((c == '\n') || /* Ignore bare LF between commands (Microsoft Telnet bug) */ (c == '\r'))) /* Ignore empty commands */ continue; if ((c == '\004') || (c == '\032')) {/* EOF character (^D or ^Z) ? */ tmxr_linemsgf (lp, "\r\nGoodbye\r\n"); tmxr_send_buffered_data (lp); /* flush any buffered data */ tmxr_reset_ln (lp); continue; } if (rem->buf_ptr == 0) { /* we just picked up the first character on a command line */ if (!master_session) tmxr_linemsgf (lp, "\r\n%s", sim_prompt); else tmxr_linemsgf (lp, "\r\n%s", sim_is_running ? "SIM> " : "sim> "); sim_debug (DBG_XMT, &sim_remote_console, "Prompt Written: %s\n", sim_is_running ? "SIM> " : "sim> "); if ((rem->act == NULL) && (!tmxr_input_pending_ln (lp))) tmxr_send_buffered_data (lp);/* flush any buffered data */ } } } } } got_command = FALSE; while (1) { if (stat == SCPE_EXIT) return stat|SCPE_NOMESSAGE; if (!rem->single_mode) { read_start_time = sim_os_msec(); if (master_session) tmxr_linemsg (lp, "sim> "); else tmxr_linemsg (lp, sim_prompt); tmxr_send_buffered_data (lp); /* flush any buffered data */ } do { if (rem->buf_ptr == 0) { if (sim_rem_getact (i, rem->buf, rem->buf_size)) { if (!master_session) tmxr_linemsgf (lp, "%s%s\n", sim_prompt, rem->buf); else tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", rem->buf); rem->buf_ptr = strlen (rem->repeat_action); got_command = TRUE; break; } else { if (rem->repeat_pending) { rem->repeat_pending = FALSE; sim_rem_setact (i, rem->repeat_action); sim_rem_getact (i, rem->buf, rem->buf_size); if (!master_session) tmxr_linemsgf (lp, "%s%s\n", sim_prompt, rem->buf); else tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", rem->buf); rem->buf_ptr = strlen (rem->repeat_action); got_command = TRUE; break; } } } if (!rem->single_mode) { c = tmxr_getc_ln (lp); if (!(TMXR_VALID & c)) { tmxr_send_buffered_data (lp); /* flush any buffered data */ if (!master_session && rem->read_timeout && ((sim_os_msec() - read_start_time)/1000 >= rem->read_timeout)) { while (rem->buf_ptr > 0) { /* Erase current input line */ tmxr_linemsg (lp, "\b \b"); --rem->buf_ptr; } if (rem->buf_ptr+80 >= rem->buf_size) { rem->buf_size += 1024; rem->buf = (char *)realloc (rem->buf, rem->buf_size); } strcpy (rem->buf, "CONTINUE ! Automatic continue due to timeout"); tmxr_linemsgf (lp, "%s\n", rem->buf); got_command = TRUE; break; } sim_os_ms_sleep (50); tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */ if (!lp->conn) { /* if connection lost? */ rem->single_mode = TRUE; /* No longer multi-command more */ break; /* done waiting */ } continue; } read_start_time = sim_os_msec(); c = c & ~TMXR_VALID; } switch (c) { case 0: /* no data */ break; case '\b': /* Backspace */ case 127: /* Rubout */ if (rem->buf_ptr > 0) { tmxr_linemsg (lp, "\b \b"); --rem->buf_ptr; } break; case 27: /* escape */ case 21: /* ^U */ while (rem->buf_ptr > 0) { tmxr_linemsg (lp, "\b \b"); --rem->buf_ptr; } break; case '\n': if (rem->buf_ptr == 0) break; case '\r': tmxr_linemsg (lp, "\r\n"); if (rem->buf_ptr+1 >= rem->buf_size) { rem->buf_size += 1024; rem->buf = (char *)realloc (rem->buf, rem->buf_size); } rem->buf[rem->buf_ptr++] = '\0'; sim_debug (DBG_RCV, &sim_remote_console, "Got Command (%d bytes still in buffer): %s\n", tmxr_input_pending_ln (lp), rem->buf); got_command = TRUE; break; case '\004': /* EOF (^D) */ case '\032': /* EOF (^Z) */ while (rem->buf_ptr > 0) { /* Erase current input line */ tmxr_linemsg (lp, "\b \b"); --rem->buf_ptr; } if (!rem->single_mode) { if (rem->buf_ptr+80 >= rem->buf_size) { rem->buf_size += 1024; rem->buf = (char *)realloc (rem->buf, rem->buf_size); } strcpy (rem->buf, "CONTINUE ! Automatic continue before close"); tmxr_linemsgf (lp, "%s\n", rem->buf); got_command = TRUE; } close_session = TRUE; break; default: tmxr_putc_ln (lp, c); if (rem->buf_ptr+2 >= rem->buf_size) { rem->buf_size += 1024; rem->buf = (char *)realloc (rem->buf, rem->buf_size); } rem->buf[rem->buf_ptr++] = (char)c; rem->buf[rem->buf_ptr] = '\0'; if (((size_t)rem->buf_ptr) >= sizeof(cbuf)) got_command = TRUE; /* command too long */ break; } c = 0; if ((!got_command) && (rem->single_mode) && (tmxr_input_pending_ln (lp))) { c = tmxr_getc_ln (lp); c = c & ~TMXR_VALID; } } while ((!got_command) && ((!rem->single_mode) || c)); if ((rem->act == NULL) && (!tmxr_input_pending_ln (lp))) tmxr_send_buffered_data (lp); /* flush any buffered data */ if ((rem->single_mode) && !got_command) { break; } if (!sim_rem_master_mode) sim_printf ("Remote Console Command from %s> %s\r\n", lp->ipad, rem->buf); got_command = FALSE; if (strlen(rem->buf) >= sizeof(cbuf)) { sim_printf ("\r\nLine too long. Ignored. Continuing Simulator execution\r\n"); tmxr_linemsgf (lp, "\nLine too long. Ignored. Continuing Simulator execution\n"); tmxr_send_buffered_data (lp); /* try to flush any buffered data */ break; } strcpy (cbuf, rem->buf); rem->buf_ptr = 0; rem->buf[rem->buf_ptr] = '\0'; while (isspace(cbuf[0])) memmove (cbuf, cbuf+1, strlen(cbuf+1)+1); /* skip leading whitespace */ if (cbuf[0] == '\0') { if (rem->single_mode) { rem->single_mode = FALSE; break; } else continue; } strcpy (sim_rem_command_buf, cbuf); sim_sub_args (cbuf, sizeof(cbuf), argv); cptr = cbuf; cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ sim_switches = 0; /* init switches */ sim_rem_active_number = i; if (!sim_log) { /* Not currently logging? */ int32 save_quiet = sim_quiet; sim_quiet = 1; sprintf (sim_rem_con_temp_name, "sim_remote_console_%d.temporary_log", (int)getpid()); sim_set_logon (0, sim_rem_con_temp_name); sim_quiet = save_quiet; sim_log_temp = TRUE; } sim_rem_cmd_log_start = sim_ftell (sim_log); basecmdp = find_cmd (gbuf); /* validate basic command */ if (basecmdp == NULL) basecmdp = find_ctab (remote_only_cmds, gbuf);/* validate basic command */ if (basecmdp == NULL) { if ((gbuf[0] == ';') || (gbuf[0] == '#')) { /* ignore comment */ sim_rem_cmd_active_line = i; was_active_command = TRUE; sim_rem_active_command = &allowed_single_remote_cmds[0];/* Dummy */ i = i - 1; break; } else stat = SCPE_UNK; } else { if ((cmdp = find_ctab (rem->single_mode ? allowed_single_remote_cmds : (master_session ? allowed_master_remote_cmds : allowed_remote_cmds), gbuf))) {/* lookup command */ sim_debug (DBG_CMD, &sim_remote_console, "gbuf='%s', basecmd='%s', cmd='%s'\n", gbuf, basecmdp->name, cmdp->name); if (cmdp->action == &x_continue_cmd) { sim_debug (DBG_CMD, &sim_remote_console, "continue_cmd executing\n"); stat = SCPE_OK; } else { if (cmdp->action == &exit_cmd) return SCPE_EXIT; if (cmdp->action == &x_step_cmd) { sim_debug (DBG_CMD, &sim_remote_console, "step_cmd executing\n"); steps = 1; /* default of 1 instruction */ stat = SCPE_OK; if (*cptr != 0) { /* argument? */ cptr = get_glyph (cptr, gbuf, 0);/* get next glyph */ if (*cptr != 0) /* should be end */ stat = SCPE_2MARG; else { steps = (int32) get_uint (gbuf, 10, INT_MAX, &stat); if ((stat != SCPE_OK) || (steps <= 0)) /* error? */ stat = SCPE_ARG; } } if (stat != SCPE_OK) cmdp = NULL; } else { if (cmdp->action == &x_run_cmd) { sim_debug (DBG_CMD, &sim_remote_console, "run_cmd executing\n"); if (sim_con_stable_registers && /* can we process command now? */ sim_rem_master_mode) sim_oline = lp; /* specify output socket */ sim_switches |= SIM_SW_HIDE; /* Request Setup only */ stat = basecmdp->action (cmdp->arg, cptr); sim_switches &= ~SIM_SW_HIDE; /* Done with Setup only mode */ if (stat == SCPE_OK) { /* switch to CONTINUE after x_run_cmd() did RUN setup */ cmdp = find_ctab (allowed_master_remote_cmds, "CONTINUE"); } } else { if (cmdp->action == &x_sampleout_cmd) { sim_debug (DBG_CMD, &sim_remote_console, "sampleout_cmd executing\n"); sim_oline = lp; /* specify output socket */ stat = sim_rem_sample_output (NULL, i); } else { if (cmdp->action == &x_repeat_cmd) { sim_debug (DBG_CMD, &sim_remote_console, "repeat_cmd executing\n"); stat = sim_rem_repeat_cmd_setup (i, &cptr); } else { if (cmdp->action == &x_collect_cmd) { sim_debug (DBG_CMD, &sim_remote_console, "sample_cmd executing\n"); stat = sim_rem_collect_cmd_setup (i, &cptr); } else { if (sim_con_stable_registers && sim_rem_master_mode) { /* can we process command now? */ sim_debug (DBG_CMD, &sim_remote_console, "Processing Command directly\n"); sim_oline = lp; /* specify output socket */ sim_remote_process_command (); stat = SCPE_OK; /* any message has already been emitted */ } else { sim_debug (DBG_CMD, &sim_remote_console, "Processing Command via SCPE_REMOTE\n"); stat = SCPE_REMOTE; /* force processing outside of sim_instr() */ } } } } } } } } else stat = SCPE_INVREM; } sim_rem_active_number = -1; if ((stat != SCPE_OK) && (stat != SCPE_REMOTE)) stat = _sim_rem_message (gbuf, stat); _sim_rem_log_out (lp); if (master_session && !sim_rem_master_mode) { rem->single_mode = TRUE; return SCPE_STOP; } if (cmdp && (cmdp->action == &x_continue_cmd)) { sim_rem_cmd_active_line = -1; /* Not active_command */ if (sim_log_temp && /* If we setup a temporary log, clean it now */ (!sim_rem_master_mode)) { int32 save_quiet = sim_quiet; sim_quiet = 1; sim_set_logoff (0, NULL); sim_quiet = save_quiet; (void)remove (sim_rem_con_temp_name); sim_log_temp = FALSE; } else { fflush (sim_log); sim_rem_cmd_log_start = sim_ftell (sim_log); } if (!rem->single_mode) { tmxr_linemsg (lp, "Simulator Running..."); tmxr_send_buffered_data (lp); for (j=0; j < sim_rem_con_tmxr.lines; j++) { TMLN *lpj = &sim_rem_con_tmxr.ldsc[j]; if ((i == j) || (!lpj->conn)) continue; tmxr_linemsg (lpj, "Simulator Running..."); tmxr_send_buffered_data (lpj); } sim_is_running = 1; sim_start_timer_services (); } if (cmdp && (cmdp->action == &x_continue_cmd)) rem->single_mode = TRUE; else { if (!rem->single_mode) { if (master_session) tmxr_linemsgf (lp, "%s", "sim> "); else tmxr_linemsgf (lp, "%s", sim_prompt); tmxr_send_buffered_data (lp); } } break; } if ((cmdp && (cmdp->action == &x_step_cmd)) || (stat == SCPE_REMOTE)) { sim_rem_cmd_active_line = i; break; } } if (close_session) { tmxr_linemsgf (lp, "\r\nGoodbye\r\n"); tmxr_send_buffered_data (lp); /* flush any buffered data */ tmxr_reset_ln (lp); rem->single_mode = FALSE; } } if (sim_rem_master_was_connected && /* Master mode ever connected? */ !sim_rem_con_tmxr.ldsc[0].sock) /* Master Connection lost? */ return SCPE_EXIT; /* simulator has been 'unplugged' */ if (sim_rem_cmd_active_line != -1) { if (steps) sim_activate(uptr, steps); /* check again after 'steps' instructions */ else return SCPE_REMOTE; /* force sim_instr() to exit to process command */ } else sim_activate_after(uptr, 100000); /* check again in 100 milliaeconds */ if (sim_rem_master_was_enabled && !sim_rem_master_mode) { /* Transitioning out of master mode? */ lp = &sim_rem_con_tmxr.ldsc[0]; tmxr_linemsgf (lp, "Non Master Mode Session..."); /* report transition */ tmxr_send_buffered_data (lp); /* flush any buffered data */ return SCPE_STOP|SCPE_NOMESSAGE; /* Unwind to the normal input path */ } else return SCPE_OK; /* keep going */ } t_stat sim_rem_con_reset (DEVICE *dptr) { if (sim_rem_con_tmxr.lines) { int32 i; sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_reset(lines=%d)\n", sim_rem_con_tmxr.lines); for (i=0; i<sim_rem_con_tmxr.lines; i++) { REMOTE *rem = &sim_rem_consoles[i]; if (!sim_rem_con_tmxr.ldsc[i].conn) continue; sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_reset(line=%d, usecs=%d)\n", i, rem->repeat_interval); if (rem->repeat_interval) sim_activate_after (&rem_con_repeat_units[rem->line], rem->repeat_interval); /* schedule */ if (rem->smp_reg_count) sim_activate (&rem_con_smp_smpl_units[rem->line], rem->smp_sample_interval); /* schedule */ } if (i != sim_rem_con_tmxr.lines) sim_activate_after (rem_con_data_unit, 100000); /* continue polling for open sessions */ return sim_rem_con_poll_svc (rem_con_poll_unit); /* establish polling for new sessions */ } return SCPE_OK; } static t_stat sim_set_rem_telnet (int32 flag, CONST char *cptr) { t_stat r; if (flag) { r = sim_parse_addr (cptr, NULL, 0, NULL, NULL, 0, NULL, NULL); if (r == SCPE_OK) { if (sim_rem_con_tmxr.master) /* already open? */ sim_set_rem_telnet (0, NULL); /* close first */ if (sim_rem_con_tmxr.lines == 0) /* Ir no connection limit set */ sim_set_rem_connections (0, "1"); /* use 1 */ sim_rem_con_tmxr.buffered = 8192; /* Use big enough buffers */ sim_register_internal_device (&sim_remote_console); r = tmxr_attach (&sim_rem_con_tmxr, rem_con_poll_unit, cptr);/* open master socket */ if (r == SCPE_OK) sim_activate_after(rem_con_poll_unit, 1000000);/* check for connection in 1 second */ return r; } return SCPE_NOPARAM; } else { if (sim_rem_con_tmxr.master) { int32 i; tmxr_detach (&sim_rem_con_tmxr, rem_con_poll_unit); for (i=0; i<sim_rem_con_tmxr.lines; i++) { REMOTE *rem = &sim_rem_consoles[i]; free (rem->buf); rem->buf = NULL; rem->buf_size = 0; rem->buf_ptr = 0; rem->single_mode = TRUE; } } } return SCPE_OK; } static t_stat sim_set_rem_connections (int32 flag, CONST char *cptr) { int32 lines; REMOTE *rem; t_stat r; int32 i; if (cptr == NULL) return SCPE_ARG; lines = (int32) get_uint (cptr, 10, MAX_REMOTE_SESSIONS, &r); if (r != SCPE_OK) return r; if (sim_rem_con_tmxr.master) return SCPE_ALATT; if (sim_rem_con_tmxr.lines) { sim_cancel (rem_con_poll_unit); sim_cancel (rem_con_data_unit); } for (i=0; i<sim_rem_con_tmxr.lines; i++) { rem = &sim_rem_consoles[i]; free (rem->buf); free (rem->act_buf); free (rem->act); free (rem->repeat_action); sim_cancel (&rem_con_repeat_units[i]); sim_cancel (&rem_con_smp_smpl_units[i]); } sim_rem_con_tmxr.lines = lines; sim_rem_con_tmxr.ldsc = (TMLN *)realloc (sim_rem_con_tmxr.ldsc, sizeof(*sim_rem_con_tmxr.ldsc)*lines); memset (sim_rem_con_tmxr.ldsc, 0, sizeof(*sim_rem_con_tmxr.ldsc)*lines); sim_remote_console.units = (UNIT *)realloc (sim_remote_console.units, sizeof(*sim_remote_console.units)*((2 * lines) + REM_CON_BASE_UNITS)); memset (sim_remote_console.units, 0, sizeof(*sim_remote_console.units)*((2 * lines) + REM_CON_BASE_UNITS)); sim_remote_console.numunits = (2 * lines) + REM_CON_BASE_UNITS; rem_con_poll_unit->action = &sim_rem_con_poll_svc;/* remote console connection polling unit */ rem_con_poll_unit->flags |= UNIT_IDLE; rem_con_data_unit->action = &sim_rem_con_data_svc;/* console data handling unit */ rem_con_data_unit->flags |= UNIT_IDLE|UNIT_DIS; sim_rem_consoles = (REMOTE *)realloc (sim_rem_consoles, sizeof(*sim_rem_consoles)*lines); memset (sim_rem_consoles, 0, sizeof(*sim_rem_consoles)*lines); sim_rem_command_buf = (char *)realloc (sim_rem_command_buf, 4*CBUFSIZE+1); memset (sim_rem_command_buf, 0, 4*CBUFSIZE+1); for (i=0; i<lines; i++) { rem_con_repeat_units[i].flags = UNIT_DIS; rem_con_repeat_units[i].action = &sim_rem_con_repeat_svc; rem_con_smp_smpl_units[i].flags = UNIT_DIS; rem_con_smp_smpl_units[i].action = &sim_rem_con_smp_collect_svc; rem = &sim_rem_consoles[i]; rem->line = i; rem->lp = &sim_rem_con_tmxr.ldsc[i]; rem->uptr = &rem_con_repeat_units[i]; } return SCPE_OK; } static t_stat sim_set_rem_timeout (int32 flag, CONST char *cptr) { int32 timeout; t_stat r; if (cptr == NULL) return SCPE_ARG; timeout = (int32) get_uint (cptr, 10, 3600, &r); if (r != SCPE_OK) return r; if (sim_rem_active_number >= 0) sim_rem_consoles[sim_rem_active_number].read_timeout = timeout; else sim_rem_read_timeout = timeout; return SCPE_OK; } static t_stat sim_set_rem_bufsize (int32 flag, CONST char *cptr) { char cmdbuf[CBUFSIZE]; int32 bufsize; t_stat r; if (cptr == NULL) return SCPE_ARG; bufsize = (int32) get_uint (cptr, 10, 32768, &r); if (r != SCPE_OK) return r; if (bufsize < 1400) return sim_messagef (SCPE_ARG, "%d is too small. Minimum size is 1400\n", bufsize); sprintf(cmdbuf, "BUFFERED=%d", bufsize); return tmxr_open_master (&sim_rem_con_tmxr, cmdbuf); /* open master socket */ } /* Enable or disable Remote Console master mode */ /* In master mode, commands are subsequently processed from the primary/initial (master mode) remote console session. Commands are processed from that source until that source disables master mode or the simulator exits */ static t_stat sim_set_rem_master (int32 flag, CONST char *cptr) { t_stat stat = SCPE_OK; if (cptr && *cptr) return SCPE_2MARG; if (sim_rem_active_number > 0) { sim_printf ("Can't change Remote Console mode from Remote Console\n"); return SCPE_INVREM; } if (sim_rem_con_tmxr.master || (!flag)) /* Remote Console Enabled? */ sim_rem_master_mode = flag; else { sim_printf ("Can't enable Remote Console Master mode with Remote Console disabled\n"); return SCPE_INVREM; } if (sim_rem_master_mode) { t_stat stat_nomessage; sim_printf ("Command input starting on Master Remote Console Session\n"); stat = sim_run_boot_prep (0); sim_rem_master_was_enabled = TRUE; while (sim_rem_master_mode) { sim_rem_consoles[0].single_mode = FALSE; sim_cancel (rem_con_data_unit); sim_activate (rem_con_data_unit, -1); stat = run_cmd (RU_GO, ""); if (stat != SCPE_TTMO) { stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */ stat = _sim_rem_message ("RUN", stat); } if (stat == SCPE_EXIT) sim_rem_master_mode = FALSE; } sim_rem_master_was_enabled = FALSE; sim_rem_master_was_connected = FALSE; if (sim_log_temp) { /* If we setup a temporary log, clean it now */ int32 save_quiet = sim_quiet; sim_quiet = 1; sim_set_logoff (0, NULL); sim_quiet = save_quiet; (void)remove (sim_rem_con_temp_name); sim_log_temp = FALSE; } stat |= stat_nomessage; } else { sim_rem_consoles[0].single_mode = TRUE; /* Force remote session into single command mode */ } return stat; } /* Set keyboard map */ t_stat sim_set_kmap (int32 flag, CONST char *cptr) { DEVICE *dptr = sim_devices[0]; int32 val, rdx; t_stat r; if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; if (dptr->dradix == 16) rdx = 16; else rdx = 8; val = (int32) get_uint (cptr, rdx, 0177, &r); if ((r != SCPE_OK) || ((val == 0) && (flag & KMAP_NZ))) return SCPE_ARG; *(cons_kmap[flag & KMAP_MASK]) = val; return SCPE_OK; } /* Show keyboard map */ t_stat sim_show_kmap (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { if (sim_devices[0]->dradix == 16) fprintf (st, "%s = %X\n", show_con_tab[flag].name, *(cons_kmap[flag & KMAP_MASK])); else fprintf (st, "%s = %o\n", show_con_tab[flag].name, *(cons_kmap[flag & KMAP_MASK])); return SCPE_OK; } /* Set printable characters */ t_stat sim_set_pchar (int32 flag, CONST char *cptr) { DEVICE *dptr = sim_devices[0]; uint32 val, rdx; t_stat r; if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; if (dptr->dradix == 16) rdx = 16; else rdx = 8; val = (uint32) get_uint (cptr, rdx, 0xFFFFFFFF, &r); if ((r != SCPE_OK) || ((val & 0x00002400) == 0)) return SCPE_ARG; sim_tt_pchar = val; return SCPE_OK; } /* Show printable characters */ t_stat sim_show_pchar (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { if (sim_devices[0]->dradix == 16) fprintf (st, "pchar mask = %X", sim_tt_pchar); else fprintf (st, "pchar mask = %o", sim_tt_pchar); if (sim_tt_pchar) { static const char *pchars[] = {"NUL(^@)", "SOH(^A)", "STX(^B)", "ETX(^C)", "EOT(^D)", "ENQ(^E)", "ACK(^F)", "BEL(^G)", "BS(^H)" , "HT(^I)", "LF(^J)", "VT(^K)", "FF(^L)", "CR(^M)", "SO(^N)", "SI(^O)", "DLE(^P)", "DC1(^Q)", "DC2(^R)", "DC3(^S)", "DC4(^T)", "NAK(^U)", "SYN(^V)", "ETB(^W)", "CAN(^X)", "EM(^Y)", "SUB(^Z)", "ESC", "FS", "GS", "RS", "US"}; int i; t_bool found = FALSE; fprintf (st, " {"); for (i=31; i>=0; i--) if (sim_tt_pchar & (1 << i)) { fprintf (st, "%s%s", found ? "," : "", pchars[i]); found = TRUE; } fprintf (st, "}"); } fprintf (st, "\n"); return SCPE_OK; } /* Set input speed (bps) */ t_stat sim_set_cons_speed (int32 flag, CONST char *cptr) { return tmxr_set_line_speed (&sim_con_ldsc, cptr); } t_stat sim_show_cons_speed (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { if (sim_con_ldsc.rxbps) { fprintf (st, "Speed = %d", sim_con_ldsc.rxbps); if (sim_con_ldsc.rxbpsfactor != TMXR_RX_BPS_UNIT_SCALE) fprintf (st, "*%.0f", sim_con_ldsc.rxbpsfactor/TMXR_RX_BPS_UNIT_SCALE); fprintf (st, " bps\n"); } return SCPE_OK; } /* Set log routine */ t_stat sim_set_logon (int32 flag, CONST char *cptr) { char gbuf[CBUFSIZE]; t_stat r; time_t now; if ((cptr == NULL) || (*cptr == 0)) /* need arg */ return SCPE_2FARG; cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */ if (*cptr != 0) /* now eol? */ return SCPE_2MARG; sim_set_logoff (0, NULL); /* close cur log */ r = sim_open_logfile (gbuf, FALSE, &sim_log, &sim_log_ref); /* open log */ if (r != SCPE_OK) /* error? */ return r; if (!sim_quiet) fprintf (stdout, "Logging to file \"%s\"\n", sim_logfile_name (sim_log, sim_log_ref)); fprintf (sim_log, "Logging to file \"%s\"\n", sim_logfile_name (sim_log, sim_log_ref)); /* start of log */ time(&now); fprintf (sim_log, "Logging to file \"%s\" at %s", sim_logfile_name (sim_log, sim_log_ref), ctime(&now)); return SCPE_OK; } /* Set nolog routine */ t_stat sim_set_logoff (int32 flag, CONST char *cptr) { if (cptr && (*cptr != 0)) /* now eol? */ return SCPE_2MARG; if (sim_log == NULL) /* no log? */ return SCPE_OK; if (!sim_quiet) fprintf (stdout, "Log file closed\n"); fprintf (sim_log, "Log file closed\n"); sim_close_logfile (&sim_log_ref); /* close log */ sim_log = NULL; return SCPE_OK; } /* Show log status */ t_stat sim_show_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { if (cptr && (*cptr != 0)) return SCPE_2MARG; if (sim_log) fprintf (st, "Logging enabled to \"%s\"\n", sim_logfile_name (sim_log, sim_log_ref)); else fprintf (st, "Logging disabled\n"); return SCPE_OK; } /* Set debug routine */ t_stat sim_set_debon (int32 flag, CONST char *cptr) { char gbuf[CBUFSIZE]; t_stat r; time_t now; sim_deb_switches = sim_switches; /* save debug switches */ if ((cptr == NULL) || (*cptr == 0)) /* need arg */ return SCPE_2FARG; cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */ if (*cptr != 0) /* now eol? */ return SCPE_2MARG; r = sim_open_logfile (gbuf, FALSE, &sim_deb, &sim_deb_ref); if (r != SCPE_OK) return r; if (sim_deb_switches & SWMASK ('R')) { clock_gettime(CLOCK_REALTIME, &sim_deb_basetime); if (!(sim_deb_switches & (SWMASK ('A') | SWMASK ('T')))) sim_deb_switches |= SWMASK ('T'); } if (!sim_quiet) { sim_printf ("Debug output to \"%s\"\n", sim_logfile_name (sim_deb, sim_deb_ref)); if (sim_deb_switches & SWMASK ('P')) sim_printf (" Debug messages contain current PC value\n"); if (sim_deb_switches & SWMASK ('T')) sim_printf (" Debug messages display time of day as hh:mm:ss.msec%s\n", sim_deb_switches & SWMASK ('R') ? " relative to the start of debugging" : ""); if (sim_deb_switches & SWMASK ('A')) sim_printf (" Debug messages display time of day as seconds.msec%s\n", sim_deb_switches & SWMASK ('R') ? " relative to the start of debugging" : ""); time(&now); fprintf (sim_deb, "Debug output to \"%s\" at %s", sim_logfile_name (sim_deb, sim_deb_ref), ctime(&now)); show_version (sim_deb, NULL, NULL, 0, NULL); } if (sim_deb_switches & SWMASK ('N')) sim_deb_switches &= ~SWMASK ('N'); /* Only process the -N flag initially */ return SCPE_OK; } t_stat sim_debug_flush (void) { int32 saved_quiet = sim_quiet; int32 saved_sim_switches = sim_switches; int32 saved_deb_switches = sim_deb_switches; struct timespec saved_deb_basetime = sim_deb_basetime; char saved_debug_filename[CBUFSIZE]; if (sim_deb == NULL) /* no debug? */ return SCPE_OK; if (sim_deb == sim_log) { /* debug is log */ fflush (sim_deb); /* fflush is the best we can do */ return SCPE_OK; } strcpy (saved_debug_filename, sim_logfile_name (sim_deb, sim_deb_ref)); sim_quiet = 1; sim_set_deboff (0, NULL); sim_switches = saved_deb_switches; sim_set_debon (0, saved_debug_filename); sim_deb_basetime = saved_deb_basetime; sim_switches = saved_sim_switches; sim_quiet = saved_quiet; return SCPE_OK; } /* Set nodebug routine */ t_stat sim_set_deboff (int32 flag, CONST char *cptr) { if (cptr && (*cptr != 0)) /* now eol? */ return SCPE_2MARG; if (sim_deb == NULL) /* no debug? */ return SCPE_OK; sim_close_logfile (&sim_deb_ref); sim_deb = NULL; sim_deb_switches = 0; if (!sim_quiet) sim_printf ("Debug output disabled\n"); return SCPE_OK; } /* Show debug routine */ t_stat sim_show_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { int32 i; if (cptr && (*cptr != 0)) return SCPE_2MARG; if (sim_deb) { fprintf (st, "Debug output enabled to \"%s\"\n", sim_logfile_name (sim_deb, sim_deb_ref)); if (sim_deb_switches & SWMASK ('P')) fprintf (st, " Debug messages contain current PC value\n"); if (sim_deb_switches & SWMASK ('T')) fprintf (st, " Debug messages display time of day as hh:mm:ss.msec%s\n", sim_deb_switches & SWMASK ('R') ? " relative to the start of debugging" : ""); if (sim_deb_switches & SWMASK ('A')) fprintf (st, " Debug messages display time of day as seconds.msec%s\n", sim_deb_switches & SWMASK ('R') ? " relative to the start of debugging" : ""); for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { if (!(dptr->flags & DEV_DIS) && (dptr->flags & DEV_DEBUG) && (dptr->dctrl)) { fprintf (st, "Device: %-6s ", dptr->name); show_dev_debug (st, dptr, NULL, 0, NULL); } } for (i = 0; sim_internal_device_count && (dptr = sim_internal_devices[i]); ++i) { if (!(dptr->flags & DEV_DIS) && (dptr->flags & DEV_DEBUG) && (dptr->dctrl)) { fprintf (st, "Device: %-6s ", dptr->name); show_dev_debug (st, dptr, NULL, 0, NULL); } } } else fprintf (st, "Debug output disabled\n"); return SCPE_OK; } /* SET CONSOLE command */ /* Set console to Telnet port (and parameters) */ t_stat sim_set_telnet (int32 flag, CONST char *cptr) { char *cvptr, gbuf[CBUFSIZE]; CTAB *ctptr; t_stat r; if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; while (*cptr != 0) { /* do all mods */ cptr = get_glyph_nc (cptr, gbuf, ','); /* get modifier */ if ((cvptr = strchr (gbuf, '='))) /* = value? */ *cvptr++ = 0; get_glyph (gbuf, gbuf, 0); /* modifier to UC */ if ((ctptr = find_ctab (set_con_telnet_tab, gbuf))) { /* match? */ r = ctptr->action (ctptr->arg, cvptr); /* do the rest */ if (r != SCPE_OK) return r; } else { if (sim_con_tmxr.master) /* already open? */ sim_set_notelnet (0, NULL); /* close first */ r = tmxr_attach (&sim_con_tmxr, &sim_con_unit, gbuf);/* open master socket */ if (r == SCPE_OK) sim_activate_after(&sim_con_unit, 1000000); /* check for connection in 1 second */ else return r; } } return SCPE_OK; } /* Close console Telnet port */ t_stat sim_set_notelnet (int32 flag, CONST char *cptr) { if (cptr && (*cptr != 0)) /* too many arguments? */ return SCPE_2MARG; if (sim_con_tmxr.master == 0) /* ignore if already closed */ return SCPE_OK; return tmxr_close_master (&sim_con_tmxr); /* close master socket */ } /* Show console Telnet status */ t_stat sim_show_telnet (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, CONST char *cptr) { if (cptr && (*cptr != 0)) return SCPE_2MARG; if ((sim_con_tmxr.master == 0) && (sim_con_ldsc.serport == 0)) fprintf (st, "Connected to console window\n"); else { if (sim_con_ldsc.serport) { fprintf (st, "Connected to "); tmxr_fconns (st, &sim_con_ldsc, -1); } else if (sim_con_ldsc.sock == 0) fprintf (st, "Listening on port %s\n", sim_con_tmxr.port); else { fprintf (st, "Listening on port %s, connection from %s\n", sim_con_tmxr.port, sim_con_ldsc.ipad); tmxr_fconns (st, &sim_con_ldsc, -1); } tmxr_fstats (st, &sim_con_ldsc, -1); } return SCPE_OK; } /* Set console to Buffering */ t_stat sim_set_cons_buff (int32 flg, CONST char *cptr) { char cmdbuf[CBUFSIZE]; sprintf(cmdbuf, "BUFFERED%c%s", cptr ? '=' : '\0', cptr ? cptr : ""); return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */ } /* Set console to NoBuffering */ t_stat sim_set_cons_unbuff (int32 flg, CONST char *cptr) { char cmdbuf[CBUFSIZE]; sprintf(cmdbuf, "UNBUFFERED%c%s", cptr ? '=' : '\0', cptr ? cptr : ""); return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */ } /* Set console to Logging */ t_stat sim_set_cons_log (int32 flg, CONST char *cptr) { char cmdbuf[CBUFSIZE]; sprintf(cmdbuf, "LOG%c%s", cptr ? '=' : '\0', cptr ? cptr : ""); return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */ } /* Set console to NoLogging */ t_stat sim_set_cons_nolog (int32 flg, CONST char *cptr) { char cmdbuf[CBUFSIZE]; sprintf(cmdbuf, "NOLOG%c%s", cptr ? '=' : '\0', cptr ? cptr : ""); return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */ } t_stat sim_show_cons_log (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, CONST char *cptr) { if (cptr && (*cptr != 0)) return SCPE_2MARG; if (sim_con_tmxr.ldsc->txlog) fprintf (st, "Log File being written to %s\n", sim_con_tmxr.ldsc->txlogname); else fprintf (st, "No Logging\n"); return SCPE_OK; } t_stat sim_show_cons_buff (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, CONST char *cptr) { if (cptr && (*cptr != 0)) return SCPE_2MARG; if (!sim_con_tmxr.ldsc->txbfd) fprintf (st, "Unbuffered\n"); else fprintf (st, "Buffer Size = %d\n", sim_con_tmxr.ldsc->txbsz); return SCPE_OK; } /* Set console Debug Mode */ t_stat sim_set_cons_debug (int32 flg, CONST char *cptr) { return set_dev_debug (&sim_con_telnet, &sim_con_unit, flg, cptr); } t_stat sim_show_cons_debug (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, CONST char *cptr) { if (cptr && (*cptr != 0)) return SCPE_2MARG; return show_dev_debug (st, &sim_con_telnet, &sim_con_unit, flag, cptr); } /* Set console to Serial port (and parameters) */ t_stat sim_set_serial (int32 flag, CONST char *cptr) { char *cvptr, gbuf[CBUFSIZE], ubuf[CBUFSIZE]; CTAB *ctptr; t_stat r; if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; while (*cptr != 0) { /* do all mods */ cptr = get_glyph_nc (cptr, gbuf, ','); /* get modifier */ if ((cvptr = strchr (gbuf, '='))) /* = value? */ *cvptr++ = 0; get_glyph (gbuf, ubuf, 0); /* modifier to UC */ if ((ctptr = find_ctab (set_con_serial_tab, ubuf))) { /* match? */ r = ctptr->action (ctptr->arg, cvptr); /* do the rest */ if (r != SCPE_OK) return r; } else { SERHANDLE serport = sim_open_serial (gbuf, NULL, &r); if (serport != INVALID_HANDLE) { sim_close_serial (serport); if (r == SCPE_OK) { char cbuf[CBUFSIZE]; if ((sim_con_tmxr.master) || /* already open? */ (sim_con_ldsc.serport)) sim_set_noserial (0, NULL); /* close first */ sprintf(cbuf, "Connect=%s", gbuf); r = tmxr_attach (&sim_con_tmxr, &sim_con_unit, cbuf);/* open master socket */ sim_con_ldsc.rcve = 1; /* rcv enabled */ if (r == SCPE_OK) sim_activate_after(&sim_con_unit, 1000000); /* check for connection in 1 second */ return r; } } return SCPE_ARG; } } return SCPE_OK; } /* Close console Serial port */ t_stat sim_set_noserial (int32 flag, CONST char *cptr) { if (cptr && (*cptr != 0)) /* too many arguments? */ return SCPE_2MARG; if (sim_con_ldsc.serport == 0) /* ignore if already closed */ return SCPE_OK; return tmxr_close_master (&sim_con_tmxr); /* close master socket */ } /* Show the console expect rules and state */ t_stat sim_show_cons_expect (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, CONST char *cptr) { return sim_exp_show (st, &sim_con_expect, cptr); } /* Log File Open/Close/Show Support */ /* Open log file */ t_stat sim_open_logfile (const char *filename, t_bool binary, FILE **pf, FILEREF **pref) { char gbuf[CBUFSIZE]; const char *tptr; if ((filename == NULL) || (*filename == 0)) /* too few arguments? */ return SCPE_2FARG; tptr = get_glyph (filename, gbuf, 0); if (*tptr != 0) /* now eol? */ return SCPE_2MARG; sim_close_logfile (pref); *pf = NULL; if (strcmp (gbuf, "LOG") == 0) { /* output to log? */ if (sim_log == NULL) /* any log? */ return SCPE_ARG; *pf = sim_log; *pref = sim_log_ref; if (*pref) ++(*pref)->refcount; } else if (strcmp (gbuf, "DEBUG") == 0) { /* output to debug? */ if (sim_deb == NULL) /* any debug? */ return SCPE_ARG; *pf = sim_deb; *pref = sim_deb_ref; if (*pref) ++(*pref)->refcount; } else if (strcmp (gbuf, "STDOUT") == 0) { /* output to stdout? */ *pf = stdout; *pref = NULL; } else if (strcmp (gbuf, "STDERR") == 0) { /* output to stderr? */ *pf = stderr; *pref = NULL; } else { *pref = (FILEREF *)calloc (1, sizeof(**pref)); if (!*pref) return SCPE_MEM; get_glyph_nc (filename, gbuf, 0); /* reparse */ strncpy ((*pref)->name, gbuf, sizeof((*pref)->name)-1); if (sim_switches & SWMASK ('N')) /* if a new log file is requested */ *pf = sim_fopen (gbuf, (binary ? "w+b" : "w+"));/* then open an empty file */ else /* otherwise */ *pf = sim_fopen (gbuf, (binary ? "a+b" : "a+"));/* append to an existing file */ if (*pf == NULL) { /* error? */ free (*pref); *pref = NULL; return SCPE_OPENERR; } setvbuf (*pf, NULL, _IOFBF, 65536); (*pref)->file = *pf; (*pref)->refcount = 1; /* need close */ } return SCPE_OK; } /* Close log file */ t_stat sim_close_logfile (FILEREF **pref) { if (NULL == *pref) return SCPE_OK; (*pref)->refcount = (*pref)->refcount - 1; if ((*pref)->refcount > 0) { *pref = NULL; return SCPE_OK; } fclose ((*pref)->file); free (*pref); *pref = NULL; return SCPE_OK; } /* Show logfile support routine */ const char *sim_logfile_name (FILE *st, FILEREF *ref) { if (!st) return ""; if (st == stdout) return "STDOUT"; if (st == stderr) return "STDERR"; if (!ref) return ""; return ref->name; } /* Check connection before executing (including a remote console which may be required in master mode) */ t_stat sim_check_console (int32 sec) { int32 c, trys = 0; if (sim_rem_master_mode) { for (;trys < sec; ++trys) { sim_rem_con_poll_svc (rem_con_poll_unit); if (sim_rem_con_tmxr.ldsc[0].conn) break; if ((trys % 10) == 0) { /* Status every 10 sec */ sim_printf ("Waiting for Remote Console connection\r\n"); fflush (stdout); if (sim_log) /* log file? */ fflush (sim_log); } sim_os_sleep (1); /* wait 1 second */ } if ((sim_rem_con_tmxr.ldsc[0].conn) && (!sim_con_ldsc.serport) && (sim_con_tmxr.master == 0) && (sim_con_console_port)) { tmxr_linemsgf (&sim_rem_con_tmxr.ldsc[0], "\r\nConsole port must be Telnet or Serial with Master Remote Console\r\n"); tmxr_linemsgf (&sim_rem_con_tmxr.ldsc[0], "Goodbye\r\n"); while (tmxr_send_buffered_data (&sim_rem_con_tmxr.ldsc[0])) sim_os_ms_sleep (100); sim_os_ms_sleep (100); tmxr_reset_ln (&sim_rem_con_tmxr.ldsc[0]); sim_printf ("Console port must be Telnet or Serial with Master Remote Console\r\n"); return SCPE_EXIT; } } if (trys == sec) { return SCPE_TTMO; /* timed out */ } if (sim_con_ldsc.serport) if (tmxr_poll_conn (&sim_con_tmxr) >= 0) sim_con_ldsc.rcve = 1; /* rcv enabled */ if ((sim_con_tmxr.master == 0) || /* serial console or not Telnet? done */ (sim_con_ldsc.serport)) return SCPE_OK; if (sim_con_ldsc.conn || sim_con_ldsc.txbfd) { /* connected or buffered ? */ tmxr_poll_rx (&sim_con_tmxr); /* poll (check disconn) */ if (sim_con_ldsc.conn || sim_con_ldsc.txbfd) { /* still connected? */ if (!sim_con_ldsc.conn) { sim_printf ("Running with Buffered Console\r\n"); /* print transition */ fflush (stdout); if (sim_log) /* log file? */ fflush (sim_log); } return SCPE_OK; } } for (; trys < sec; trys++) { /* loop */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) { /* poll connect */ sim_con_ldsc.rcve = 1; /* rcv enabled */ if (trys) { /* if delayed */ sim_printf ("Running\r\n"); /* print transition */ fflush (stdout); if (sim_log) /* log file? */ fflush (sim_log); } return SCPE_OK; /* ready to proceed */ } c = sim_os_poll_kbd (); /* check for stop char */ if ((c == SCPE_STOP) || stop_cpu) return SCPE_STOP; if ((trys % 10) == 0) { /* Status every 10 sec */ sim_printf ("Waiting for console Telnet connection\r\n"); fflush (stdout); if (sim_log) /* log file? */ fflush (sim_log); } sim_os_sleep (1); /* wait 1 second */ } return SCPE_TTMO; /* timed out */ } /* Get Send object address for console */ SEND *sim_cons_get_send (void) { return &sim_con_send; } /* Get Expect object address for console */ EXPECT *sim_cons_get_expect (void) { return &sim_con_expect; } /* Display console Queued input data status */ t_stat sim_show_cons_send_input (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { return sim_show_send_input (st, &sim_con_send); } /* Poll for character */ t_stat sim_poll_kbd (void) { t_stat c; if (sim_send_poll_data (&sim_con_send, &c)) /* injected input characters available? */ return c; if (!sim_rem_master_mode) { if ((sim_con_ldsc.rxbps) && /* rate limiting && */ (sim_gtime () < sim_con_ldsc.rxnexttime)) /* too soon? */ return SCPE_OK; /* not yet */ c = sim_os_poll_kbd (); /* get character */ if (c == SCPE_STOP) { /* ^E */ stop_cpu = 1; /* Force a stop (which is picked up by sim_process_event */ return SCPE_OK; } if ((sim_con_tmxr.master == 0) && /* not Telnet? */ (sim_con_ldsc.serport == 0)) { /* and not serial? */ if (c && sim_con_ldsc.rxbps) /* got something && rate limiting? */ sim_con_ldsc.rxnexttime = /* compute next input time */ floor (sim_gtime () + ((sim_con_ldsc.rxdelta * sim_timer_inst_per_sec ())/sim_con_ldsc.rxbpsfactor)); if (c) sim_debug (DBG_RCV, &sim_con_telnet, "sim_poll_kbd() returning: '%c' (0x%02X)\n", sim_isprint (c & 0xFF) ? c & 0xFF : '.', c); return c; /* in-window */ } if (!sim_con_ldsc.conn) { /* no telnet or serial connection? */ if (!sim_con_ldsc.txbfd) /* unbuffered? */ return SCPE_LOST; /* connection lost */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */ sim_con_ldsc.rcve = 1; /* rcv enabled */ else /* fall through to poll reception */ return SCPE_OK; /* unconnected and buffered - nothing to receive */ } } tmxr_poll_rx (&sim_con_tmxr); /* poll for input */ if ((c = (t_stat)tmxr_getc_ln (&sim_con_ldsc))) /* any char? */ return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG; return SCPE_OK; } /* Output character */ t_stat sim_putchar (int32 c) { sim_exp_check (&sim_con_expect, c); if ((sim_con_tmxr.master == 0) && /* not Telnet? */ (sim_con_ldsc.serport == 0)) { /* and not serial port */ if (sim_log) /* log file? */ fputc (c, sim_log); sim_debug (DBG_XMT, &sim_con_telnet, "sim_putchar('%c' (0x%02X)\n", sim_isprint (c) ? c : '.', c); return sim_os_putchar (c); /* in-window version */ } if (!sim_con_ldsc.conn) { /* no Telnet or serial connection? */ if (!sim_con_ldsc.txbfd) /* unbuffered? */ return SCPE_LOST; /* connection lost */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */ sim_con_ldsc.rcve = 1; /* rcv enabled */ } tmxr_putc_ln (&sim_con_ldsc, c); /* output char */ tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ return SCPE_OK; } t_stat sim_putchar_s (int32 c) { t_stat r; sim_exp_check (&sim_con_expect, c); if ((sim_con_tmxr.master == 0) && /* not Telnet? */ (sim_con_ldsc.serport == 0)) { /* and not serial port */ if (sim_log) /* log file? */ fputc (c, sim_log); sim_debug (DBG_XMT, &sim_con_telnet, "sim_putchar('%c' (0x%02X)\n", sim_isprint (c) ? c : '.', c); return sim_os_putchar (c); /* in-window version */ } if (!sim_con_ldsc.conn) { /* no Telnet or serial connection? */ if (!sim_con_ldsc.txbfd) /* non-buffered Telnet connection? */ return SCPE_LOST; /* lost */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */ sim_con_ldsc.rcve = 1; /* rcv enabled */ } if (sim_con_ldsc.xmte == 0) /* xmt disabled? */ r = SCPE_STALL; else r = tmxr_putc_ln (&sim_con_ldsc, c); /* no, Telnet output */ tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ return r; /* return status */ } /* Input character processing */ int32 sim_tt_inpcvt (int32 c, uint32 mode) { uint32 md = mode & TTUF_M_MODE; if (md != TTUF_MODE_8B) { uint32 par_mode = (mode >> TTUF_W_MODE) & TTUF_M_PAR; static int32 nibble_even_parity = 0x699600; /* bit array indicating the even parity for each index (offset by 8) */ c = c & 0177; if (md == TTUF_MODE_UC) { if (islower (c)) c = toupper (c); if (mode & TTUF_KSR) c = c | 0200; } switch (par_mode) { case TTUF_PAR_EVEN: c |= (((nibble_even_parity >> ((c & 0xF) + 1)) ^ (nibble_even_parity >> (((c >> 4) & 0xF) + 1))) & 0x80); break; case TTUF_PAR_ODD: c |= ((~((nibble_even_parity >> ((c & 0xF) + 1)) ^ (nibble_even_parity >> (((c >> 4) & 0xF) + 1)))) & 0x80); break; case TTUF_PAR_MARK: c = c | 0x80; break; } } else c = c & 0377; return c; } /* Output character processing */ int32 sim_tt_outcvt (int32 c, uint32 mode) { uint32 md = mode & TTUF_M_MODE; if (md != TTUF_MODE_8B) { c = c & 0177; if (md == TTUF_MODE_UC) { if (islower (c)) c = toupper (c); if ((mode & TTUF_KSR) && (c >= 0140)) return -1; } if (((md == TTUF_MODE_UC) || (md == TTUF_MODE_7P)) && ((c == 0177) || ((c < 040) && !((sim_tt_pchar >> c) & 1)))) return -1; } else c = c & 0377; return c; } /* Tab stop array handling *desc points to a uint8 array of length val Columns with tabs set are non-zero; columns without tabs are 0 */ t_stat sim_tt_settabs (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { uint8 *temptabs, *tabs = (uint8 *) desc; int32 i, d; t_stat r; char gbuf[CBUFSIZE]; if ((cptr == NULL) || (tabs == NULL) || (val <= 1)) return SCPE_IERR; if (*cptr == 0) return SCPE_2FARG; if ((temptabs = (uint8 *)malloc (val)) == NULL) return SCPE_MEM; for (i = 0; i < val; i++) temptabs[i] = 0; do { cptr = get_glyph (cptr, gbuf, ';'); d = (int32)get_uint (gbuf, 10, val, &r); if ((r != SCPE_OK) || (d == 0)) { free (temptabs); return SCPE_ARG; } temptabs[d - 1] = 1; } while (*cptr != 0); for (i = 0; i < val; i++) tabs[i] = temptabs[i]; free (temptabs); return SCPE_OK; } t_stat sim_tt_showtabs (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { const uint8 *tabs = (const uint8 *) desc; int32 i, any; if ((st == NULL) || (val == 0) || (desc == NULL)) return SCPE_IERR; for (i = any = 0; i < val; i++) { if (tabs[i] != 0) { fprintf (st, (any? ";%d": "%d"), i + 1); any = 1; } } fprintf (st, (any? "\n": "no tabs set\n")); return SCPE_OK; } #if defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX) extern pthread_mutex_t sim_tmxr_poll_lock; extern pthread_cond_t sim_tmxr_poll_cond; extern int32 sim_tmxr_poll_count; extern t_bool sim_tmxr_poll_running; extern int32 sim_is_running; pthread_t sim_console_poll_thread; /* Keyboard Polling Thread Id */ t_bool sim_console_poll_running = FALSE; pthread_cond_t sim_console_startup_cond; static void * _console_poll(void *arg) { int wait_count = 0; DEVICE *d; /* Boost Priority for this I/O thread vs the CPU instruction execution thread which, in general, won't be readily yielding the processor when this thread needs to run */ sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - starting\n"); pthread_mutex_lock (&sim_tmxr_poll_lock); pthread_cond_signal (&sim_console_startup_cond); /* Signal we're ready to go */ while (sim_asynch_enabled) { if (!sim_is_running) { if (wait_count) { sim_debug (DBG_ASY, d, "_console_poll() - Removing interest in %s. Other interest: %d\n", d->name, sim_con_ldsc.uptr->a_poll_waiter_count); --sim_con_ldsc.uptr->a_poll_waiter_count; --sim_tmxr_poll_count; } break; } /* If we started something, let it finish before polling again */ if (wait_count) { sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - waiting for %d units\n", wait_count); pthread_cond_wait (&sim_tmxr_poll_cond, &sim_tmxr_poll_lock); sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - continuing with after wait\n"); } pthread_mutex_unlock (&sim_tmxr_poll_lock); wait_count = 0; if (sim_os_poll_kbd_ready (1000)) { sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - Keyboard Data available\n"); pthread_mutex_lock (&sim_tmxr_poll_lock); ++wait_count; if (!sim_con_ldsc.uptr->a_polling_now) { sim_con_ldsc.uptr->a_polling_now = TRUE; sim_con_ldsc.uptr->a_poll_waiter_count = 1; d = find_dev_from_unit(sim_con_ldsc.uptr); sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - Activating %s\n", d->name); pthread_mutex_unlock (&sim_tmxr_poll_lock); _sim_activate (sim_con_ldsc.uptr, 0); pthread_mutex_lock (&sim_tmxr_poll_lock); } else { d = find_dev_from_unit(sim_con_ldsc.uptr); sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - Already Activated %s %d times\n", d->name, sim_con_ldsc.uptr->a_poll_waiter_count); ++sim_con_ldsc.uptr->a_poll_waiter_count; } } else pthread_mutex_lock (&sim_tmxr_poll_lock); sim_tmxr_poll_count += wait_count; } pthread_mutex_unlock (&sim_tmxr_poll_lock); sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - exiting\n"); return NULL; } #endif /* defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX) */ t_stat sim_ttinit (void) { sim_con_tmxr.ldsc->mp = &sim_con_tmxr; sim_register_internal_device (&sim_con_telnet); tmxr_startup (); return sim_os_ttinit (); } t_stat sim_ttrun (void) { if (!sim_con_tmxr.ldsc->uptr) { /* If simulator didn't declare its input polling unit */ sim_con_unit.dynflags &= ~UNIT_TM_POLL; /* we can't poll asynchronously */ sim_con_unit.dynflags |= TMUF_NOASYNCH; /* disable asynchronous behavior */ } else { #if defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX) if (sim_asynch_enabled) { sim_con_tmxr.ldsc->uptr->dynflags |= UNIT_TM_POLL;/* flag console input device as a polling unit */ sim_con_unit.dynflags |= UNIT_TM_POLL; /* flag as polling unit */ } #endif } #if defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX) pthread_mutex_lock (&sim_tmxr_poll_lock); if (sim_asynch_enabled) { pthread_attr_t attr; pthread_cond_init (&sim_console_startup_cond, NULL); pthread_attr_init (&attr); pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); pthread_create (&sim_console_poll_thread, &attr, _console_poll, NULL); pthread_attr_destroy( &attr); pthread_cond_wait (&sim_console_startup_cond, &sim_tmxr_poll_lock); /* Wait for thread to stabilize */ pthread_cond_destroy (&sim_console_startup_cond); sim_console_poll_running = TRUE; } pthread_mutex_unlock (&sim_tmxr_poll_lock); #endif tmxr_start_poll (); return sim_os_ttrun (); } t_stat sim_ttcmd (void) { #if defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX) pthread_mutex_lock (&sim_tmxr_poll_lock); if (sim_console_poll_running) { pthread_cond_signal (&sim_tmxr_poll_cond); pthread_mutex_unlock (&sim_tmxr_poll_lock); pthread_join (sim_console_poll_thread, NULL); sim_console_poll_running = FALSE; } else pthread_mutex_unlock (&sim_tmxr_poll_lock); #endif tmxr_stop_poll (); return sim_os_ttcmd (); } t_stat sim_ttclose (void) { t_stat r1 = tmxr_shutdown (); t_stat r2 = sim_os_ttclose (); if (r1 != SCPE_OK) return r1; return r2; } t_bool sim_ttisatty (void) { return sim_os_ttisatty (); } /* Platform specific routine definitions */ /* VMS routines, from Ben Thomas, with fixes from Robert Alan Byer */ #if defined (VMS) #if defined(__VAX) #define sys$assign SYS$ASSIGN #define sys$qiow SYS$QIOW #define sys$dassgn SYS$DASSGN #endif #include <descrip.h> #include <ttdef.h> #include <tt2def.h> #include <iodef.h> #include <ssdef.h> #include <starlet.h> #include <unistd.h> #define EFN 0 uint32 tty_chan = 0; int buffered_character = 0; typedef struct { unsigned short sense_count; unsigned char sense_first_char; unsigned char sense_reserved; unsigned int stat; unsigned int stat2; } SENSE_BUF; typedef struct { unsigned short status; unsigned short count; unsigned int dev_status; } IOSB; SENSE_BUF cmd_mode = { 0 }; SENSE_BUF run_mode = { 0 }; static t_stat sim_os_ttinit (void) { unsigned int status; IOSB iosb; $DESCRIPTOR (terminal_device, "tt"); status = sys$assign (&terminal_device, &tty_chan, 0, 0); if (status != SS$_NORMAL) return SCPE_TTIERR; status = sys$qiow (EFN, tty_chan, IO$_SENSEMODE, &iosb, 0, 0, &cmd_mode, sizeof (cmd_mode), 0, 0, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; run_mode = cmd_mode; run_mode.stat = cmd_mode.stat | TT$M_NOECHO & ~(TT$M_HOSTSYNC | TT$M_TTSYNC); run_mode.stat2 = cmd_mode.stat2 | TT2$M_PASTHRU; return SCPE_OK; } static t_stat sim_os_ttrun (void) { unsigned int status; IOSB iosb; status = sys$qiow (EFN, tty_chan, IO$_SETMODE, &iosb, 0, 0, &run_mode, sizeof (run_mode), 0, 0, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; return SCPE_OK; } static t_stat sim_os_ttcmd (void) { unsigned int status; IOSB iosb; status = sys$qiow (EFN, tty_chan, IO$_SETMODE, &iosb, 0, 0, &cmd_mode, sizeof (cmd_mode), 0, 0, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; return SCPE_OK; } static t_stat sim_os_ttclose (void) { sim_ttcmd (); sys$dassgn (tty_chan); return SCPE_OK; } static t_bool sim_os_ttisatty (void) { return isatty (fileno (stdin)); } static t_stat sim_os_poll_kbd_data (void) { unsigned int status, term[2]; unsigned char buf[4]; IOSB iosb; SENSE_BUF sense; term[0] = 0; term[1] = 0; status = sys$qiow (EFN, tty_chan, IO$_SENSEMODE | IO$M_TYPEAHDCNT, &iosb, 0, 0, &sense, 8, 0, term, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; if (sense.sense_count == 0) return SCPE_OK; term[0] = 0; term[1] = 0; status = sys$qiow (EFN, tty_chan, IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED | IO$M_TRMNOECHO, &iosb, 0, 0, buf, 1, 0, term, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_OK; if (buf[0] == sim_int_char) return SCPE_STOP; if (sim_brk_char && (buf[0] == sim_brk_char)) return SCPE_BREAK; return (buf[0] | SCPE_KFLAG); } static t_stat sim_os_poll_kbd (void) { t_stat response; if (response = buffered_character) { buffered_character = 0; return response; } return sim_os_poll_kbd_data (); } static t_bool sim_os_poll_kbd_ready (int ms_timeout) { unsigned int status, term[2]; unsigned char buf[4]; IOSB iosb; term[0] = 0; term[1] = 0; status = sys$qiow (EFN, tty_chan, IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED | IO$M_TRMNOECHO, &iosb, 0, 0, buf, 1, (ms_timeout+999)/1000, term, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return FALSE; if (buf[0] == sim_int_char) buffered_character = SCPE_STOP; else if (sim_brk_char && (buf[0] == sim_brk_char)) buffered_character = SCPE_BREAK; else buffered_character = (buf[0] | SCPE_KFLAG); return TRUE; } static t_stat sim_os_putchar (int32 out) { unsigned int status; char c; IOSB iosb; c = out; status = sys$qiow (EFN, tty_chan, IO$_WRITELBLK | IO$M_NOFORMAT, &iosb, 0, 0, &c, 1, 0, 0, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTOERR; return SCPE_OK; } /* Win32 routines */ #elif defined (_WIN32) #include <fcntl.h> #include <io.h> #include <windows.h> #define RAW_MODE 0 static HANDLE std_input; static HANDLE std_output; static DWORD saved_input_mode; static DWORD saved_output_mode; #ifndef ENABLE_VIRTUAL_TERMINAL_INPUT #define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200 #endif #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 #endif /* Note: This routine catches all the potential events which some aspect of the windows system can generate. The CTRL_C_EVENT won't be generated by a user typing in a console session since that session is in RAW mode. In general, Ctrl-C on a simulator's console terminal is a useful character to be passed to the simulator. This code does nothing to disable or affect that. */ static BOOL WINAPI ControlHandler(DWORD dwCtrlType) { DWORD Mode; extern void int_handler (int sig); switch (dwCtrlType) { case CTRL_BREAK_EVENT: // Use CTRL-Break or CTRL-C to simulate case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode int_handler(0); return TRUE; case CTRL_CLOSE_EVENT: // Window is Closing case CTRL_LOGOFF_EVENT: // User is logging off if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &Mode)) return TRUE; // Not our User, so ignore case CTRL_SHUTDOWN_EVENT: // System is shutting down int_handler(0); return TRUE; } return FALSE; } static t_stat sim_os_ttinit (void) { SetConsoleCtrlHandler( ControlHandler, TRUE ); std_input = GetStdHandle (STD_INPUT_HANDLE); std_output = GetStdHandle (STD_OUTPUT_HANDLE); if ((std_input) && /* Not Background process? */ (std_input != INVALID_HANDLE_VALUE)) GetConsoleMode (std_input, &saved_input_mode); /* Save Input Mode */ if ((std_output) && /* Not Background process? */ (std_output != INVALID_HANDLE_VALUE)) GetConsoleMode (std_output, &saved_output_mode); /* Save Output Mode */ return SCPE_OK; } static t_stat sim_os_ttrun (void) { if ((std_input) && /* If Not Background process? */ (std_input != INVALID_HANDLE_VALUE)) { if (!GetConsoleMode(std_input, &saved_input_mode)) return SCPE_TTYERR; if ((!SetConsoleMode(std_input, ENABLE_VIRTUAL_TERMINAL_INPUT)) && (!SetConsoleMode(std_input, RAW_MODE))) return SCPE_TTYERR; } if ((std_output) && /* If Not Background process? */ (std_output != INVALID_HANDLE_VALUE)) { if (GetConsoleMode(std_output, &saved_output_mode)) SetConsoleMode(std_output, ENABLE_VIRTUAL_TERMINAL_PROCESSING|ENABLE_PROCESSED_OUTPUT); } if (sim_log) { fflush (sim_log); _setmode (_fileno (sim_log), _O_BINARY); } sim_os_set_thread_priority (PRIORITY_BELOW_NORMAL); return SCPE_OK; } static t_stat sim_os_ttcmd (void) { if (sim_log) { fflush (sim_log); _setmode (_fileno (sim_log), _O_TEXT); } sim_os_set_thread_priority (PRIORITY_NORMAL); if ((std_input) && /* If Not Background process? */ (std_input != INVALID_HANDLE_VALUE) && (!SetConsoleMode(std_input, saved_input_mode))) /* Restore Normal mode */ return SCPE_TTYERR; if ((std_output) && /* If Not Background process? */ (std_output != INVALID_HANDLE_VALUE) && (!SetConsoleMode(std_output, saved_output_mode))) /* Restore Normal mode */ return SCPE_TTYERR; return SCPE_OK; } static t_stat sim_os_ttclose (void) { return SCPE_OK; } static t_bool sim_os_ttisatty (void) { DWORD Mode; return (std_input) && (std_input != INVALID_HANDLE_VALUE) && GetConsoleMode (std_input, &Mode); } static t_stat sim_os_poll_kbd (void) { int c = -1; DWORD nkbevents, nkbevent; INPUT_RECORD rec; sim_debug (DBG_TRC, &sim_con_telnet, "sim_os_poll_kbd()\n"); if ((std_input == NULL) || /* No keyboard for */ (std_input == INVALID_HANDLE_VALUE)) /* background processes */ return SCPE_OK; if (!GetNumberOfConsoleInputEvents(std_input, &nkbevents)) return SCPE_TTYERR; while (c == -1) { if (0 == nkbevents) return SCPE_OK; if (!ReadConsoleInput(std_input, &rec, 1, &nkbevent)) return SCPE_TTYERR; if (0 == nkbevent) return SCPE_OK; --nkbevents; if (rec.EventType == KEY_EVENT) { if (rec.Event.KeyEvent.bKeyDown) { if (0 == rec.Event.KeyEvent.uChar.UnicodeChar) { /* Special Character/Keys? */ if (rec.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) /* Pause/Break Key */ c = sim_brk_char | SCPE_BREAK; else if (rec.Event.KeyEvent.wVirtualKeyCode == '2') /* ^@ */ c = 0; /* return NUL */ } else c = rec.Event.KeyEvent.uChar.AsciiChar; } } } if ((c & 0177) == sim_del_char) c = 0177; if ((c & 0177) == sim_int_char) return SCPE_STOP; if ((sim_brk_char && ((c & 0177) == sim_brk_char)) || (c & SCPE_BREAK)) return SCPE_BREAK; return c | SCPE_KFLAG; } static t_bool sim_os_poll_kbd_ready (int ms_timeout) { sim_debug (DBG_TRC, &sim_con_telnet, "sim_os_poll_kbd_ready()\n"); if ((std_input == NULL) || /* No keyboard for */ (std_input == INVALID_HANDLE_VALUE)) { /* background processes */ Sleep (ms_timeout); return FALSE; } return (WAIT_OBJECT_0 == WaitForSingleObject (std_input, ms_timeout)); } #define BELL_CHAR 7 /* Bell Character */ #define BELL_INTERVAL_MS 500 /* No more than 2 Bell Characters Per Second */ #define ESC_CHAR 033 /* Escape Character */ #define CSI_CHAR 0233 /* Control Sequence Introducer */ #define NUL_CHAR 0000 /* NUL character */ #define ESC_HOLD_USEC_DELAY 8000 /* Escape hold interval */ #define ESC_HOLD_MAX 32 /* Maximum Escape hold buffer */ static uint8 out_buf[ESC_HOLD_MAX]; /* Buffered characters pending output */ static int32 out_ptr = 0; static t_stat sim_out_hold_svc (UNIT *uptr) { DWORD unused; WriteConsoleA(std_output, out_buf, out_ptr, &unused, NULL); out_ptr = 0; return SCPE_OK; } #define out_hold_unit sim_con_units[1] static t_stat sim_os_putchar (int32 c) { DWORD unused; uint32 now; static uint32 last_bell_time; if (c != 0177) { switch (c) { case BELL_CHAR: now = sim_os_msec (); if ((now - last_bell_time) > BELL_INTERVAL_MS) { WriteConsoleA(std_output, &c, 1, &unused, NULL); last_bell_time = now; } break; case NUL_CHAR: break; case CSI_CHAR: case ESC_CHAR: if (out_ptr) { WriteConsoleA(std_output, out_buf, out_ptr, &unused, NULL); out_ptr = 0; sim_cancel (&out_hold_unit); } out_buf[out_ptr++] = (uint8)c; sim_activate_after (&out_hold_unit, ESC_HOLD_USEC_DELAY); out_hold_unit.action = &sim_out_hold_svc; break; default: if (out_ptr) { if (out_ptr >= ESC_HOLD_MAX) { /* Stop buffering if full */ WriteConsoleA(std_output, out_buf, out_ptr, &unused, NULL); out_ptr = 0; WriteConsoleA(std_output, &c, 1, &unused, NULL); } else out_buf[out_ptr++] = (uint8)c; } else WriteConsoleA(std_output, &c, 1, &unused, NULL); } } return SCPE_OK; } /* OS/2 routines, from Bruce Ray and Holger Veit */ #elif defined (__OS2__) #include <conio.h> static t_stat sim_os_ttinit (void) { return SCPE_OK; } static t_stat sim_os_ttrun (void) { return SCPE_OK; } static t_stat sim_os_ttcmd (void) { return SCPE_OK; } static t_stat sim_os_ttclose (void) { return SCPE_OK; } static t_bool sim_os_ttisatty (void) { return 1; } static t_stat sim_os_poll_kbd (void) { int c; #if defined (__EMX__) switch (c = _read_kbd(0,0,0)) { /* EMX has _read_kbd */ case -1: /* no char*/ return SCPE_OK; case 0: /* char pending */ c = _read_kbd(0,1,0); break; default: /* got char */ break; } #else if (!kbhit ()) return SCPE_OK; c = getch(); #endif if ((c & 0177) == sim_del_char) c = 0177; if ((c & 0177) == sim_int_char) return SCPE_STOP; if (sim_brk_char && ((c & 0177) == sim_brk_char)) return SCPE_BREAK; return c | SCPE_KFLAG; } static t_bool sim_os_poll_kbd_ready (int ms_timeout) /* Don't know how to do this on this platform */ { sim_os_ms_sleep (MIN(20,ms_timeout)); /* Wait a little */ return TRUE; /* force a poll */ } static t_stat sim_os_putchar (int32 c) { if (c != 0177) { #if defined (__EMX__) putchar (c); #else putch (c); #endif fflush (stdout); } return SCPE_OK; } /* Metrowerks CodeWarrior Macintosh routines, from Louis Chretien and Peter Schorn */ #elif defined (__MWERKS__) && defined (macintosh) #include <console.h> #include <Mactypes.h> #include <string.h> #include <sioux.h> #include <unistd.h> #include <siouxglobals.h> #include <Traps.h> #include <LowMem.h> /* function prototypes */ Boolean SIOUXIsAppWindow(WindowPtr window); void SIOUXDoMenuChoice(long menuValue); void SIOUXUpdateMenuItems(void); void SIOUXUpdateScrollbar(void); int ps_kbhit(void); int ps_getch(void); extern pSIOUXWin SIOUXTextWindow; static CursHandle iBeamCursorH = NULL; /* contains the iBeamCursor */ static void updateCursor(void) { WindowPtr window; window = FrontWindow(); if (SIOUXIsAppWindow(window)) { GrafPtr savePort; Point localMouse; GetPort(&savePort); SetPort(window); #if TARGET_API_MAC_CARBON GetGlobalMouse(&localMouse); #else localMouse = LMGetMouseLocation(); #endif GlobalToLocal(&localMouse); if (PtInRect(localMouse, &(*SIOUXTextWindow->edit)->viewRect) && iBeamCursorH) { SetCursor(*iBeamCursorH); } else { SetCursor(&qd.arrow); } TEIdle(SIOUXTextWindow->edit); SetPort(savePort); } else { SetCursor(&qd.arrow); TEIdle(SIOUXTextWindow->edit); } return; } int ps_kbhit(void) { EventRecord event; int c; updateCursor(); SIOUXUpdateScrollbar(); while (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask | highLevelEventMask | diskEvt, &event)) { SIOUXHandleOneEvent(&event); } if (SIOUXQuitting) { exit(1); } if (EventAvail(keyDownMask,&event)) { c = event.message&charCodeMask; if ((event.modifiers & cmdKey) && (c > 0x20)) { GetNextEvent(keyDownMask, &event); SIOUXHandleOneEvent(&event); if (SIOUXQuitting) { exit(1); } return false; } return true; } else { return false; } } int ps_getch(void) { int c; EventRecord event; fflush(stdout); updateCursor(); while(!GetNextEvent(keyDownMask,&event)) { if (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask | highLevelEventMask | diskEvt, &event)) { SIOUXUpdateScrollbar(); SIOUXHandleOneEvent(&event); } } if (SIOUXQuitting) { exit(1); } c = event.message&charCodeMask; if ((event.modifiers & cmdKey) && (c > 0x20)) { SIOUXUpdateMenuItems(); SIOUXDoMenuChoice(MenuKey(c)); } if (SIOUXQuitting) { exit(1); } return c; } /* Note that this only works if the call to sim_ttinit comes before any output to the console */ static t_stat sim_os_ttinit (void) { int i; /* this blank will later be replaced by the number of characters */ char title[50] = " "; unsigned char ptitle[50]; SIOUXSettings.autocloseonquit = TRUE; SIOUXSettings.asktosaveonclose = FALSE; SIOUXSettings.showstatusline = FALSE; SIOUXSettings.columns = 80; SIOUXSettings.rows = 40; SIOUXSettings.toppixel = 42; SIOUXSettings.leftpixel = 6; iBeamCursorH = GetCursor(iBeamCursor); sim_strlcat(title, sim_name, sizeof(title)); sim_strlcat(title, " Simulator", sizeof(title)); title[0] = strlen(title) - 1; /* Pascal string done */ for (i = 0; i <= title[0]; i++) { /* copy to unsigned char */ ptitle[i] = title[i]; } SIOUXSetTitle(ptitle); return SCPE_OK; } static t_stat sim_os_ttrun (void) { return SCPE_OK; } static t_stat sim_os_ttcmd (void) { return SCPE_OK; } static t_stat sim_os_ttclose (void) { return SCPE_OK; } static t_bool sim_os_ttisatty (void) { return 1; } static t_stat sim_os_poll_kbd (void) { int c; if (!ps_kbhit ()) return SCPE_OK; c = ps_getch(); if ((c & 0177) == sim_del_char) c = 0177; if ((c & 0177) == sim_int_char) return SCPE_STOP; if (sim_brk_char && ((c & 0177) == sim_brk_char)) return SCPE_BREAK; return c | SCPE_KFLAG; } static t_bool sim_os_poll_kbd_ready (int ms_timeout) /* Don't know how to do this on this platform */ { sim_os_ms_sleep (MIN(20,ms_timeout)); /* Wait a little */ return TRUE; /* force a poll */ } static t_stat sim_os_putchar (int32 c) { if (c != 0177) { putchar (c); fflush (stdout); } return SCPE_OK; } /* BSD UNIX routines */ #elif defined (BSDTTY) #include <sgtty.h> #include <fcntl.h> #include <unistd.h> struct sgttyb cmdtty,runtty; /* V6/V7 stty data */ struct tchars cmdtchars,runtchars; /* V7 editing */ struct ltchars cmdltchars,runltchars; /* 4.2 BSD editing */ int cmdfl,runfl; /* TTY flags */ static t_stat sim_os_ttinit (void) { cmdfl = fcntl (0, F_GETFL, 0); /* get old flags and status */ runfl = cmdfl | FNDELAY; if (ioctl (0, TIOCGETP, &cmdtty) < 0) return SCPE_TTIERR; if (ioctl (0, TIOCGETC, &cmdtchars) < 0) return SCPE_TTIERR; if (ioctl (0, TIOCGLTC, &cmdltchars) < 0) return SCPE_TTIERR; runtty = cmdtty; /* initial run state */ runtty.sg_flags = cmdtty.sg_flags & ~(ECHO|CRMOD) | CBREAK; runtchars.t_intrc = sim_int_char; /* interrupt */ runtchars.t_quitc = 0xFF; /* no quit */ runtchars.t_startc = 0xFF; /* no host sync */ runtchars.t_stopc = 0xFF; runtchars.t_eofc = 0xFF; runtchars.t_brkc = 0xFF; runltchars.t_suspc = 0xFF; /* no specials of any kind */ runltchars.t_dsuspc = 0xFF; runltchars.t_rprntc = 0xFF; runltchars.t_flushc = 0xFF; runltchars.t_werasc = 0xFF; runltchars.t_lnextc = 0xFF; return SCPE_OK; /* return success */ } static t_stat sim_os_ttrun (void) { runtchars.t_intrc = sim_int_char; /* in case changed */ fcntl (0, F_SETFL, runfl); /* non-block mode */ if (ioctl (0, TIOCSETP, &runtty) < 0) return SCPE_TTIERR; if (ioctl (0, TIOCSETC, &runtchars) < 0) return SCPE_TTIERR; if (ioctl (0, TIOCSLTC, &runltchars) < 0) return SCPE_TTIERR; sim_os_set_thread_priority (PRIORITY_BELOW_NORMAL)l /* lower priority */ return SCPE_OK; } static t_stat sim_os_ttcmd (void) { sim_os_set_thread_priority (PRIORITY_NORMAL); /* restore priority */ fcntl (0, F_SETFL, cmdfl); /* block mode */ if (ioctl (0, TIOCSETP, &cmdtty) < 0) return SCPE_TTIERR; if (ioctl (0, TIOCSETC, &cmdtchars) < 0) return SCPE_TTIERR; if (ioctl (0, TIOCSLTC, &cmdltchars) < 0) return SCPE_TTIERR; return SCPE_OK; } static t_stat sim_os_ttclose (void) { return sim_ttcmd (); } static t_bool sim_os_ttisatty (void) { return isatty (fileno (stdin)); } static t_stat sim_os_poll_kbd (void) { int status; unsigned char buf[1]; status = read (0, buf, 1); if (status != 1) return SCPE_OK; if (sim_brk_char && (buf[0] == sim_brk_char)) return SCPE_BREAK; if (sim_int_char && (buf[0] == sim_int_char)) return SCPE_STOP; return (buf[0] | SCPE_KFLAG); } static t_bool sim_os_poll_kbd_ready (int ms_timeout) { fd_set readfds; struct timeval timeout; if (!isatty (0)) { /* skip if !tty */ sim_os_ms_sleep (ms_timeout); return FALSE; } FD_ZERO (&readfds); FD_SET (0, &readfds); timeout.tv_sec = (ms_timeout*1000)/1000000; timeout.tv_usec = (ms_timeout*1000)%1000000; return (1 == select (1, &readfds, NULL, NULL, &timeout)); } static t_stat sim_os_putchar (int32 out) { char c; c = out; write (1, &c, 1); return SCPE_OK; } /* POSIX UNIX routines, from Leendert Van Doorn */ #else #include <termios.h> #include <unistd.h> struct termios cmdtty, runtty; static t_stat sim_os_ttinit (void) { if (!isatty (fileno (stdin))) /* skip if !tty */ return SCPE_OK; if (tcgetattr (0, &cmdtty) < 0) /* get old flags */ return SCPE_TTIERR; runtty = cmdtty; runtty.c_lflag = runtty.c_lflag & ~(ECHO | ICANON); /* no echo or edit */ runtty.c_oflag = runtty.c_oflag & ~OPOST; /* no output edit */ runtty.c_iflag = runtty.c_iflag & ~ICRNL; /* no cr conversion */ #if defined(USE_SIM_VIDEO) && defined(HAVE_LIBSDL) runtty.c_cc[VINTR] = 0; /* OS X doesn't deliver SIGINT to main thread when enabled */ #else runtty.c_cc[VINTR] = sim_int_char; /* interrupt */ #endif runtty.c_cc[VQUIT] = 0; /* no quit */ runtty.c_cc[VERASE] = 0; runtty.c_cc[VKILL] = 0; runtty.c_cc[VEOF] = 0; runtty.c_cc[VEOL] = 0; runtty.c_cc[VSTART] = 0; /* no host sync */ runtty.c_cc[VSUSP] = 0; runtty.c_cc[VSTOP] = 0; #if defined (VREPRINT) runtty.c_cc[VREPRINT] = 0; /* no specials */ #endif #if defined (VDISCARD) runtty.c_cc[VDISCARD] = 0; #endif #if defined (VWERASE) runtty.c_cc[VWERASE] = 0; #endif #if defined (VLNEXT) runtty.c_cc[VLNEXT] = 0; #endif runtty.c_cc[VMIN] = 0; /* no waiting */ runtty.c_cc[VTIME] = 0; #if defined (VDSUSP) runtty.c_cc[VDSUSP] = 0; #endif #if defined (VSTATUS) runtty.c_cc[VSTATUS] = 0; #endif return SCPE_OK; } static t_stat sim_os_ttrun (void) { if (!isatty (fileno (stdin))) /* skip if !tty */ return SCPE_OK; #if defined(USE_SIM_VIDEO) && defined(HAVE_LIBSDL) runtty.c_cc[VINTR] = 0; /* OS X doesn't deliver SIGINT to main thread when enabled */ #else runtty.c_cc[VINTR] = sim_int_char; /* in case changed */ #endif if (tcsetattr (0, TCSAFLUSH, &runtty) < 0) return SCPE_TTIERR; sim_os_set_thread_priority (PRIORITY_BELOW_NORMAL); /* try to lower pri */ return SCPE_OK; } static t_stat sim_os_ttcmd (void) { if (!isatty (fileno (stdin))) /* skip if !tty */ return SCPE_OK; sim_os_set_thread_priority (PRIORITY_NORMAL); /* try to raise pri */ if (tcsetattr (0, TCSAFLUSH, &cmdtty) < 0) return SCPE_TTIERR; return SCPE_OK; } static t_stat sim_os_ttclose (void) { return sim_ttcmd (); } static t_bool sim_os_ttisatty (void) { return isatty (fileno (stdin)); } static t_stat sim_os_poll_kbd (void) { int status; unsigned char buf[1]; status = read (0, buf, 1); if (status != 1) return SCPE_OK; if (sim_brk_char && (buf[0] == sim_brk_char)) return SCPE_BREAK; if (sim_int_char && (buf[0] == sim_int_char)) return SCPE_STOP; return (buf[0] | SCPE_KFLAG); } static t_bool sim_os_poll_kbd_ready (int ms_timeout) { fd_set readfds; struct timeval timeout; if (!sim_os_ttisatty()) { /* skip if !tty */ sim_os_ms_sleep (ms_timeout); return FALSE; } FD_ZERO (&readfds); FD_SET (0, &readfds); timeout.tv_sec = (ms_timeout*1000)/1000000; timeout.tv_usec = (ms_timeout*1000)%1000000; return (1 == select (1, &readfds, NULL, NULL, &timeout)); } static t_stat sim_os_putchar (int32 out) { char c; c = out; (void)write (1, &c, 1); return SCPE_OK; } #endif /* Decode a string. A string containing encoded control characters is decoded into the equivalent character string. Escape targets @, A-Z, and [\]^_ form control characters 000-037. */ #define ESCAPE_CHAR '~' static void decode (char *decoded, const char *encoded) { char c; while ((c = *decoded++ = *encoded++)) /* copy the character */ if (c == ESCAPE_CHAR) { /* does it start an escape? */ if ((isalpha (*encoded)) || /* is next character "A-Z" or "a-z"? */ (*encoded == '@') || /* or "@"? */ ((*encoded >= '[') && (*encoded <= '_'))) /* or "[\]^_"? */ *(decoded - 1) = *encoded++ & 037; /* convert back to control character */ else { if ((*encoded == '\0') || /* single escape character at EOL? */ (*encoded++ != ESCAPE_CHAR)) /* or not followed by another escape? */ decoded--; /* drop the encoding */ } } return; } /* Set console halt */ static t_stat sim_set_halt (int32 flag, CONST char *cptr) { if (flag == 0) /* no halt? */ sim_exp_clrall (&sim_con_expect); /* disable halt checks */ else { char *mbuf; char *mbuf2; if (cptr == NULL || *cptr == 0) /* no match string? */ return SCPE_2FARG; /* need an argument */ sim_exp_clrall (&sim_con_expect); /* make sure that none currently exist */ mbuf = (char *)malloc (1 + strlen (cptr)); decode (mbuf, cptr); /* save decoded match string */ mbuf2 = (char *)malloc (3 + strlen(cptr)); sprintf (mbuf2, "%s%s%s", (sim_switches & SWMASK ('A')) ? "\n" : "", mbuf, (sim_switches & SWMASK ('I')) ? "" : "\n"); free (mbuf); mbuf = sim_encode_quoted_string ((uint8 *)mbuf2, strlen (mbuf2)); sim_exp_set (&sim_con_expect, mbuf, 0, sim_con_expect.after, EXP_TYP_PERSIST, NULL); free (mbuf); free (mbuf2); } return SCPE_OK; } /* Set console response */ static t_stat sim_set_response (int32 flag, CONST char *cptr) { if (flag == 0) /* no response? */ sim_send_clear (&sim_con_send); else { uint8 *rbuf; if (cptr == NULL || *cptr == 0) return SCPE_2FARG; /* need arg */ rbuf = (uint8 *)malloc (1 + strlen(cptr)); decode ((char *)rbuf, cptr); /* decod string */ sim_send_input (&sim_con_send, rbuf, strlen((char *)rbuf), 0, 0); /* queue it for output */ free (rbuf); } return SCPE_OK; } /* Set console delay */ static t_stat sim_set_delay (int32 flag, CONST char *cptr) { int32 val; t_stat r; if (cptr == NULL || *cptr == 0) /* no argument string? */ return SCPE_2FARG; /* need an argument */ val = (int32) get_uint (cptr, 10, INT_MAX, &r); /* parse the argument */ if (r == SCPE_OK) /* parse OK? */ sim_con_expect.after = val; /* save the delay value */ return r; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | /* sim_console.h: simulator console I/O library headers Copyright (c) 1993-2014, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 02-Jan-14 RMS Added tab stop routines 17-Jan-11 MP Added buffered line capabilities 22-Jun-06 RMS Implemented SET/SHOW PCHAR 22-Nov-05 RMS Added central input/output conversion support 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy 28-May-04 RMS Added SET/SHOW CONSOLE 02-Jan-04 RMS Removed timer routines, added Telnet console routines */ #ifndef SIM_CONSOLE_H_ #define SIM_CONSOLE_H_ 0 #ifdef __cplusplus extern "C" { #endif #define TTUF_V_MODE (UNIT_V_UF + 0) #define TTUF_W_MODE 2 #define TTUF_MODE_7B 0 #define TTUF_MODE_8B 1 #define TTUF_MODE_UC 2 #define TTUF_MODE_7P 3 #define TTUF_M_MODE ((1u << TTUF_W_MODE) - 1) #define TTUF_V_PAR (TTUF_V_MODE + TTUF_W_MODE) #define TTUF_W_PAR 2 #define TTUF_PAR_SPACE 0 #define TTUF_PAR_MARK 1 #define TTUF_PAR_EVEN 2 #define TTUF_PAR_ODD 3 #define TTUF_M_PAR ((1u << TTUF_W_PAR) - 1) #define TTUF_KSR (1u << (TTUF_W_MODE + TTUF_W_PAR)) #define TTUF_V_UF (TTUF_V_MODE + TTUF_W_MODE + TTUF_W_PAR) #define TT_MODE (TTUF_M_MODE << TTUF_V_MODE) #define TT_MODE_7B (TTUF_MODE_7B << TTUF_V_MODE) #define TT_MODE_8B (TTUF_MODE_8B << TTUF_V_MODE) #define TT_MODE_UC (TTUF_MODE_UC << TTUF_V_MODE) #define TT_MODE_7P (TTUF_MODE_7P << TTUF_V_MODE) #define TT_MODE_KSR (TT_MODE_UC) /* 7 bit modes allow for an 8th bit parity mode */ #define TT_PAR (TTUF_M_PAR << TTUF_V_PAR) #define TT_PAR_SPACE (TTUF_PAR_SPACE << TTUF_V_PAR) #define TT_PAR_MARK (TTUF_PAR_MARK << TTUF_V_PAR) #define TT_PAR_EVEN (TTUF_PAR_EVEN << TTUF_V_PAR) #define TT_PAR_ODD (TTUF_PAR_ODD << TTUF_V_PAR) /* TT_GET_MODE returns both the TT_MODE and TT_PAR fields since they together are passed into sim_tt_inpcvt() */ #define TT_GET_MODE(x) (((x) >> TTUF_V_MODE) & (TTUF_M_MODE | (TTUF_M_PAR << TTUF_W_MODE))) t_stat sim_set_console (int32 flag, CONST char *cptr); t_stat sim_set_remote_console (int32 flag, CONST char *cptr); void sim_remote_process_command (void); t_stat sim_set_kmap (int32 flag, CONST char *cptr); t_stat sim_set_telnet (int32 flag, CONST char *cptr); t_stat sim_set_notelnet (int32 flag, CONST char *cptr); t_stat sim_set_serial (int32 flag, CONST char *cptr); t_stat sim_set_noserial (int32 flag, CONST char *cptr); t_stat sim_set_logon (int32 flag, CONST char *cptr); t_stat sim_set_logoff (int32 flag, CONST char *cptr); t_stat sim_set_debon (int32 flag, CONST char *cptr); t_stat sim_set_cons_debug (int32 flg, CONST char *cptr); t_stat sim_set_cons_buff (int32 flg, CONST char *cptr); t_stat sim_set_cons_unbuff (int32 flg, CONST char *cptr); t_stat sim_set_cons_log (int32 flg, CONST char *cptr); t_stat sim_set_cons_nolog (int32 flg, CONST char *cptr); t_stat sim_set_deboff (int32 flag, CONST char *cptr); t_stat sim_set_cons_expect (int32 flg, CONST char *cptr); t_stat sim_set_cons_noexpect (int32 flg, CONST char *cptr); t_stat sim_debug_flush (void); t_stat sim_set_pchar (int32 flag, CONST char *cptr); t_stat sim_set_cons_speed (int32 flag, CONST char *cptr); t_stat sim_show_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_remote_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_kmap (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_telnet (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_pchar (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_cons_speed (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_cons_buff (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_cons_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_cons_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_cons_expect (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_check_console (int32 sec); t_stat sim_open_logfile (const char *filename, t_bool binary, FILE **pf, FILEREF **pref); t_stat sim_close_logfile (FILEREF **pref); const char *sim_logfile_name (FILE *st, FILEREF *ref); SEND *sim_cons_get_send (void); EXPECT *sim_cons_get_expect (void); t_stat sim_show_cons_send_input (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_set_noconsole_port (void); t_stat sim_set_stable_registers_state (void); t_stat sim_poll_kbd (void); t_stat sim_putchar (int32 c); t_stat sim_putchar_s (int32 c); t_stat sim_ttinit (void); t_stat sim_ttrun (void); t_stat sim_ttcmd (void); t_stat sim_ttclose (void); t_bool sim_ttisatty (void); int32 sim_tt_inpcvt (int32 c, uint32 mode); int32 sim_tt_outcvt (int32 c, uint32 mode); t_stat sim_tt_settabs (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_tt_showtabs (FILE *st, UNIT *uptr, int32 val, CONST void *desc); extern int32 sim_rem_cmd_active_line; /* command in progress on line # */ extern int32 sim_int_char; /* interrupt character */ extern int32 sim_brk_char; /* break character */ extern int32 sim_tt_pchar; /* printable character mask */ extern int32 sim_del_char; /* delete character */ #ifdef __cplusplus } #endif #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 | /* sim_defs.h: simulator definitions Copyright (c) 1993-2016, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 25-Sep-16 RMS Removed KBD_WAIT and friends 08-Mar-16 RMS Added shutdown invisible switch 24-Dec-14 JDB Added T_ADDR_FMT 05-Jan-11 MP Added Asynch I/O support 18-Jan-11 MP Added log file reference count support 21-Jul-08 RMS Removed inlining support 28-May-08 RMS Added inlining support 28-Jun-07 RMS Added IA64 VMS support (from Norm Lastovica) 18-Jun-07 RMS Added UNIT_IDLE flag 18-Mar-07 RMS Added UNIT_TEXT flag 07-Mar-07 JDB Added DEBUG_PRJ macro 18-Oct-06 RMS Added limit check for clock synchronized keyboard waits 13-Jul-06 RMS Guarantee CBUFSIZE is at least 256 07-Jan-06 RMS Added support for breakpoint spaces Added REG_FIT flag 16-Aug-05 RMS Fixed C++ declaration and cast problems 11-Mar-05 RMS Moved 64b data type definitions outside USE_INT64 07-Feb-05 RMS Added assertion fail stop 05-Nov-04 RMS Added support for SHOW opt=val 20-Oct-04 RMS Converted all base types to typedefs 21-Sep-04 RMS Added switch to flag stop message printout 06-Feb-04 RMS Moved device and unit user flags fields (V3.2) RMS Added REG_VMAD 29-Dec-03 RMS Added output stall status 15-Jun-03 RMS Added register flag REG_VMIO 23-Apr-03 RMS Revised for 32b/64b t_addr 14-Mar-03 RMS Lengthened default serial output wait 31-Mar-03 RMS Added u5, u6 fields 18-Mar-03 RMS Added logical name support Moved magtape definitions to sim_tape.h Moved breakpoint definitions from scp.c 03-Mar-03 RMS Added sim_fsize 08-Feb-03 RMS Changed sim_os_sleep to void, added match_ext 05-Jan-03 RMS Added hidden switch definitions, device dyn memory support, parameters for function pointers, case sensitive SET support 22-Dec-02 RMS Added break flag 08-Oct-02 RMS Increased simulator error code space Added Telnet errors Added end of medium support Added help messages to CTAB Added flag and context fields to DEVICE Added restore flag masks Revised 64b definitions 02-May-02 RMS Removed log status codes 22-Apr-02 RMS Added magtape record length error 30-Dec-01 RMS Generalized timer package, added circular arrays 07-Dec-01 RMS Added breakpoint package 01-Dec-01 RMS Added read-only unit support, extended SET/SHOW features, improved error messages 24-Nov-01 RMS Added unit-based registers 27-Sep-01 RMS Added queue count prototype 17-Sep-01 RMS Removed multiple console support 07-Sep-01 RMS Removed conditional externs on function prototypes 31-Aug-01 RMS Changed int64 to t_int64 for Windoze 17-Jul-01 RMS Added additional function prototypes 27-May-01 RMS Added multiple console support 15-May-01 RMS Increased string buffer size 25-Feb-01 RMS Revisions for V2.6 15-Oct-00 RMS Editorial revisions for V2.5 11-Jul-99 RMS Added unsigned int data types 14-Apr-99 RMS Converted t_addr to unsigned 04-Oct-98 RMS Additional definitions for V2.4 The interface between the simulator control package (SCP) and the simulator consists of the following routines and data structures sim_name simulator name string sim_devices[] array of pointers to simulated devices sim_PC pointer to saved PC register descriptor sim_interval simulator interval to next event sim_stop_messages[] array of pointers to stop messages sim_instr() instruction execution routine sim_load() binary loader routine sim_emax maximum number of words in an instruction In addition, the simulator must supply routines to print and parse architecture specific formats print_sym print symbolic output parse_sym parse symbolic input */ #ifndef SIM_DEFS_H_ #define SIM_DEFS_H_ 0 #include <stddef.h> #include <stdlib.h> #include <stdio.h> #if defined(_MSC_VER) && (_MSC_VER < 1900) #define snprintf _snprintf /* poor man's snprintf which will work most of the time but has different return value */ #endif #include <stdarg.h> #include <string.h> #include <errno.h> #include <limits.h> #ifdef _WIN32 #include <winsock2.h> #undef PACKED /* avoid macro name collision */ #undef ERROR /* avoid macro name collision */ #undef MEM_MAPPED /* avoid macro name collision */ #include <process.h> #endif #ifdef USE_REGEX #undef USE_REGEX #endif #if defined(HAVE_PCREPOSIX_H) #include <pcreposix.h> #define USE_REGEX 1 #elif defined(HAVE_REGEX_H) #include <regex.h> #define USE_REGEX 1 #endif #ifdef __cplusplus extern "C" { #endif /* avoid macro names collisions */ #ifdef MAX #undef MAX #endif #ifdef MIN #undef MIN #endif #ifdef PMASK #undef PMASK #endif #ifdef RS #undef RS #endif #ifdef PAGESIZE #undef PAGESIZE #endif #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif /* SCP API shim. The SCP API for version 4.0 introduces a number of "pointer-to-const" parameter qualifiers that were not present in the 3.x versions. To maintain compatibility with the earlier versions, the new qualifiers are expressed as "CONST" rather than "const". This allows macro removal of the qualifiers when compiling for SIMH 3.x. */ #ifndef CONST #define CONST const #endif /* Length specific integer declarations */ #if defined (VMS) #include <ints.h> #else typedef signed char int8; typedef signed short int16; typedef signed int int32; typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; #endif typedef int t_stat; /* status */ typedef int t_bool; /* boolean */ /* 64b integers */ #if defined (__GNUC__) /* GCC */ typedef signed long long t_int64; typedef unsigned long long t_uint64; #elif defined (_WIN32) /* Windows */ typedef signed __int64 t_int64; typedef unsigned __int64 t_uint64; #elif (defined (__ALPHA) || defined (__ia64)) && defined (VMS) /* 64b VMS */ typedef signed __int64 t_int64; typedef unsigned __int64 t_uint64; #elif defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */ typedef signed long t_int64; typedef unsigned long t_uint64; #else /* default */ #define t_int64 signed long long #define t_uint64 unsigned long long #endif /* end 64b */ #ifndef INT64_C #define INT64_C(x) x ## LL #endif #if defined (USE_INT64) /* 64b data */ typedef t_int64 t_svalue; /* signed value */ typedef t_uint64 t_value; /* value */ #else /* 32b data */ typedef int32 t_svalue; typedef uint32 t_value; #endif /* end 64b data */ #if defined (USE_INT64) && defined (USE_ADDR64) /* 64b address */ typedef t_uint64 t_addr; #define T_ADDR_W 64 #define T_ADDR_FMT LL_FMT #else /* 32b address */ typedef uint32 t_addr; #define T_ADDR_W 32 #define T_ADDR_FMT "" #endif /* end 64b address */ #if defined (_WIN32) #define vsnprintf _vsnprintf #endif #if defined (__DECC) && defined (__VMS) && (defined (__VAX) || (__CRTL_VER <= 70311000)) #define NO_vsnprintf #endif #if defined( NO_vsnprintf) #define STACKBUFSIZE 16384 #else #define STACKBUFSIZE 2048 #endif #if defined (_WIN32) /* Actually, a GCC issue */ #define LL_FMT "I64" #define LL_TYPE long long #else #if defined (__VAX) /* No 64 bit ints on VAX */ #define LL_FMT "l" #define LL_TYPE long #else #define LL_FMT "ll" #define LL_TYPE long long #endif #endif #if defined (VMS) && (defined (__ia64) || defined (__ALPHA)) #define HAVE_GLOB #endif #if defined (__linux) || defined (VMS) || defined (__APPLE__) #define HAVE_C99_STRFTIME 1 #endif #if defined (_WIN32) #define NULL_DEVICE "NUL:" #elif defined (_VMS) #define NULL_DEVICE "NL:" #else #define NULL_DEVICE "/dev/null" #endif /* Stubs for inlining */ #if defined(_MSC_VER) #define SIM_INLINE _inline #define SIM_NOINLINE _declspec (noinline) #elif defined(__GNUC__) #define SIM_INLINE inline #define SIM_NOINLINE __attribute__ ((noinline)) #else #define SIM_INLINE #define SIM_NOINLINE #endif /* Storage class modifier for weak link definition for sim_vm_init() */ #if defined(__cplusplus) #if defined(__GNUC__) #define WEAK __attribute__((weak)) #elif defined(_MSC_VER) #define WEAK __declspec(selectany) #else #define WEAK extern #endif #else #define WEAK #endif /* System independent definitions */ #define FLIP_SIZE (1 << 16) /* flip buf size */ #if !defined (PATH_MAX) /* usually in limits */ #define PATH_MAX 512 #endif #if (PATH_MAX >= 128) #define CBUFSIZE (128 + PATH_MAX) /* string buf size */ #else #define CBUFSIZE 256 #endif /* Breakpoint spaces definitions */ #define SIM_BKPT_N_SPC (1 << (32 - SIM_BKPT_V_SPC)) /* max number spaces */ #define SIM_BKPT_V_SPC (BRK_TYP_MAX + 1) /* location in arg */ /* Extended switch definitions (bits >= 26) */ #define SIM_SW_HIDE (1u << 26) /* enable hiding */ #define SIM_SW_REST (1u << 27) /* attach/restore */ #define SIM_SW_REG (1u << 28) /* register value */ #define SIM_SW_STOP (1u << 29) /* stop message */ #define SIM_SW_SHUT (1u << 30) /* shutdown */ /* Simulator status codes 0 ok 1 - (SCPE_BASE - 1) simulator specific SCPE_BASE - n general */ #define SCPE_OK 0 /* normal return */ #define SCPE_BASE 64 /* base for messages */ #define SCPE_NXM (SCPE_BASE + 0) /* nxm */ #define SCPE_UNATT (SCPE_BASE + 1) /* no file */ #define SCPE_IOERR (SCPE_BASE + 2) /* I/O error */ #define SCPE_CSUM (SCPE_BASE + 3) /* loader cksum */ #define SCPE_FMT (SCPE_BASE + 4) /* loader format */ #define SCPE_NOATT (SCPE_BASE + 5) /* not attachable */ #define SCPE_OPENERR (SCPE_BASE + 6) /* open error */ #define SCPE_MEM (SCPE_BASE + 7) /* alloc error */ #define SCPE_ARG (SCPE_BASE + 8) /* argument error */ #define SCPE_STEP (SCPE_BASE + 9) /* step expired */ #define SCPE_UNK (SCPE_BASE + 10) /* unknown command */ #define SCPE_RO (SCPE_BASE + 11) /* read only */ #define SCPE_INCOMP (SCPE_BASE + 12) /* incomplete */ #define SCPE_STOP (SCPE_BASE + 13) /* sim stopped */ #define SCPE_EXIT (SCPE_BASE + 14) /* sim exit */ #define SCPE_TTIERR (SCPE_BASE + 15) /* console tti err */ #define SCPE_TTOERR (SCPE_BASE + 16) /* console tto err */ #define SCPE_EOF (SCPE_BASE + 17) /* end of file */ #define SCPE_REL (SCPE_BASE + 18) /* relocation error */ #define SCPE_NOPARAM (SCPE_BASE + 19) /* no parameters */ #define SCPE_ALATT (SCPE_BASE + 20) /* already attached */ #define SCPE_TIMER (SCPE_BASE + 21) /* hwre timer err */ #define SCPE_SIGERR (SCPE_BASE + 22) /* signal err */ #define SCPE_TTYERR (SCPE_BASE + 23) /* tty setup err */ #define SCPE_SUB (SCPE_BASE + 24) /* subscript err */ #define SCPE_NOFNC (SCPE_BASE + 25) /* func not imp */ #define SCPE_UDIS (SCPE_BASE + 26) /* unit disabled */ #define SCPE_NORO (SCPE_BASE + 27) /* rd only not ok */ #define SCPE_INVSW (SCPE_BASE + 28) /* invalid switch */ #define SCPE_MISVAL (SCPE_BASE + 29) /* missing value */ #define SCPE_2FARG (SCPE_BASE + 30) /* too few arguments */ #define SCPE_2MARG (SCPE_BASE + 31) /* too many arguments */ #define SCPE_NXDEV (SCPE_BASE + 32) /* nx device */ #define SCPE_NXUN (SCPE_BASE + 33) /* nx unit */ #define SCPE_NXREG (SCPE_BASE + 34) /* nx register */ #define SCPE_NXPAR (SCPE_BASE + 35) /* nx parameter */ #define SCPE_NEST (SCPE_BASE + 36) /* nested DO */ #define SCPE_IERR (SCPE_BASE + 37) /* internal error */ #define SCPE_MTRLNT (SCPE_BASE + 38) /* tape rec lnt error */ #define SCPE_LOST (SCPE_BASE + 39) /* Telnet conn lost */ #define SCPE_TTMO (SCPE_BASE + 40) /* Telnet conn timeout */ #define SCPE_STALL (SCPE_BASE + 41) /* Telnet conn stall */ #define SCPE_AFAIL (SCPE_BASE + 42) /* assert failed */ #define SCPE_INVREM (SCPE_BASE + 43) /* invalid remote console command */ #define SCPE_NOTATT (SCPE_BASE + 44) /* not attached */ #define SCPE_EXPECT (SCPE_BASE + 45) /* expect matched */ #define SCPE_AMBREG (SCPE_BASE + 46) /* ambiguous register */ #define SCPE_REMOTE (SCPE_BASE + 47) /* remote console command */ #define SCPE_MAX_ERR (SCPE_BASE + 48) /* Maximum SCPE Error Value */ #define SCPE_KFLAG 0x1000 /* tti data flag */ #define SCPE_BREAK 0x2000 /* tti break flag */ #define SCPE_NOMESSAGE 0x10000000 /* message display supression flag */ #define SCPE_BARE_STATUS(stat) ((stat) & ~(SCPE_NOMESSAGE|SCPE_KFLAG|SCPE_BREAK)) /* Print value format codes */ #define PV_RZRO 0 /* right, zero fill */ #define PV_RSPC 1 /* right, space fill */ #define PV_RCOMMA 2 /* right, space fill. Comma separate every 3 */ #define PV_LEFT 3 /* left justify */ /* Default timing parameters */ #define KBD_POLL_WAIT 5000 /* keyboard poll */ #define SERIAL_IN_WAIT 100 /* serial in time */ #define SERIAL_OUT_WAIT 100 /* serial output */ #define NOQUEUE_WAIT 1000000 /* min check time */ /* Convert switch letter to bit mask */ #define SWMASK(x) (1u << (((int) (x)) - ((int) 'A'))) /* String match - at least one character required */ #define MATCH_CMD(ptr,cmd) ((NULL == (ptr)) || (!*(ptr)) || sim_strncasecmp ((ptr), (cmd), strlen (ptr))) /* End of Linked List/Queue value */ /* Chosen for 2 reasons: */ /* 1 - to not be NULL, this allowing the NULL value to */ /* indicate inclusion on a list */ /* and */ /* 2 - to not be a valid/possible pointer (alignment) */ #define QUEUE_LIST_END ((UNIT *)1) /* Typedefs for principal structures */ typedef struct DEVICE DEVICE; typedef struct UNIT UNIT; typedef struct REG REG; typedef struct CTAB CTAB; typedef struct C1TAB C1TAB; typedef struct SHTAB SHTAB; typedef struct MTAB MTAB; typedef struct SCHTAB SCHTAB; typedef struct BRKTAB BRKTAB; typedef struct BRKTYPTAB BRKTYPTAB; typedef struct EXPTAB EXPTAB; typedef struct EXPECT EXPECT; typedef struct SEND SEND; typedef struct DEBTAB DEBTAB; typedef struct FILEREF FILEREF; typedef struct MEMFILE MEMFILE; typedef struct BITFIELD BITFIELD; typedef t_stat (*ACTIVATE_API)(UNIT *unit, int32 interval); /* Device data structure */ struct DEVICE { const char *name; /* name */ UNIT *units; /* units */ REG *registers; /* registers */ MTAB *modifiers; /* modifiers */ uint32 numunits; /* #units */ uint32 aradix; /* address radix */ uint32 awidth; /* address width */ uint32 aincr; /* addr increment */ uint32 dradix; /* data radix */ uint32 dwidth; /* data width */ t_stat (*examine)(t_value *v, t_addr a, UNIT *up, int32 sw); /* examine routine */ t_stat (*deposit)(t_value v, t_addr a, UNIT *up, int32 sw); /* deposit routine */ t_stat (*reset)(DEVICE *dp); /* reset routine */ t_stat (*boot)(int32 u, DEVICE *dp); /* boot routine */ t_stat (*attach)(UNIT *up, CONST char *cp); /* attach routine */ t_stat (*detach)(UNIT *up); /* detach routine */ void *ctxt; /* context */ uint32 flags; /* flags */ uint32 dctrl; /* debug control */ DEBTAB *debflags; /* debug flags */ t_stat (*msize)(UNIT *up, int32 v, CONST char *cp, void *dp); /* mem size routine */ char *lname; /* logical name */ t_stat (*help)(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); /* help */ t_stat (*attach_help)(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); /* attach help */ void *help_ctx; /* Context available to help routines */ const char *(*description)(DEVICE *dptr); /* Device Description */ BRKTYPTAB *brk_types; /* Breakpoint types */ }; /* Device flags */ #define DEV_V_DIS 0 /* dev disabled */ #define DEV_V_DISABLE 1 /* dev disable-able */ #define DEV_V_DYNM 2 /* mem size dynamic */ #define DEV_V_DEBUG 3 /* debug capability */ #define DEV_V_TYPE 4 /* Attach type */ #define DEV_S_TYPE 3 /* Width of Type Field */ #define DEV_V_SECTORS 7 /* Unit Capacity is in 512byte sectors */ #define DEV_V_DONTAUTO 8 /* Do not auto detach already attached units */ #define DEV_V_FLATHELP 9 /* Use traditional (unstructured) help */ #define DEV_V_NOSAVE 10 /* Don't save device state */ #define DEV_V_UF_31 12 /* user flags, V3.1 */ #define DEV_V_UF 16 /* user flags */ #define DEV_V_RSV 31 /* reserved */ #define DEV_DIS (1 << DEV_V_DIS) /* device is currently disabled */ #define DEV_DISABLE (1 << DEV_V_DISABLE) /* device can be set enabled or disabled */ #define DEV_DYNM (1 << DEV_V_DYNM) /* device requires call on msize routine to change memory size */ #define DEV_DEBUG (1 << DEV_V_DEBUG) /* device supports SET DEBUG command */ #define DEV_SECTORS (1 << DEV_V_SECTORS) /* capacity is 512 byte sectors */ #define DEV_DONTAUTO (1 << DEV_V_DONTAUTO) /* Do not auto detach already attached units */ #define DEV_FLATHELP (1 << DEV_V_FLATHELP) /* Use traditional (unstructured) help */ #define DEV_NOSAVE (1 << DEV_V_NOSAVE) /* Don't save device state */ #define DEV_NET 0 /* Deprecated - meaningless */ #define DEV_TYPEMASK (((1 << DEV_S_TYPE) - 1) << DEV_V_TYPE) #define DEV_DISK (1 << DEV_V_TYPE) /* sim_disk Attach */ #define DEV_TAPE (2 << DEV_V_TYPE) /* sim_tape Attach */ #define DEV_MUX (3 << DEV_V_TYPE) /* sim_tmxr Attach */ #define DEV_ETHER (4 << DEV_V_TYPE) /* Ethernet Device */ #define DEV_DISPLAY (5 << DEV_V_TYPE) /* Display Device */ #define DEV_TYPE(dptr) ((dptr)->flags & DEV_TYPEMASK) #define DEV_UFMASK_31 (((1u << DEV_V_RSV) - 1) & ~((1u << DEV_V_UF_31) - 1)) #define DEV_UFMASK (((1u << DEV_V_RSV) - 1) & ~((1u << DEV_V_UF) - 1)) #define DEV_RFLAGS (DEV_UFMASK|DEV_DIS) /* restored flags */ /* Unit data structure Parts of the unit structure are device specific, that is, they are not referenced by the simulator control package and can be freely used by device simulators. Fields starting with 'buf', and flags starting with 'UF', are device specific. The definitions given here are for a typical sequential device. */ struct UNIT { UNIT *next; /* next active */ t_stat (*action)(UNIT *up); /* action routine */ char *filename; /* open file name */ FILE *fileref; /* file reference */ void *filebuf; /* memory buffer */ uint32 hwmark; /* high water mark */ int32 time; /* time out */ uint32 flags; /* flags */ uint32 dynflags; /* dynamic flags */ t_addr capac; /* capacity */ t_addr pos; /* file position */ void (*io_flush)(UNIT *up); /* io flush routine */ uint32 iostarttime; /* I/O start time */ int32 buf; /* buffer */ int32 wait; /* wait */ int32 u3; /* device specific */ int32 u4; /* device specific */ int32 u5; /* device specific */ int32 u6; /* device specific */ void *up7; /* device specific */ void *up8; /* device specific */ uint16 us9; /* device specific */ uint16 us10; /* device specific */ void *tmxr; /* TMXR linkage */ t_bool (*cancel)(UNIT *); double usecs_remaining; /* time balance for long delays */ char *uname; /* Unit name */ #ifdef SIM_ASYNCH_IO void (*a_check_completion)(UNIT *); t_bool (*a_is_active)(UNIT *); UNIT *a_next; /* next asynch active */ int32 a_event_time; ACTIVATE_API a_activate_call; /* Asynchronous Polling control */ /* These fields should only be referenced when holding the sim_tmxr_poll_lock */ t_bool a_polling_now; /* polling active flag */ int32 a_poll_waiter_count; /* count of polling threads */ /* waiting for this unit */ /* Asynchronous Timer control */ double a_due_time; /* due time for timer event */ double a_due_gtime; /* due time (in instructions) for timer event */ double a_usec_delay; /* time delay for timer event */ #endif }; /* Unit flags */ #define UNIT_V_UF_31 12 /* dev spec, V3.1 */ #define UNIT_V_UF 16 /* device specific */ #define UNIT_V_RSV 31 /* reserved!! */ #define UNIT_ATTABLE 0000001 /* attachable */ #define UNIT_RO 0000002 /* read only */ #define UNIT_FIX 0000004 /* fixed capacity */ #define UNIT_SEQ 0000010 /* sequential */ #define UNIT_ATT 0000020 /* attached */ #define UNIT_BINK 0000040 /* K = power of 2 */ #define UNIT_BUFABLE 0000100 /* bufferable */ #define UNIT_MUSTBUF 0000200 /* must buffer */ #define UNIT_BUF 0000400 /* buffered */ #define UNIT_ROABLE 0001000 /* read only ok */ #define UNIT_DISABLE 0002000 /* disable-able */ #define UNIT_DIS 0004000 /* disabled */ #define UNIT_IDLE 0040000 /* idle eligible */ /* Unused/meaningless flags */ #define UNIT_TEXT 0000000 /* text mode - no effect */ #define UNIT_UFMASK_31 (((1u << UNIT_V_RSV) - 1) & ~((1u << UNIT_V_UF_31) - 1)) #define UNIT_UFMASK (((1u << UNIT_V_RSV) - 1) & ~((1u << UNIT_V_UF) - 1)) #define UNIT_RFLAGS (UNIT_UFMASK|UNIT_DIS) /* restored flags */ /* Unit dynamic flags (dynflags) */ /* These flags are only set dynamically */ #define UNIT_ATTMULT 0000001 /* Allow multiple attach commands */ #define UNIT_TM_POLL 0000002 /* TMXR Polling unit */ #define UNIT_NO_FIO 0000004 /* fileref is NOT a FILE * */ #define UNIT_DISK_CHK 0000010 /* disk data debug checking (sim_disk) */ #define UNIT_TMR_UNIT 0000020 /* Unit registered as a calibrated timer */ #define UNIT_V_DF_TAPE 5 /* Bit offset for Tape Density reservation */ #define UNIT_S_DF_TAPE 3 /* Bits Reserved for Tape Density */ struct BITFIELD { const char *name; /* field name */ uint32 offset; /* starting bit */ uint32 width; /* width */ const char **valuenames; /* map of values to strings */ const char *format; /* value format string */ }; /* Register data structure */ struct REG { CONST char *name; /* name */ void *loc; /* location */ uint32 radix; /* radix */ uint32 width; /* width */ uint32 offset; /* starting bit */ uint32 depth; /* save depth */ const char *desc; /* description */ BITFIELD *fields; /* bit fields */ uint32 flags; /* flags */ uint32 qptr; /* circ q ptr */ size_t str_size; /* structure size */ }; /* Register flags */ #define REG_FMT 00003 /* see PV_x */ #define REG_RO 00004 /* read only */ #define REG_HIDDEN 00010 /* hidden */ #define REG_NZ 00020 /* must be non-zero */ #define REG_UNIT 00040 /* in unit struct */ #define REG_STRUCT 00100 /* in structure array */ #define REG_CIRC 00200 /* circular array */ #define REG_VMIO 00400 /* use VM data print/parse */ #define REG_VMAD 01000 /* use VM addr print/parse */ #define REG_FIT 02000 /* fit access to size */ #define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */ #define REG_V_UF 16 /* device specific */ #define REG_UFMASK (~((1u << REG_V_UF) - 1)) /* user flags mask */ #define REG_VMFLAGS (REG_VMIO | REG_UFMASK) /* call VM routine if any of these are set */ /* Command tables, base and alternate formats */ struct CTAB { const char *name; /* name */ t_stat (*action)(int32 flag, CONST char *cptr); /* action routine */ int32 arg; /* argument */ const char *help; /* help string/structured locator */ const char *help_base; /* structured help base*/ void (*message)(const char *unechoed_cmdline, t_stat stat); /* message printing routine */ }; struct C1TAB { const char *name; /* name */ t_stat (*action)(DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr);/* action routine */ int32 arg; /* argument */ const char *help; /* help string */ }; struct SHTAB { const char *name; /* name */ t_stat (*action)(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); int32 arg; /* argument */ const char *help; /* help string */ }; /* Modifier table - only extended entries have disp, reg, or flags */ struct MTAB { uint32 mask; /* mask */ uint32 match; /* match */ const char *pstring; /* print string */ const char *mstring; /* match string */ t_stat (*valid)(UNIT *up, int32 v, CONST char *cp, void *dp); /* validation routine */ t_stat (*disp)(FILE *st, UNIT *up, int32 v, CONST void *dp); /* display routine */ void *desc; /* value descriptor */ /* REG * if MTAB_VAL */ /* int * if not */ const char *help; /* help string */ }; /* mtab mask flag bits */ /* NOTE: MTAB_VALR and MTAB_VALO are only used to display help */ #define MTAB_XTD (1u << UNIT_V_RSV) /* ext entry flag */ #define MTAB_VDV (0001 | MTAB_XTD) /* valid for dev */ #define MTAB_VUN (0002 | MTAB_XTD) /* valid for unit */ #define MTAB_VALR (0004 | MTAB_XTD) /* takes a value (required) */ #define MTAB_VALO (0010 | MTAB_XTD) /* takes a value (optional) */ #define MTAB_NMO (0020 | MTAB_XTD) /* only if named */ #define MTAB_NC (0040 | MTAB_XTD) /* no UC conversion */ #define MTAB_QUOTE (0100 | MTAB_XTD) /* quoted string */ #define MTAB_SHP (0200 | MTAB_XTD) /* show takes parameter */ #define MODMASK(mptr,flag) (((mptr)->mask & (uint32)(flag)) == (uint32)(flag))/* flag mask test */ /* Search table */ struct SCHTAB { int32 logic; /* logical operator */ int32 boolop; /* boolean operator */ uint32 count; /* value count in mask and comp arrays */ t_value *mask; /* mask for logical */ t_value *comp; /* comparison for boolean */ }; /* Breakpoint table */ struct BRKTAB { t_addr addr; /* address */ uint32 typ; /* mask of types */ #define BRK_TYP_USR_TYPES ((1 << ('Z'-'A'+1)) - 1)/* all types A-Z */ #define BRK_TYP_DYN_STEPOVER (SWMASK ('Z'+1)) #define BRK_TYP_DYN_USR (SWMASK ('Z'+2)) #define BRK_TYP_DYN_ALL (BRK_TYP_DYN_USR|BRK_TYP_DYN_STEPOVER) /* Mask of All Dynamic types */ #define BRK_TYP_TEMP (SWMASK ('Z'+3)) /* Temporary (one-shot) */ #define BRK_TYP_MAX (('Z'-'A')+3) /* Maximum breakpoint type */ int32 cnt; /* proceed count */ char *act; /* action string */ double time_fired[SIM_BKPT_N_SPC]; /* instruction count when match occurred */ BRKTAB *next; /* list with same address value */ }; /* Breakpoint table */ struct BRKTYPTAB { uint32 btyp; /* type mask */ const char *desc; /* description */ }; #define BRKTYPE(typ,descrip) {SWMASK(typ), descrip} /* Expect rule */ struct EXPTAB { uint8 *match; /* match string */ uint32 size; /* match string size */ char *match_pattern; /* match pattern for format */ int32 cnt; /* proceed count */ int32 switches; /* flags */ #define EXP_TYP_PERSIST (SWMASK ('P')) /* rule persists after match, default is once a rule matches, it is removed */ #define EXP_TYP_CLEARALL (SWMASK ('C')) /* clear all rules after matching this rule, default is to once a rule matches, it is removed */ #define EXP_TYP_REGEX (SWMASK ('R')) /* rule pattern is a regular expression */ #define EXP_TYP_REGEX_I (SWMASK ('I')) /* regular expression pattern matching should be case independent */ #define EXP_TYP_TIME (SWMASK ('T')) /* halt delay is in microseconds instead of instructions */ #if defined(USE_REGEX) regex_t regex; /* compiled regular expression */ #endif char *act; /* action string */ }; /* Expect Context */ struct EXPECT { DEVICE *dptr; /* Device (for Debug) */ uint32 dbit; /* Debugging Bit */ EXPTAB *rules; /* match rules */ int32 size; /* count of match rules */ uint32 after; /* delay before halting */ uint8 *buf; /* buffer of output data which has produced */ uint32 buf_ins; /* buffer insertion point for the next output data */ uint32 buf_size; /* buffer size */ }; /* Send Context */ struct SEND { uint32 delay; /* instruction delay between sent data */ #define SEND_DEFAULT_DELAY 1000 /* default delay instruction count */ DEVICE *dptr; /* Device (for Debug) */ uint32 dbit; /* Debugging Bit */ uint32 after; /* instruction delay before sending any data */ double next_time; /* execution time when next data can be sent */ uint8 *buffer; /* buffer */ size_t bufsize; /* buffer size */ int32 insoff; /* insert offset */ int32 extoff; /* extra offset */ }; /* Debug table */ struct DEBTAB { const char *name; /* control name */ uint32 mask; /* control bit */ const char *desc; /* description */ }; /* Deprecated Debug macros. Use sim_debug() */ #define DEBUG_PRS(d) (sim_deb && d.dctrl) #define DEBUG_PRD(d) (sim_deb && d->dctrl) #define DEBUG_PRI(d,m) (sim_deb && (d.dctrl & (m))) #define DEBUG_PRJ(d,m) (sim_deb && ((d)->dctrl & (m))) #define SIM_DBG_EVENT 0x10000 #define SIM_DBG_ACTIVATE 0x20000 #define SIM_DBG_AIO_QUEUE 0x40000 /* Open File Reference */ struct FILEREF { char name[CBUFSIZE]; /* file name */ FILE *file; /* file handle */ int32 refcount; /* reference count */ }; struct MEMFILE { char *buf; /* buffered data */ size_t size; /* size */ size_t pos; /* data used */ }; /* The following macros exist to help populate structure contents They are dependent on the declaration order of the fields of the structures they exist to populate. */ #define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),0,(cap),0,NULL,0,0 #if defined (__STDC__) || defined (_WIN32) /* Variants which depend on how macro arguments are convered to strings */ /* Generic Register declaration for all fields. If the register structure is extended, this macro will be retained and a new macro will be provided that populates the new register structure */ #define REGDATA(nm,loc,rdx,wd,off,dep,desc,flds,fl,qptr,siz) \ #nm, &(loc), (rdx), (wd), (off), (dep), (desc), (flds), (fl), (qptr), (siz) /* Right Justified Octal Register Data */ #define ORDATA(nm,loc,wd) #nm, &(loc), 8, (wd), 0, 1, NULL, NULL /* Right Justified Decimal Register Data */ #define DRDATA(nm,loc,wd) #nm, &(loc), 10, (wd), 0, 1, NULL, NULL /* Right Justified Hexadecimal Register Data */ #define HRDATA(nm,loc,wd) #nm, &(loc), 16, (wd), 0, 1, NULL, NULL /* Right Justified Binary Register Data */ #define BINRDATA(nm,loc,wd) #nm, &(loc), 2, (wd), 0, 1, NULL, NULL /* One-bit binary flag at an arbitrary offset in a 32-bit word Register */ #define FLDATA(nm,loc,pos) #nm, &(loc), 2, 1, (pos), 1, NULL, NULL /* Arbitrary location and Radix Register */ #define GRDATA(nm,loc,rdx,wd,pos) #nm, &(loc), (rdx), (wd), (pos), 1, NULL, NULL /* Arrayed register whose data is kept in a standard C array Register */ #define BRDATA(nm,loc,rdx,wd,dep) #nm, (loc), (rdx), (wd), 0, (dep), NULL, NULL /* Same as above, but with additional description initializer */ #define ORDATAD(nm,loc,wd,desc) #nm, &(loc), 8, (wd), 0, 1, (desc), NULL #define DRDATAD(nm,loc,wd,desc) #nm, &(loc), 10, (wd), 0, 1, (desc), NULL #define HRDATAD(nm,loc,wd,desc) #nm, &(loc), 16, (wd), 0, 1, (desc), NULL #define BINRDATAD(nm,loc,wd,desc) #nm, &(loc), 2, (wd), 0, 1, (desc), NULL #define FLDATAD(nm,loc,pos,desc) #nm, &(loc), 2, 1, (pos), 1, (desc), NULL #define GRDATAD(nm,loc,rdx,wd,pos,desc) #nm, &(loc), (rdx), (wd), (pos), 1, (desc), NULL #define BRDATAD(nm,loc,rdx,wd,dep,desc) #nm, (loc), (rdx), (wd), 0, (dep), (desc), NULL /* Same as above, but with additional description initializer, and bitfields */ #define ORDATADF(nm,loc,wd,desc,flds) #nm, &(loc), 8, (wd), 0, 1, (desc), (flds) #define DRDATADF(nm,loc,wd,desc,flds) #nm, &(loc), 10, (wd), 0, 1, (desc), (flds) #define HRDATADF(nm,loc,wd,desc,flds) #nm, &(loc), 16, (wd), 0, 1, (desc), (flds) #define BINRDATADF(nm,loc,wd) #nm, &(loc), 2, (wd), 0, 1, NULL, NULL #define FLDATADF(nm,loc,pos,desc,flds) #nm, &(loc), 2, 1, (pos), 1, (desc), (flds) #define GRDATADF(nm,loc,rdx,wd,pos,desc,flds) #nm, &(loc), (rdx), (wd), (pos), 1, (desc), (flds) #define BRDATADF(nm,loc,rdx,wd,dep,desc,flds) #nm, (loc), (rdx), (wd), 0, (dep), (desc), (flds) #define BIT(nm) {#nm, 0xffffffff, 1} /* Single Bit definition */ #define BITNC {"", 0xffffffff, 1} /* Don't care Bit definition */ #define BITF(nm,sz) {#nm, 0xffffffff, sz} /* Bit Field definition */ #define BITNCF(sz) {"", 0xffffffff, sz} /* Don't care Bit Field definition */ #define BITFFMT(nm,sz,fmt) {#nm, 0xffffffff, sz, NULL, #fmt}/* Bit Field definition with Output format */ #define BITFNAM(nm,sz,names) {#nm, 0xffffffff, sz, names} /* Bit Field definition with value->name map */ #else /* For non-STD-C compiler which can't stringify macro arguments with # */ #define REGDATA(nm,loc,rdx,wd,off,dep,desc,flds,fl,qptr,siz) \ "nm", &(loc), (rdx), (wd), (off), (dep), (desc), (flds), (fl), (qptr), (siz) #define ORDATA(nm,loc,wd) "nm", &(loc), 8, (wd), 0, 1, NULL, NULL #define DRDATA(nm,loc,wd) "nm", &(loc), 10, (wd), 0, 1, NULL, NULL #define HRDATA(nm,loc,wd) "nm", &(loc), 16, (wd), 0, 1, NULL, NULL #define BINRDATA(nm,loc,wd) "nm", &(loc), 2, (wd), 0, 1, NULL, NULL #define FLDATA(nm,loc,pos) "nm", &(loc), 2, 1, (pos), 1, NULL, NULL #define GRDATA(nm,loc,rdx,wd,pos) "nm", &(loc), (rdx), (wd), (pos), 1, NULL, NULL #define BRDATA(nm,loc,rdx,wd,dep) "nm", (loc), (rdx), (wd), 0, (dep), NULL, NULL #define ORDATAD(nm,loc,wd,desc) "nm", &(loc), 8, (wd), 0, 1, (desc), NULL #define DRDATAD(nm,loc,wd,desc) "nm", &(loc), 10, (wd), 0, 1, (desc), NULL #define HRDATAD(nm,loc,wd,desc) "nm", &(loc), 16, (wd), 0, 1, (desc), NULL #define BINRDATAD(nm,loc,wd,desc) "nm", &(loc), 2, (wd), 0, 1, (desc), NULL #define FLDATAD(nm,loc,pos,desc) "nm", &(loc), 2, 1, (pos), 1, (desc), NULL #define GRDATAD(nm,loc,rdx,wd,pos,desc) "nm", &(loc), (rdx), (wd), (pos), 1, (desc), NULL #define BRDATAD(nm,loc,rdx,wd,dep,desc) "nm", (loc), (rdx), (wd), 0, (dep), (desc), NULL #define ORDATADF(nm,loc,wd,desc,flds) "nm", &(loc), 8, (wd), 0, 1, (desc), (flds) #define DRDATADF(nm,loc,wd,desc,flds) "nm", &(loc), 10, (wd), 0, 1, (desc), (flds) #define HRDATADF(nm,loc,wd,desc,flds) "nm", &(loc), 16, (wd), 0, 1, (desc), (flds) #define BINRDATADF(nm,loc,wd,desc,flds) "nm", &(loc), 2, (wd), 0, 1, (desc), (flds) #define FLDATADF(nm,loc,pos,desc,flds) "nm", &(loc), 2, 1, (pos), 1, (desc), (flds) #define GRDATADF(nm,loc,rdx,wd,pos,desc,flds) "nm", &(loc), (rdx), (wd), (pos), 1, (desc), (flds) #define BRDATADF(nm,loc,rdx,wd,dep,desc,flds) "nm", (loc), (rdx), (wd), 0, (dep), (desc), (flds) #define BIT(nm) {"nm", 0xffffffff, 1} /* Single Bit definition */ #define BITNC {"", 0xffffffff, 1} /* Don't care Bit definition */ #define BITF(nm,sz) {"nm", 0xffffffff, sz} /* Bit Field definition */ #define BITNCF(sz) {"", 0xffffffff, sz} /* Don't care Bit Field definition */ #define BITFFMT(nm,sz,fmt) {"nm", 0xffffffff, sz, NULL, "fmt"}/* Bit Field definition with Output format */ #define BITFNAM(nm,sz,names) {"nm", 0xffffffff, sz, names} /* Bit Field definition with value->name map */ #endif #define ENDBITS {NULL} /* end of bitfield list */ /* Arrayed register whose data is part of the UNIT structure */ #define URDATA(nm,loc,rdx,wd,off,dep,fl) \ REGDATA(nm,(loc),(rdx),(wd),(off),(dep),NULL,NULL,((fl) | REG_UNIT),0,0) /* Arrayed register whose data is part of an arbitrary structure */ #define STRDATA(nm,loc,rdx,wd,off,dep,siz,fl) \ REGDATA(nm,(loc),(rdx),(wd),(off),(dep),NULL,NULL,((fl) | REG_STRUCT),0,(siz)) /* Same as above, but with additional description initializer */ #define URDATAD(nm,loc,rdx,wd,off,dep,fl,desc) \ REGDATA(nm,(loc),(rdx),(wd),(off),(dep),(desc),NULL,((fl) | REG_UNIT),0,0) #define STRDATAD(nm,loc,rdx,wd,off,dep,siz,fl,desc) \ REGDATA(nm,(loc),(rdx),(wd),(off),(dep),(desc),NULL,((fl) | REG_STRUCT),0,(siz)) /* Same as above, but with additional description initializer, and bitfields */ #define URDATADF(nm,loc,rdx,wd,off,dep,fl,desc,flds) \ REGDATA(nm,(loc),(rdx),(wd),(off),(dep),(desc),(flds),((fl) | REG_UNIT),0,0) #define STRDATADF(nm,loc,rdx,wd,off,dep,siz,fl,desc,flds) \ REGDATA(nm,(loc),(rdx),(wd),(off),(dep),(desc),(flds),((fl) | REG_STRUCT),0,(siz)) /* Function prototypes */ #include "scp.h" #include "sim_console.h" #include "sim_timer.h" #include "sim_fio.h" /* Macro to ALWAYS execute the specified expression and fail if it evaluates to false. */ /* This replaces any references to "assert()" which should never be invoked */ /* with an expression which causes side effects (i.e. must be executed for */ /* the program to work correctly) */ #define ASSURE(_Expression) while (!(_Expression)) {fprintf(stderr, "%s failed at %s line %d\n", #_Expression, __FILE__, __LINE__); \ sim_printf("%s failed at %s line %d\n", #_Expression, __FILE__, __LINE__); \ abort();} /* Asynch/Threaded I/O support */ #if defined (SIM_ASYNCH_IO) #include <pthread.h> #define SIM_ASYNCH_CLOCKS 1 extern pthread_mutex_t sim_asynch_lock; extern pthread_cond_t sim_asynch_wake; extern pthread_mutex_t sim_timer_lock; extern pthread_cond_t sim_timer_wake; extern t_bool sim_timer_event_canceled; extern int32 sim_tmxr_poll_count; extern pthread_cond_t sim_tmxr_poll_cond; extern pthread_mutex_t sim_tmxr_poll_lock; extern pthread_t sim_asynch_main_threadid; extern UNIT * volatile sim_asynch_queue; extern volatile t_bool sim_idle_wait; extern int32 sim_asynch_check; extern int32 sim_asynch_latency; extern int32 sim_asynch_inst_latency; /* Thread local storage */ #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__hpux) && !defined(__OpenBSD__) && !defined(_AIX) #define AIO_TLS __thread #elif defined(_MSC_VER) #define AIO_TLS __declspec(thread) #else /* Other compiler environment, then don't worry about thread local storage. */ /* It is primarily used only used in debugging messages */ #define AIO_TLS #endif #define AIO_QUEUE_CHECK(que, lock) \ do { \ UNIT *_cptr; \ if (lock) \ pthread_mutex_lock (lock); \ for (_cptr = que; \ (_cptr != QUEUE_LIST_END); \ _cptr = _cptr->next) \ if (!_cptr->next) { \ if (sim_deb) { \ sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Queue Corruption detected\n");\ fclose(sim_deb); \ } \ sim_printf("Queue Corruption detected\n"); \ abort(); \ } \ if (lock) \ pthread_mutex_unlock (lock); \ } while (0) #define AIO_MAIN_THREAD (pthread_equal ( pthread_self(), sim_asynch_main_threadid )) #define AIO_LOCK \ pthread_mutex_lock(&sim_asynch_lock) #define AIO_UNLOCK \ pthread_mutex_unlock(&sim_asynch_lock) #define AIO_IS_ACTIVE(uptr) (((uptr)->a_is_active ? (uptr)->a_is_active (uptr) : FALSE) || ((uptr)->a_next)) #if defined(SIM_ASYNCH_MUX) #define AIO_CANCEL(uptr) \ if (((uptr)->dynflags & UNIT_TM_POLL) && \ !((uptr)->next) && !((uptr)->a_next)) { \ (uptr)->a_polling_now = FALSE; \ sim_tmxr_poll_count -= (uptr)->a_poll_waiter_count; \ (uptr)->a_poll_waiter_count = 0; \ } #endif /* defined(SIM_ASYNCH_MUX) */ #if !defined(AIO_CANCEL) #define AIO_CANCEL(uptr) #endif /* !defined(AIO_CANCEL) */ #define AIO_EVENT_BEGIN(uptr) \ do { \ int __was_poll = uptr->dynflags & UNIT_TM_POLL #define AIO_EVENT_COMPLETE(uptr, reason) \ if (__was_poll) { \ pthread_mutex_lock (&sim_tmxr_poll_lock); \ uptr->a_polling_now = FALSE; \ if (uptr->a_poll_waiter_count) { \ sim_tmxr_poll_count -= uptr->a_poll_waiter_count; \ uptr->a_poll_waiter_count = 0; \ if (0 == sim_tmxr_poll_count) \ pthread_cond_broadcast (&sim_tmxr_poll_cond); \ } \ pthread_mutex_unlock (&sim_tmxr_poll_lock); \ } \ AIO_UPDATE_QUEUE; \ } while (0) #if defined(__DECC_VER) #include <builtins> #if defined(__IA64) #define USE_AIO_INTRINSICS 1 #endif #endif #if defined(_WIN32) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) #define USE_AIO_INTRINSICS 1 #endif /* Provide a way to test both Intrinsic and Lock based queue manipulations */ /* when both are available on a particular platform */ #if defined(DONT_USE_AIO_INTRINSICS) && defined(USE_AIO_INTRINSICS) #undef USE_AIO_INTRINSICS #endif #ifdef USE_AIO_INTRINSICS /* This approach uses intrinsics to manage access to the link list head */ /* sim_asynch_queue. This implementation is a completely lock free design */ /* which avoids the potential ABA issues. */ #define AIO_QUEUE_MODE "Lock free asynchronous event queue" #define AIO_INIT \ do { \ int tmr; \ sim_asynch_main_threadid = pthread_self(); \ /* Empty list/list end uses the point value (void *)1. \ This allows NULL in an entry's a_next pointer to \ indicate that the entry is not currently in any list */ \ sim_asynch_queue = QUEUE_LIST_END; \ for (tmr=0; tmr<SIM_NTIMERS; tmr++) \ sim_clock_cosched_queue[tmr] = QUEUE_LIST_END; \ } while (0) #define AIO_CLEANUP \ do { \ pthread_mutex_destroy(&sim_asynch_lock); \ pthread_cond_destroy(&sim_asynch_wake); \ pthread_mutex_destroy(&sim_timer_lock); \ pthread_cond_destroy(&sim_timer_wake); \ pthread_mutex_destroy(&sim_tmxr_poll_lock); \ pthread_cond_destroy(&sim_tmxr_poll_cond); \ } while (0) #ifdef _WIN32 #elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) #define InterlockedCompareExchangePointer(Destination, Exchange, Comparand) __sync_val_compare_and_swap(Destination, Comparand, Exchange) #elif defined(__DECC_VER) #define InterlockedCompareExchangePointer(Destination, Exchange, Comparand) (void *)((int32)_InterlockedCompareExchange64(Destination, Exchange, Comparand)) #else #error "Implementation of function InterlockedCompareExchangePointer() is needed to build with USE_AIO_INTRINSICS" #endif #define AIO_ILOCK AIO_LOCK #define AIO_IUNLOCK AIO_UNLOCK #define AIO_QUEUE_VAL (UNIT *)(InterlockedCompareExchangePointer((void * volatile *)&sim_asynch_queue, (void *)sim_asynch_queue, NULL)) #define AIO_QUEUE_SET(newval, oldval) (UNIT *)(InterlockedCompareExchangePointer((void * volatile *)&sim_asynch_queue, (void *)newval, oldval)) #define AIO_UPDATE_QUEUE sim_aio_update_queue () #define AIO_ACTIVATE(caller, uptr, event_time) \ if (!pthread_equal ( pthread_self(), sim_asynch_main_threadid )) { \ sim_aio_activate ((ACTIVATE_API)caller, uptr, event_time); \ return SCPE_OK; \ } else (void)0 #else /* !USE_AIO_INTRINSICS */ /* This approach uses a pthread mutex to manage access to the link list */ /* head sim_asynch_queue. It will always work, but may be slower than the */ /* lock free approach when using USE_AIO_INTRINSICS */ #define AIO_QUEUE_MODE "Lock based asynchronous event queue" #define AIO_INIT \ do { \ int tmr; \ pthread_mutexattr_t attr; \ \ pthread_mutexattr_init (&attr); \ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \ pthread_mutex_init (&sim_asynch_lock, &attr); \ pthread_mutexattr_destroy (&attr); \ sim_asynch_main_threadid = pthread_self(); \ /* Empty list/list end uses the point value (void *)1. \ This allows NULL in an entry's a_next pointer to \ indicate that the entry is not currently in any list */ \ sim_asynch_queue = QUEUE_LIST_END; \ for (tmr=0; tmr<SIM_NTIMERS; tmr++) \ sim_clock_cosched_queue[tmr] = QUEUE_LIST_END; \ } while (0) #define AIO_CLEANUP \ do { \ pthread_mutex_destroy(&sim_asynch_lock); \ pthread_cond_destroy(&sim_asynch_wake); \ pthread_mutex_destroy(&sim_timer_lock); \ pthread_cond_destroy(&sim_timer_wake); \ pthread_mutex_destroy(&sim_tmxr_poll_lock); \ pthread_cond_destroy(&sim_tmxr_poll_cond); \ } while (0) #define AIO_ILOCK AIO_LOCK #define AIO_IUNLOCK AIO_UNLOCK #define AIO_QUEUE_VAL sim_asynch_queue #define AIO_QUEUE_SET(newval, oldval) ((sim_asynch_queue = newval),oldval) #define AIO_UPDATE_QUEUE sim_aio_update_queue () #define AIO_ACTIVATE(caller, uptr, event_time) \ if (!pthread_equal ( pthread_self(), sim_asynch_main_threadid )) { \ sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "Queueing Asynch event for %s after %d instructions\n", sim_uname(uptr), event_time);\ AIO_LOCK; \ if (uptr->a_next) { /* already queued? */ \ uptr->a_activate_call = sim_activate_abs; \ } else { \ uptr->a_next = sim_asynch_queue; \ uptr->a_event_time = event_time; \ uptr->a_activate_call = (ACTIVATE_API)&caller; \ sim_asynch_queue = uptr; \ } \ if (sim_idle_wait) { \ sim_debug (TIMER_DBG_IDLE, &sim_timer_dev, "waking due to event on %s after %d instructions\n", sim_uname(uptr), event_time);\ pthread_cond_signal (&sim_asynch_wake); \ } \ AIO_UNLOCK; \ sim_asynch_check = 0; \ return SCPE_OK; \ } else (void)0 #endif /* USE_AIO_INTRINSICS */ #define AIO_VALIDATE if (!pthread_equal ( pthread_self(), sim_asynch_main_threadid )) {sim_printf("Improper thread context for operation\n"); abort();} #define AIO_CHECK_EVENT \ if (0 > --sim_asynch_check) { \ AIO_UPDATE_QUEUE; \ sim_asynch_check = sim_asynch_inst_latency; \ } else (void)0 #define AIO_SET_INTERRUPT_LATENCY(instpersec) \ do { \ sim_asynch_inst_latency = (int32)((((double)(instpersec))*sim_asynch_latency)/1000000000);\ if (sim_asynch_inst_latency == 0) \ sim_asynch_inst_latency = 1; \ } while (0) #else /* !SIM_ASYNCH_IO */ #define AIO_QUEUE_MODE "Asynchronous I/O is not available" #define AIO_UPDATE_QUEUE #define AIO_ACTIVATE(caller, uptr, event_time) #define AIO_VALIDATE #define AIO_CHECK_EVENT #define AIO_INIT #define AIO_MAIN_THREAD TRUE #define AIO_LOCK #define AIO_UNLOCK #define AIO_CLEANUP #define AIO_EVENT_BEGIN(uptr) #define AIO_EVENT_COMPLETE(uptr, reason) #define AIO_IS_ACTIVE(uptr) FALSE #define AIO_CANCEL(uptr) #define AIO_SET_INTERRUPT_LATENCY(instpersec) #define AIO_TLS #endif /* SIM_ASYNCH_IO */ #ifdef __cplusplus } #endif #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 | /* sim_disk.c: simulator disk support library Copyright (c) 2011, Mark Pizzolato Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the names of Mark Pizzolato shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Mark Pizzolato. This is the place which hides processing of various disk formats, as well as OS-specific direct hardware access. 25-Jan-11 MP Initial Implemementation Public routines: sim_disk_attach attach disk unit sim_disk_detach detach disk unit sim_disk_attach_help help routine for attaching disks sim_disk_rdsect read disk sectors sim_disk_rdsect_a read disk sectors asynchronously sim_disk_wrsect write disk sectors sim_disk_wrsect_a write disk sectors asynchronously sim_disk_unload unload or detach a disk as needed sim_disk_reset reset unit sim_disk_wrp TRUE if write protected sim_disk_isavailable TRUE if available for I/O sim_disk_size get disk size sim_disk_set_fmt set disk format sim_disk_show_fmt show disk format sim_disk_set_capac set disk capacity sim_disk_show_capac show disk capacity sim_disk_set_async enable asynchronous operation sim_disk_clr_async disable asynchronous operation sim_disk_data_trace debug support Internal routines: sim_os_disk_open_raw platform specific open raw device sim_os_disk_close_raw platform specific close raw device sim_os_disk_size_raw platform specific raw device size sim_os_disk_unload_raw platform specific disk unload/eject sim_os_disk_rdsect platform specific read sectors sim_os_disk_wrsect platform specific write sectors sim_vhd_disk_open platform independent open virtual disk file sim_vhd_disk_create platform independent create virtual disk file sim_vhd_disk_create_diff platform independent create differencing virtual disk file sim_vhd_disk_close platform independent close virtual disk file sim_vhd_disk_size platform independent virtual disk size sim_vhd_disk_rdsect platform independent read virtual disk sectors sim_vhd_disk_wrsect platform independent write virtual disk sectors */ #define _FILE_OFFSET_BITS 64 /* 64 bit file offset for raw I/O operations */ #include "sim_defs.h" #include "sim_disk.h" #include "sim_ether.h" #include <ctype.h> #include <sys/stat.h> #ifdef _WIN32 #include <windows.h> #endif #if defined SIM_ASYNCH_IO #include <pthread.h> #endif struct disk_context { DEVICE *dptr; /* Device for unit (access to debug flags) */ uint32 dbit; /* debugging bit */ uint32 sector_size; /* Disk Sector Size (of the pseudo disk) */ uint32 capac_factor; /* Units of Capacity (2 = word, 1 = byte) */ uint32 xfer_element_size; /* Disk Bus Transfer size (1 - byte, 2 - word, 4 - longword) */ uint32 storage_sector_size;/* Sector size of the containing storage */ uint32 removable; /* Removable device flag */ uint32 auto_format; /* Format determined dynamically */ #if defined _WIN32 HANDLE disk_handle; /* OS specific Raw device handle */ #endif #if defined SIM_ASYNCH_IO int asynch_io; /* Asynchronous Interrupt scheduling enabled */ int asynch_io_latency; /* instructions to delay pending interrupt */ pthread_mutex_t lock; pthread_t io_thread; /* I/O Thread Id */ pthread_mutex_t io_lock; pthread_cond_t io_cond; pthread_cond_t io_done; pthread_cond_t startup_cond; int io_dop; uint8 *buf; t_seccnt *rsects; t_seccnt sects; t_lba lba; DISK_PCALLBACK callback; t_stat io_status; #endif }; #define disk_ctx up8 /* Field in Unit structure which points to the disk_context */ #if defined SIM_ASYNCH_IO #define AIO_CALLSETUP \ struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; \ \ if ((!callback) || !ctx->asynch_io) #define AIO_CALL(op, _lba, _buf, _rsects, _sects, _callback) \ if (ctx->asynch_io) { \ struct disk_context *ctx = \ (struct disk_context *)uptr->disk_ctx; \ \ pthread_mutex_lock (&ctx->io_lock); \ \ sim_debug (ctx->dbit, ctx->dptr, \ "sim_disk AIO_CALL(op=%d, unit=%d, lba=0x%X, sects=%d)\n",\ op, (int)(uptr-ctx->dptr->units), _lba, _sects);\ \ if (ctx->callback) \ abort(); /* horrible mistake, stop */ \ ctx->io_dop = op; \ ctx->lba = _lba; \ ctx->buf = _buf; \ ctx->sects = _sects; \ ctx->rsects = _rsects; \ ctx->callback = _callback; \ pthread_cond_signal (&ctx->io_cond); \ pthread_mutex_unlock (&ctx->io_lock); \ } \ else \ if (_callback) \ (_callback) (uptr, r); #define DOP_DONE 0 /* close */ #define DOP_RSEC 1 /* sim_disk_rdsect_a */ #define DOP_WSEC 2 /* sim_disk_wrsect_a */ #define DOP_IAVL 3 /* sim_disk_isavailable_a */ static void * _disk_io(void *arg) { UNIT* volatile uptr = (UNIT*)arg; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; /* Boost Priority for this I/O thread vs the CPU instruction execution thread which in general won't be readily yielding the processor when this thread needs to run */ sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); sim_debug (ctx->dbit, ctx->dptr, "_disk_io(unit=%d) starting\n", (int)(uptr-ctx->dptr->units)); pthread_mutex_lock (&ctx->io_lock); pthread_cond_signal (&ctx->startup_cond); /* Signal we're ready to go */ while (ctx->asynch_io) { pthread_cond_wait (&ctx->io_cond, &ctx->io_lock); if (ctx->io_dop == DOP_DONE) break; pthread_mutex_unlock (&ctx->io_lock); switch (ctx->io_dop) { case DOP_RSEC: ctx->io_status = sim_disk_rdsect (uptr, ctx->lba, ctx->buf, ctx->rsects, ctx->sects); break; case DOP_WSEC: ctx->io_status = sim_disk_wrsect (uptr, ctx->lba, ctx->buf, ctx->rsects, ctx->sects); break; case DOP_IAVL: ctx->io_status = sim_disk_isavailable (uptr); break; } pthread_mutex_lock (&ctx->io_lock); ctx->io_dop = DOP_DONE; pthread_cond_signal (&ctx->io_done); sim_activate (uptr, ctx->asynch_io_latency); } pthread_mutex_unlock (&ctx->io_lock); sim_debug (ctx->dbit, ctx->dptr, "_disk_io(unit=%d) exiting\n", (int)(uptr-ctx->dptr->units)); return NULL; } /* This routine is called in the context of the main simulator thread before processing events for any unit. It is only called when an asynchronous thread has called sim_activate() to activate a unit. The job of this routine is to put the unit in proper condition to digest what may have occurred in the asynchrconous thread. Since disk processing only handles a single I/O at a time to a particular disk device (due to using stdio for the SimH Disk format and stdio doesn't have an atomic seek+(read|write) operation), we have the opportunity to possibly detect improper attempts to issue multiple concurrent I/O requests. */ static void _disk_completion_dispatch (UNIT *uptr) { struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; DISK_PCALLBACK callback = ctx->callback; sim_debug (ctx->dbit, ctx->dptr, "_disk_completion_dispatch(unit=%d, dop=%d, callback=%p)\n", (int)(uptr-ctx->dptr->units), ctx->io_dop, ctx->callback); if (ctx->io_dop != DOP_DONE) abort(); /* horribly wrong, stop */ if (ctx->callback && ctx->io_dop == DOP_DONE) { ctx->callback = NULL; callback (uptr, ctx->io_status); } } static t_bool _disk_is_active (UNIT *uptr) { struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; if (ctx) { sim_debug (ctx->dbit, ctx->dptr, "_disk_is_active(unit=%d, dop=%d)\n", (int)(uptr-ctx->dptr->units), ctx->io_dop); return (ctx->io_dop != DOP_DONE); } return FALSE; } static t_bool _disk_cancel (UNIT *uptr) { struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; if (ctx) { sim_debug (ctx->dbit, ctx->dptr, "_disk_cancel(unit=%d, dop=%d)\n", (int)(uptr-ctx->dptr->units), ctx->io_dop); if (ctx->asynch_io) { pthread_mutex_lock (&ctx->io_lock); while (ctx->io_dop != DOP_DONE) pthread_cond_wait (&ctx->io_done, &ctx->io_lock); pthread_mutex_unlock (&ctx->io_lock); } } return FALSE; } #else #define AIO_CALLSETUP #define AIO_CALL(op, _lba, _buf, _rsects, _sects, _callback) \ if (_callback) \ (_callback) (uptr, r); #endif /* Forward declarations */ static t_stat sim_vhd_disk_implemented (void); static FILE *sim_vhd_disk_open (const char *rawdevicename, const char *openmode); static FILE *sim_vhd_disk_create (const char *szVHDPath, t_offset desiredsize); static FILE *sim_vhd_disk_create_diff (const char *szVHDPath, const char *szParentVHDPath); static FILE *sim_vhd_disk_merge (const char *szVHDPath, char **ParentVHD); static int sim_vhd_disk_close (FILE *f); static void sim_vhd_disk_flush (FILE *f); static t_offset sim_vhd_disk_size (FILE *f); static t_stat sim_vhd_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects); static t_stat sim_vhd_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects); static t_stat sim_vhd_disk_clearerr (UNIT *uptr); static t_stat sim_vhd_disk_set_dtype (FILE *f, const char *dtype); static const char *sim_vhd_disk_get_dtype (FILE *f); static t_stat sim_os_disk_implemented_raw (void); static FILE *sim_os_disk_open_raw (const char *rawdevicename, const char *openmode); static int sim_os_disk_close_raw (FILE *f); static void sim_os_disk_flush_raw (FILE *f); static t_offset sim_os_disk_size_raw (FILE *f); static t_stat sim_os_disk_unload_raw (FILE *f); static t_bool sim_os_disk_isavailable_raw (FILE *f); static t_stat sim_os_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects); static t_stat sim_os_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects); static t_stat sim_os_disk_info_raw (FILE *f, uint32 *sector_size, uint32 *removable); static char *HostPathToVhdPath (const char *szHostPath, char *szVhdPath, size_t VhdPathSize); static char *VhdPathToHostPath (const char *szVhdPath, char *szHostPath, size_t HostPathSize); static t_offset get_filesystem_size (UNIT *uptr); struct sim_disk_fmt { const char *name; /* name */ int32 uflags; /* unit flags */ int32 fmtval; /* Format type value */ t_stat (*impl_fnc)(void); /* Implemented Test Function */ }; static struct sim_disk_fmt fmts[DKUF_N_FMT] = { { "SIMH", 0, DKUF_F_STD, NULL}, { "RAW", 0, DKUF_F_RAW, sim_os_disk_implemented_raw}, { "VHD", 0, DKUF_F_VHD, sim_vhd_disk_implemented}, { NULL, 0, 0} }; /* Set disk format */ t_stat sim_disk_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { uint32 f; if (uptr == NULL) return SCPE_IERR; if (cptr == NULL) return SCPE_ARG; for (f = 0; f < DKUF_N_FMT && fmts[f].name; f++) { if (fmts[f].name && (strcmp (cptr, fmts[f].name) == 0)) { if ((fmts[f].impl_fnc) && (fmts[f].impl_fnc() != SCPE_OK)) return SCPE_NOFNC; uptr->flags = (uptr->flags & ~DKUF_FMT) | (fmts[f].fmtval << DKUF_V_FMT) | fmts[f].uflags; return SCPE_OK; } } return SCPE_ARG; } /* Show disk format */ t_stat sim_disk_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { int32 f = DK_GET_FMT (uptr); size_t i; for (i = 0; i < DKUF_N_FMT; i++) if (fmts[i].fmtval == f) { fprintf (st, "%s format", fmts[i].name); return SCPE_OK; } fprintf (st, "invalid format"); return SCPE_OK; } /* Set disk capacity */ t_stat sim_disk_set_capac (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { t_offset cap; t_stat r; DEVICE *dptr = find_dev_from_unit (uptr); if ((cptr == NULL) || (*cptr == 0)) return SCPE_ARG; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; cap = (t_offset) get_uint (cptr, 10, sim_taddr_64? 2000000: 2000, &r); if (r != SCPE_OK) return SCPE_ARG; uptr->capac = (t_addr)((cap * ((t_offset) 1000000))/((dptr->flags & DEV_SECTORS) ? 512 : 1)); return SCPE_OK; } /* Show disk capacity */ t_stat sim_disk_show_capac (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { const char *cap_units = "B"; DEVICE *dptr = find_dev_from_unit (uptr); t_offset capac = ((t_offset)uptr->capac)*((dptr->flags & DEV_SECTORS) ? 512 : 1); if ((dptr->dwidth / dptr->aincr) == 16) cap_units = "W"; if (capac) { if (capac >= (t_offset) 1000000) fprintf (st, "capacity=%dM%s", (uint32) (capac / ((t_offset) 1000000)), cap_units); else if (uptr->capac >= (t_addr) 1000) fprintf (st, "capacity=%dK%s", (uint32) (capac / ((t_offset) 1000)), cap_units); else fprintf (st, "capacity=%d%s", (uint32) capac, cap_units); } else fprintf (st, "undefined capacity"); return SCPE_OK; } /* Test for available */ t_bool sim_disk_isavailable (UNIT *uptr) { if (!(uptr->flags & UNIT_ATT)) /* attached? */ return FALSE; switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_STD: /* SIMH format */ return TRUE; case DKUF_F_VHD: /* VHD format */ return TRUE; break; case DKUF_F_RAW: /* Raw Physical Disk Access */ return sim_os_disk_isavailable_raw (uptr->fileref); break; default: return FALSE; } } t_bool sim_disk_isavailable_a (UNIT *uptr, DISK_PCALLBACK callback) { t_bool r = FALSE; AIO_CALLSETUP r = sim_disk_isavailable (uptr); AIO_CALL(DOP_IAVL, 0, NULL, NULL, 0, callback); return r; } /* Test for write protect */ t_bool sim_disk_wrp (UNIT *uptr) { return (uptr->flags & DKUF_WRP)? TRUE: FALSE; } /* Get Disk size */ t_offset sim_disk_size (UNIT *uptr) { t_offset physical_size, filesystem_size; t_bool saved_quiet = sim_quiet; switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_STD: /* SIMH format */ physical_size = sim_fsize_ex (uptr->fileref); break; case DKUF_F_VHD: /* VHD format */ physical_size = sim_vhd_disk_size (uptr->fileref); break; case DKUF_F_RAW: /* Raw Physical Disk Access */ physical_size = sim_os_disk_size_raw (uptr->fileref); break; default: return (t_offset)-1; } sim_quiet = TRUE; filesystem_size = get_filesystem_size (uptr); sim_quiet = saved_quiet; if ((filesystem_size == (t_offset)-1) || (filesystem_size < physical_size)) return physical_size; return filesystem_size; } /* Enable asynchronous operation */ t_stat sim_disk_set_async (UNIT *uptr, int latency) { #if !defined(SIM_ASYNCH_IO) char *msg = "Disk: can't operate asynchronously\r\n"; sim_printf ("%s", msg); return SCPE_NOFNC; #else struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; pthread_attr_t attr; sim_debug (ctx->dbit, ctx->dptr, "sim_disk_set_async(unit=%d)\n", (int)(uptr-ctx->dptr->units)); ctx->asynch_io = sim_asynch_enabled; ctx->asynch_io_latency = latency; if (ctx->asynch_io) { pthread_mutex_init (&ctx->io_lock, NULL); pthread_cond_init (&ctx->io_cond, NULL); pthread_cond_init (&ctx->io_done, NULL); pthread_cond_init (&ctx->startup_cond, NULL); pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); pthread_mutex_lock (&ctx->io_lock); pthread_create (&ctx->io_thread, &attr, _disk_io, (void *)uptr); pthread_attr_destroy(&attr); pthread_cond_wait (&ctx->startup_cond, &ctx->io_lock); /* Wait for thread to stabilize */ pthread_mutex_unlock (&ctx->io_lock); pthread_cond_destroy (&ctx->startup_cond); } uptr->a_check_completion = _disk_completion_dispatch; uptr->a_is_active = _disk_is_active; uptr->cancel = _disk_cancel; return SCPE_OK; #endif } /* Disable asynchronous operation */ t_stat sim_disk_clr_async (UNIT *uptr) { #if !defined(SIM_ASYNCH_IO) return SCPE_NOFNC; #else struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; /* make sure device exists */ if (!ctx) return SCPE_UNATT; sim_debug (ctx->dbit, ctx->dptr, "sim_disk_clr_async(unit=%d)\n", (int)(uptr-ctx->dptr->units)); if (ctx->asynch_io) { pthread_mutex_lock (&ctx->io_lock); ctx->asynch_io = 0; pthread_cond_signal (&ctx->io_cond); pthread_mutex_unlock (&ctx->io_lock); pthread_join (ctx->io_thread, NULL); pthread_mutex_destroy (&ctx->io_lock); pthread_cond_destroy (&ctx->io_cond); pthread_cond_destroy (&ctx->io_done); } return SCPE_OK; #endif } /* Read Sectors */ static t_stat _sim_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects) { t_offset da; uint32 err, tbc; size_t i; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; sim_debug (ctx->dbit, ctx->dptr, "_sim_disk_rdsect(unit=%d, lba=0x%X, sects=%d)\n", (int)(uptr-ctx->dptr->units), lba, sects); da = ((t_offset)lba) * ctx->sector_size; tbc = sects * ctx->sector_size; if (sectsread) *sectsread = 0; err = sim_fseeko (uptr->fileref, da, SEEK_SET); /* set pos */ if (!err) { i = sim_fread (buf, ctx->xfer_element_size, tbc/ctx->xfer_element_size, uptr->fileref); if (i < tbc/ctx->xfer_element_size) /* fill */ memset (&buf[i*ctx->xfer_element_size], 0, tbc-(i*ctx->xfer_element_size)); err = ferror (uptr->fileref); if ((!err) && (sectsread)) *sectsread = (t_seccnt)((i*ctx->xfer_element_size+ctx->sector_size-1)/ctx->sector_size); } return err; } t_stat sim_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects) { t_stat r; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; t_seccnt sread = 0; sim_debug (ctx->dbit, ctx->dptr, "sim_disk_rdsect(unit=%d, lba=0x%X, sects=%d)\n", (int)(uptr-ctx->dptr->units), lba, sects); if ((sects == 1) && /* Single sector reads */ (lba >= (uptr->capac*ctx->capac_factor)/(ctx->sector_size/((ctx->dptr->flags & DEV_SECTORS) ? 512 : 1)))) {/* beyond the end of the disk */ memset (buf, '\0', ctx->sector_size); /* are bad block management efforts - zero buffer */ if (sectsread) *sectsread = 1; return SCPE_OK; /* return success */ } if ((0 == (ctx->sector_size & (ctx->storage_sector_size - 1))) || /* Sector Aligned & whole sector transfers */ ((0 == ((lba*ctx->sector_size) & (ctx->storage_sector_size - 1))) && (0 == ((sects*ctx->sector_size) & (ctx->storage_sector_size - 1))))) { switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_STD: /* SIMH format */ return _sim_disk_rdsect (uptr, lba, buf, sectsread, sects); case DKUF_F_VHD: /* VHD format */ r = sim_vhd_disk_rdsect (uptr, lba, buf, &sread, sects); break; case DKUF_F_RAW: /* Raw Physical Disk Access */ r = sim_os_disk_rdsect (uptr, lba, buf, &sread, sects); break; default: return SCPE_NOFNC; } if (sectsread) *sectsread = sread; if (r != SCPE_OK) return r; sim_buf_swap_data (buf, ctx->xfer_element_size, (sread * ctx->sector_size) / ctx->xfer_element_size); return r; } else { /* Unaligned and/or partial sector transfers */ uint8 *tbuf = (uint8*) malloc (sects*ctx->sector_size + 2*ctx->storage_sector_size); t_lba sspsts = ctx->storage_sector_size/ctx->sector_size; /* sim sectors in a storage sector */ t_lba tlba = lba & ~(sspsts - 1); t_seccnt tsects = sects + (lba - tlba); tsects = (tsects + (sspsts - 1)) & ~(sspsts - 1); if (sectsread) *sectsread = 0; if (tbuf == NULL) return SCPE_MEM; switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_STD: /* SIMH format */ r = _sim_disk_rdsect (uptr, tlba, tbuf, &sread, tsects); break; case DKUF_F_VHD: /* VHD format */ r = sim_vhd_disk_rdsect (uptr, tlba, tbuf, &sread, tsects); if (r == SCPE_OK) sim_buf_swap_data (tbuf, ctx->xfer_element_size, (sread * ctx->sector_size) / ctx->xfer_element_size); break; case DKUF_F_RAW: /* Raw Physical Disk Access */ r = sim_os_disk_rdsect (uptr, tlba, tbuf, &sread, tsects); if (r == SCPE_OK) sim_buf_swap_data (tbuf, ctx->xfer_element_size, (sread * ctx->sector_size) / ctx->xfer_element_size); break; default: free (tbuf); return SCPE_NOFNC; } if (r == SCPE_OK) { memcpy (buf, tbuf + ((lba - tlba) * ctx->sector_size), sects * ctx->sector_size); if (sectsread) { *sectsread = sread - (lba - tlba); if (*sectsread > sects) *sectsread = sects; } } free (tbuf); return r; } } t_stat sim_disk_rdsect_a (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects, DISK_PCALLBACK callback) { t_stat r = SCPE_OK; AIO_CALLSETUP r = sim_disk_rdsect (uptr, lba, buf, sectsread, sects); AIO_CALL(DOP_RSEC, lba, buf, sectsread, sects, callback); return r; } /* Write Sectors */ static t_stat _sim_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects) { t_offset da; uint32 err, tbc; size_t i; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; sim_debug (ctx->dbit, ctx->dptr, "_sim_disk_wrsect(unit=%d, lba=0x%X, sects=%d)\n", (int)(uptr-ctx->dptr->units), lba, sects); da = ((t_offset)lba) * ctx->sector_size; tbc = sects * ctx->sector_size; if (sectswritten) *sectswritten = 0; err = sim_fseeko (uptr->fileref, da, SEEK_SET); /* set pos */ if (!err) { i = sim_fwrite (buf, ctx->xfer_element_size, tbc/ctx->xfer_element_size, uptr->fileref); err = ferror (uptr->fileref); if ((!err) && (sectswritten)) *sectswritten = (t_seccnt)((i*ctx->xfer_element_size+ctx->sector_size-1)/ctx->sector_size); } return err; } t_stat sim_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects) { struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; uint32 f = DK_GET_FMT (uptr); t_stat r; uint8 *tbuf = NULL; sim_debug (ctx->dbit, ctx->dptr, "sim_disk_wrsect(unit=%d, lba=0x%X, sects=%d)\n", (int)(uptr-ctx->dptr->units), lba, sects); if (uptr->dynflags & UNIT_DISK_CHK) { DEVICE *dptr = find_dev_from_unit (uptr); uint32 capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* capacity units (word: 2, byte: 1) */ t_lba total_sectors = (t_lba)((uptr->capac*capac_factor)/(ctx->sector_size/((dptr->flags & DEV_SECTORS) ? 512 : 1))); t_lba sect; for (sect = 0; sect < sects; sect++) { t_lba offset; t_bool sect_error = FALSE; for (offset = 0; offset < ctx->sector_size; offset += sizeof(uint32)) { if (*((uint32 *)&buf[sect*ctx->sector_size + offset]) != (uint32)(lba + sect)) { sect_error = TRUE; break; } } if (sect_error) { uint32 save_dctrl = dptr->dctrl; FILE *save_sim_deb = sim_deb; sim_printf ("\n%s%d: Write Address Verification Error on lbn %d(0x%X) of %d(0x%X).\n", sim_dname (dptr), (int)(uptr-dptr->units), (int)(lba+sect), (int)(lba+sect), (int)total_sectors, (int)total_sectors); dptr->dctrl = 0xFFFFFFFF; sim_deb = save_sim_deb ? save_sim_deb : stdout; sim_disk_data_trace (uptr, buf+sect*ctx->sector_size, lba+sect, ctx->sector_size, "Found", TRUE, 1); dptr->dctrl = save_dctrl; sim_deb = save_sim_deb; } } } if (f == DKUF_F_STD) return _sim_disk_wrsect (uptr, lba, buf, sectswritten, sects); if ((0 == (ctx->sector_size & (ctx->storage_sector_size - 1))) || /* Sector Aligned & whole sector transfers */ ((0 == ((lba*ctx->sector_size) & (ctx->storage_sector_size - 1))) && (0 == ((sects*ctx->sector_size) & (ctx->storage_sector_size - 1))))) { if (sim_end || (ctx->xfer_element_size == sizeof (char))) switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_VHD: /* VHD format */ return sim_vhd_disk_wrsect (uptr, lba, buf, sectswritten, sects); case DKUF_F_RAW: /* Raw Physical Disk Access */ return sim_os_disk_wrsect (uptr, lba, buf, sectswritten, sects); default: return SCPE_NOFNC; } tbuf = (uint8*) malloc (sects * ctx->sector_size); if (NULL == tbuf) return SCPE_MEM; sim_buf_copy_swapped (tbuf, buf, ctx->xfer_element_size, (sects * ctx->sector_size) / ctx->xfer_element_size); switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_VHD: /* VHD format */ r = sim_vhd_disk_wrsect (uptr, lba, tbuf, sectswritten, sects); break; case DKUF_F_RAW: /* Raw Physical Disk Access */ r = sim_os_disk_wrsect (uptr, lba, tbuf, sectswritten, sects); break; default: r = SCPE_NOFNC; break; } } else { /* Unaligned and/or partial sector transfers */ t_lba sspsts = ctx->storage_sector_size/ctx->sector_size; /* sim sectors in a storage sector */ t_lba tlba = lba & ~(sspsts - 1); t_seccnt tsects = sects + (lba - tlba); tbuf = (uint8*) malloc (sects*ctx->sector_size + 2*ctx->storage_sector_size); tsects = (tsects + (sspsts - 1)) & ~(sspsts - 1); if (sectswritten) *sectswritten = 0; if (tbuf == NULL) return SCPE_MEM; /* Partial Sector writes require a read-modify-write sequence for the partial sectors */ if ((lba & (sspsts - 1)) || (sects < sspsts)) switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_VHD: /* VHD format */ sim_vhd_disk_rdsect (uptr, tlba, tbuf, NULL, sspsts); break; case DKUF_F_RAW: /* Raw Physical Disk Access */ sim_os_disk_rdsect (uptr, tlba, tbuf, NULL, sspsts); break; default: r = SCPE_NOFNC; break; } if ((tsects > sspsts) && ((sects + lba - tlba) & (sspsts - 1))) switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_VHD: /* VHD format */ sim_vhd_disk_rdsect (uptr, tlba + tsects - sspsts, tbuf + (tsects - sspsts) * ctx->sector_size, NULL, sspsts); break; case DKUF_F_RAW: /* Raw Physical Disk Access */ sim_os_disk_rdsect (uptr, tlba + tsects - sspsts, tbuf + (tsects - sspsts) * ctx->sector_size, NULL, sspsts); break; default: r = SCPE_NOFNC; break; } sim_buf_copy_swapped (tbuf + (lba & (sspsts - 1)) * ctx->sector_size, buf, ctx->xfer_element_size, (sects * ctx->sector_size) / ctx->xfer_element_size); switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_VHD: /* VHD format */ r = sim_vhd_disk_wrsect (uptr, tlba, tbuf, sectswritten, tsects); break; case DKUF_F_RAW: /* Raw Physical Disk Access */ r = sim_os_disk_wrsect (uptr, tlba, tbuf, sectswritten, tsects); break; default: r = SCPE_NOFNC; break; } if ((r == SCPE_OK) && sectswritten) { *sectswritten -= (lba - tlba); if (*sectswritten > sects) *sectswritten = sects; } } free (tbuf); return r; } t_stat sim_disk_wrsect_a (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects, DISK_PCALLBACK callback) { t_stat r = SCPE_OK; AIO_CALLSETUP r = sim_disk_wrsect (uptr, lba, buf, sectswritten, sects); AIO_CALL(DOP_WSEC, lba, buf, sectswritten, sects, callback); return r; } t_stat sim_disk_unload (UNIT *uptr) { switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_STD: /* Simh */ case DKUF_F_VHD: /* VHD format */ return sim_disk_detach (uptr); case DKUF_F_RAW: /* Raw Physical Disk Access */ return sim_os_disk_unload_raw (uptr->fileref); /* remove/eject disk */ break; default: return SCPE_NOFNC; } } /* This routine is called when the simulator stops and any time the asynch mode is changed (enabled or disabled) */ static void _sim_disk_io_flush (UNIT *uptr) { uint32 f = DK_GET_FMT (uptr); #if defined (SIM_ASYNCH_IO) struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; sim_disk_clr_async (uptr); if (sim_asynch_enabled) sim_disk_set_async (uptr, ctx->asynch_io_latency); #endif switch (f) { /* case on format */ case DKUF_F_STD: /* Simh */ fflush (uptr->fileref); break; case DKUF_F_VHD: /* Virtual Disk */ sim_vhd_disk_flush (uptr->fileref); break; case DKUF_F_RAW: /* Physical */ sim_os_disk_flush_raw (uptr->fileref); break; } } static t_stat _err_return (UNIT *uptr, t_stat stat) { free (uptr->filename); uptr->filename = NULL; free (uptr->disk_ctx); uptr->disk_ctx = NULL; return stat; } #pragma pack(push,1) typedef struct _ODS1_HomeBlock { uint16 hm1_w_ibmapsize; uint32 hm1_l_ibmaplbn; uint16 hm1_w_maxfiles; uint16 hm1_w_cluster; uint16 hm1_w_devtype; uint16 hm1_w_structlev; #define HM1_C_LEVEL1 0401 #define HM1_C_LEVEL2 0402 uint8 hm1_t_volname[12]; uint8 hm1_b_fill_1[4]; uint16 hm1_w_volowner; uint16 hm1_w_protect; uint16 hm1_w_volchar; uint16 hm1_w_fileprot; uint8 hm1_b_fill_2[6]; uint8 hm1_b_window; uint8 hm1_b_extend; uint8 hm1_b_lru_lim; uint8 hm1_b_fill_3[11]; uint16 hm1_w_checksum1; uint8 hm1_t_credate[14]; uint8 hm1_b_fill_4[382]; uint32 hm1_l_serialnum; uint8 hm1_b_fill_5[12]; uint8 hm1_t_volname2[12]; uint8 hm1_t_ownername[12]; uint8 hm1_t_format[12]; uint8 hm1_t_fill_6[2]; uint16 hm1_w_checksum2; } ODS1_HomeBlock; typedef struct _ODS2_HomeBlock { uint32 hm2_l_homelbn; uint32 hm2_l_alhomelbn; uint32 hm2_l_altidxlbn; uint8 hm2_b_strucver; uint8 hm2_b_struclev; uint16 hm2_w_cluster; uint16 hm2_w_homevbn; uint16 hm2_w_alhomevbn; uint16 hm2_w_altidxvbn; uint16 hm2_w_ibmapvbn; uint32 hm2_l_ibmaplbn; uint32 hm2_l_maxfiles; uint16 hm2_w_ibmapsize; uint16 hm2_w_resfiles; uint16 hm2_w_devtype; uint16 hm2_w_rvn; uint16 hm2_w_setcount; uint16 hm2_w_volchar; uint32 hm2_l_volowner; uint32 hm2_l_reserved; uint16 hm2_w_protect; uint16 hm2_w_fileprot; uint16 hm2_w_reserved; uint16 hm2_w_checksum1; uint32 hm2_q_credate[2]; uint8 hm2_b_window; uint8 hm2_b_lru_lim; uint16 hm2_w_extend; uint32 hm2_q_retainmin[2]; uint32 hm2_q_retainmax[2]; uint32 hm2_q_revdate[2]; uint8 hm2_r_min_class[20]; uint8 hm2_r_max_class[20]; uint8 hm2_r_reserved[320]; uint32 hm2_l_serialnum; uint8 hm2_t_strucname[12]; uint8 hm2_t_volname[12]; uint8 hm2_t_ownername[12]; uint8 hm2_t_format[12]; uint16 hm2_w_reserved2; uint16 hm2_w_checksum2; } ODS2_HomeBlock; typedef struct _ODS1_FileHeader { uint8 fh1_b_idoffset; uint8 fh1_b_mpoffset; uint16 fh1_w_fid_num; uint16 fh1_w_fid_seq; uint16 fh1_w_struclev; uint16 fh1_w_fileowner; uint16 fh1_w_fileprot; uint16 fh1_w_filechar; uint16 fh1_w_recattr; uint8 fh1_b_fill_1[494]; uint16 fh1_w_checksum; } ODS1_FileHeader; typedef struct _ODS2_FileHeader { uint8 fh2_b_idoffset; uint8 fh2_b_mpoffset; uint8 fh2_b_acoffset; uint8 fh2_b_rsoffset; uint16 fh2_w_seg_num; uint16 fh2_w_structlev; uint16 fh2_w_fid[3]; uint16 fh2_w_ext_fid[3]; uint16 fh2_w_recattr[16]; uint32 fh2_l_filechar; uint16 fh2_w_remaining[228]; } ODS2_FileHeader; typedef union _ODS2_Retreval { struct { unsigned fm2___fill : 14; /* type specific data */ unsigned fm2_v_format : 2; /* format type code */ } fm2_r_word0_bits; struct { unsigned fm2_v_exact : 1; /* exact placement specified */ unsigned fm2_v_oncyl : 1; /* on cylinder allocation desired */ unsigned fm2___fill : 10; unsigned fm2_v_lbn : 1; /* use LBN of next map pointer */ unsigned fm2_v_rvn : 1; /* place on specified RVN */ unsigned fm2_v_format0 : 2; } fm2_r_map_bits0; struct { unsigned fm2_b_count1 : 8; /* low byte described below */ unsigned fm2_v_highlbn1 : 6; /* high order LBN */ unsigned fm2_v_format1 : 2; unsigned fm2_w_lowlbn1 : 16; /* low order LBN */ } fm2_r_map_bits1; struct { struct { unsigned fm2_v_count2 : 14; /* count field */ unsigned fm2_v_format2 : 2; unsigned fm2_l_lowlbn2 : 16; /* low order LBN */ } fm2_r_map2_long0; uint16 fm2_l_highlbn2; /* high order LBN */ } fm2_r_map_bits2; struct { struct { unsigned fm2_v_highcount3 : 14; /* low order count field */ unsigned fm2_v_format3 : 2; unsigned fm2_w_lowcount3 : 16; /* high order count field */ } fm2_r_map3_long0; uint32 fm2_l_lbn3; } fm2_r_map_bits3; } ODS2_Retreval; typedef struct _ODS1_Retreval { uint8 fm1_b_ex_segnum; uint8 fm1_b_ex_rvn; uint16 fm1_w_ex_filnum; uint16 fm1_w_ex_filseq; uint8 fm1_b_countsize; uint8 fm1_b_lbnsize; uint8 fm1_b_inuse; uint8 fm1_b_avail; union { struct { uint8 fm1_b_highlbn; uint8 fm1_b_count; uint16 fm1_w_lowlbn; } fm1_s_fm1def1; struct { uint8 fm1_b_highlbn; uint8 fm1_b_count; uint16 fm1_w_lowlbn; } fm1_s_fm1def2; } fm1_pointers[4]; } ODS1_Retreval; typedef struct _ODS1_StorageControlBlock { uint8 scb_b_unused[3]; uint8 scb_b_bitmapblks; struct _bitmapblk { uint16 scb_w_freeblks; uint16 scb_w_freeptr; } scb_r_blocks[1]; } ODS1_SCB; typedef struct _ODS2_StorageControlBlock { uint8 scb_b_strucver; /* 1 */ uint8 scb_b_struclev; /* 2 */ uint16 scb_w_cluster; uint32 scb_l_volsize; uint32 scb_l_blksize; uint32 scb_l_sectors; uint32 scb_l_tracks; uint32 scb_l_cylinder; uint32 scb_l_status; uint32 scb_l_status2; uint16 scb_w_writecnt; uint8 scb_t_volockname[12]; uint32 scb_q_mounttime[2]; uint16 scb_w_backrev; uint32 scb_q_genernum[2]; uint8 scb_b_reserved[446]; uint16 scb_w_checksum; } ODS2_SCB; #pragma pack(pop) static uint16 ODSChecksum (void *Buffer, uint16 WordCount) { int i; uint16 Sum = 0; uint16 CheckSum = 0; uint16 *Buf = (uint16 *)Buffer; for (i=0; i<WordCount; i++) CheckSum += Buf[i]; return CheckSum; } static t_offset get_ods2_filesystem_size (UNIT *uptr) { DEVICE *dptr; t_addr saved_capac; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; t_offset temp_capac = 512 * (t_offset)0xFFFFFFFFu; /* Make sure we can access the largest sector */ uint32 capac_factor; ODS2_HomeBlock Home; ODS2_FileHeader Header; ODS2_Retreval *Retr; ODS2_SCB Scb; uint16 CheckSum1, CheckSum2; uint32 ScbLbn = 0; t_offset ret_val = (t_offset)-1; if ((dptr = find_dev_from_unit (uptr)) == NULL) return ret_val; capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* save capacity units (word: 2, byte: 1) */ saved_capac = uptr->capac; uptr->capac = (t_addr)(temp_capac/(capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))); if (sim_disk_rdsect (uptr, 512 / ctx->sector_size, (uint8 *)&Home, NULL, sizeof (Home) / ctx->sector_size)) goto Return_Cleanup; CheckSum1 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm2_w_checksum1)-((char *)&Home.hm2_l_homelbn))/2)); CheckSum2 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm2_w_checksum2)-((char *)&Home.hm2_l_homelbn))/2)); if ((Home.hm2_l_homelbn == 0) || (Home.hm2_l_alhomelbn == 0) || (Home.hm2_l_altidxlbn == 0) || ((Home.hm2_b_struclev != 2) && (Home.hm2_b_struclev != 5)) || (Home.hm2_b_strucver == 0) || (Home.hm2_w_cluster == 0) || (Home.hm2_w_homevbn == 0) || (Home.hm2_w_alhomevbn == 0) || (Home.hm2_w_ibmapvbn == 0) || (Home.hm2_l_ibmaplbn == 0) || (Home.hm2_w_resfiles >= Home.hm2_l_maxfiles) || (Home.hm2_w_ibmapsize == 0) || (Home.hm2_w_resfiles < 5) || (Home.hm2_w_checksum1 != CheckSum1) || (Home.hm2_w_checksum2 != CheckSum2)) goto Return_Cleanup; if (sim_disk_rdsect (uptr, (Home.hm2_l_ibmaplbn+Home.hm2_w_ibmapsize+1) * (512 / ctx->sector_size), (uint8 *)&Header, NULL, sizeof (Header) / ctx->sector_size)) goto Return_Cleanup; CheckSum1 = ODSChecksum (&Header, 255); if (CheckSum1 != *(((uint16 *)&Header)+255)) /* Verify Checksum on BITMAP.SYS file header */ goto Return_Cleanup; Retr = (ODS2_Retreval *)(((uint16*)(&Header))+Header.fh2_b_mpoffset); /* The BitMap File has a single extent, which may be preceeded by a placement descriptor */ if (Retr->fm2_r_word0_bits.fm2_v_format == 0) Retr = (ODS2_Retreval *)(((uint16 *)Retr)+1); /* skip placement descriptor */ switch (Retr->fm2_r_word0_bits.fm2_v_format) { case 1: ScbLbn = (Retr->fm2_r_map_bits1.fm2_v_highlbn1<<16)+Retr->fm2_r_map_bits1.fm2_w_lowlbn1; break; case 2: ScbLbn = (Retr->fm2_r_map_bits2.fm2_l_highlbn2<<16)+Retr->fm2_r_map_bits2.fm2_r_map2_long0.fm2_l_lowlbn2; break; case 3: ScbLbn = Retr->fm2_r_map_bits3.fm2_l_lbn3; break; } Retr = (ODS2_Retreval *)(((uint16 *)Retr)+Retr->fm2_r_word0_bits.fm2_v_format+1); if (sim_disk_rdsect (uptr, ScbLbn * (512 / ctx->sector_size), (uint8 *)&Scb, NULL, sizeof (Scb) / ctx->sector_size)) goto Return_Cleanup; CheckSum1 = ODSChecksum (&Scb, 255); if (CheckSum1 != *(((uint16 *)&Scb)+255)) /* Verify Checksum on Storage Control Block */ goto Return_Cleanup; if ((Scb.scb_w_cluster != Home.hm2_w_cluster) || (Scb.scb_b_strucver != Home.hm2_b_strucver) || (Scb.scb_b_struclev != Home.hm2_b_struclev)) goto Return_Cleanup; if (!sim_quiet) { sim_printf ("%s%d: '%s' Contains ODS%d File system\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename, Home.hm2_b_struclev); sim_printf ("%s%d: Volume Name: %12.12s ", sim_dname (dptr), (int)(uptr-dptr->units), Home.hm2_t_volname); sim_printf ("Format: %12.12s ", Home.hm2_t_format); sim_printf ("Sectors In Volume: %u\n", Scb.scb_l_volsize); } ret_val = ((t_offset)Scb.scb_l_volsize) * 512; Return_Cleanup: uptr->capac = saved_capac; return ret_val; } static t_offset get_ods1_filesystem_size (UNIT *uptr) { DEVICE *dptr; t_addr saved_capac; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; t_offset temp_capac = 512 * (t_offset)0xFFFFFFFFu; /* Make sure we can access the largest sector */ uint32 capac_factor; ODS1_HomeBlock Home; ODS1_FileHeader Header; ODS1_Retreval *Retr; uint8 scb_buf[512]; ODS1_SCB *Scb = (ODS1_SCB *)scb_buf; uint16 CheckSum1, CheckSum2; uint32 ScbLbn; t_offset ret_val = (t_offset)-1; if ((dptr = find_dev_from_unit (uptr)) == NULL) return ret_val; capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* save capacity units (word: 2, byte: 1) */ saved_capac = uptr->capac; uptr->capac = (t_addr)(temp_capac/(capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))); if (sim_disk_rdsect (uptr, 512 / ctx->sector_size, (uint8 *)&Home, NULL, sizeof (Home) / ctx->sector_size)) goto Return_Cleanup; CheckSum1 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm1_w_checksum1)-((char *)&Home.hm1_w_ibmapsize))/2)); CheckSum2 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm1_w_checksum2)-((char *)&Home.hm1_w_ibmapsize))/2)); if ((Home.hm1_w_ibmapsize == 0) || (Home.hm1_l_ibmaplbn == 0) || (Home.hm1_w_maxfiles == 0) || (Home.hm1_w_cluster != 1) || ((Home.hm1_w_structlev != HM1_C_LEVEL1) && (Home.hm1_w_structlev != HM1_C_LEVEL2)) || (Home.hm1_l_ibmaplbn == 0) || (Home.hm1_w_checksum1 != CheckSum1) || (Home.hm1_w_checksum2 != CheckSum2)) goto Return_Cleanup; if (sim_disk_rdsect (uptr, (((Home.hm1_l_ibmaplbn << 16) + ((Home.hm1_l_ibmaplbn >> 16) & 0xFFFF)) + Home.hm1_w_ibmapsize + 1) * (512 / ctx->sector_size), (uint8 *)&Header, NULL, sizeof (Header) / ctx->sector_size)) goto Return_Cleanup; CheckSum1 = ODSChecksum (&Header, 255); if (CheckSum1 != *(((uint16 *)&Header)+255)) /* Verify Checksum on BITMAP.SYS file header */ goto Return_Cleanup; Retr = (ODS1_Retreval *)(((uint16*)(&Header))+Header.fh1_b_mpoffset); ScbLbn = (Retr->fm1_pointers[0].fm1_s_fm1def1.fm1_b_highlbn<<16)+Retr->fm1_pointers[0].fm1_s_fm1def1.fm1_w_lowlbn; if (sim_disk_rdsect (uptr, ScbLbn * (512 / ctx->sector_size), (uint8 *)Scb, NULL, 512 / ctx->sector_size)) goto Return_Cleanup; if (Scb->scb_b_bitmapblks < 127) ret_val = (((t_offset)Scb->scb_r_blocks[Scb->scb_b_bitmapblks].scb_w_freeblks << 16) + Scb->scb_r_blocks[Scb->scb_b_bitmapblks].scb_w_freeptr) * 512; else ret_val = (((t_offset)Scb->scb_r_blocks[0].scb_w_freeblks << 16) + Scb->scb_r_blocks[0].scb_w_freeptr) * 512; if (!sim_quiet) { sim_printf ("%s%d: '%s' Contains an ODS1 File system\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename); sim_printf ("%s%d: Volume Name: %12.12s ", sim_dname (dptr), (int)(uptr-dptr->units), Home.hm1_t_volname); sim_printf ("Format: %12.12s ", Home.hm1_t_format); sim_printf ("Sectors In Volume: %u\n", (uint32)(ret_val / 512)); } Return_Cleanup: uptr->capac = saved_capac; return ret_val; } typedef struct ultrix_disklabel { uint32 pt_magic; /* magic no. indicating part. info exits */ uint32 pt_valid; /* set by driver if pt is current */ struct pt_info { uint32 pi_nblocks; /* no. of sectors */ uint32 pi_blkoff; /* block offset for start */ } pt_part[8]; } ultrix_disklabel; #define PT_MAGIC 0x032957 /* Partition magic number */ #define PT_VALID 1 /* Indicates if struct is valid */ static t_offset get_ultrix_filesystem_size (UNIT *uptr) { DEVICE *dptr; t_addr saved_capac; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; t_offset temp_capac = 512 * (t_offset)0xFFFFFFFFu; /* Make sure we can access the largest sector */ uint32 capac_factor; uint8 sector_buf[512]; ultrix_disklabel *Label = (ultrix_disklabel *)(sector_buf + sizeof (sector_buf) - sizeof (ultrix_disklabel)); t_offset ret_val = (t_offset)-1; int i; uint32 max_lbn = 0, max_lbn_partnum = 0; if ((dptr = find_dev_from_unit (uptr)) == NULL) return ret_val; capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* save capacity units (word: 2, byte: 1) */ saved_capac = uptr->capac; uptr->capac = (t_addr)(temp_capac/(capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))); if (sim_disk_rdsect (uptr, 31 * (512 / ctx->sector_size), sector_buf, NULL, 512 / ctx->sector_size)) goto Return_Cleanup; if ((Label->pt_magic != PT_MAGIC) || (Label->pt_valid != PT_VALID)) goto Return_Cleanup; for (i = 0; i < 8; i++) { uint32 end_lbn = Label->pt_part[i].pi_blkoff + Label->pt_part[i].pi_nblocks; if (end_lbn > max_lbn) { max_lbn = end_lbn; max_lbn_partnum = i; } } if (!sim_quiet) { sim_printf ("%s%d: '%s' Contains Ultrix partitions\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename); sim_printf ("Partition with highest sector: %c, Sectors On Disk: %u\n", 'a' + max_lbn_partnum, max_lbn); } ret_val = ((t_offset)max_lbn) * 512; Return_Cleanup: uptr->capac = saved_capac; return ret_val; } typedef t_offset (*FILESYSTEM_CHECK)(UNIT *uptr); static t_offset get_filesystem_size (UNIT *uptr) { static FILESYSTEM_CHECK checks[] = { &get_ods2_filesystem_size, &get_ods1_filesystem_size, &get_ultrix_filesystem_size, NULL }; t_offset ret_val; int i; for (i = 0; checks[i] != NULL; i++) { ret_val = checks[i] (uptr); if (ret_val != (t_offset)-1) break; } return ret_val; } t_stat sim_disk_attach (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize, uint32 dbit, const char *dtype, uint32 pdp11tracksize, int completion_delay) { struct disk_context *ctx; DEVICE *dptr; char tbuf[4*CBUFSIZE]; FILE *(*open_function)(const char *filename, const char *mode) = sim_fopen; FILE *(*create_function)(const char *filename, t_offset desiredsize) = NULL; t_offset (*size_function)(FILE *file); t_stat (*storage_function)(FILE *file, uint32 *sector_size, uint32 *removable) = NULL; t_bool created = FALSE, copied = FALSE; t_bool auto_format = FALSE; t_offset capac, filesystem_capac; if (uptr->flags & UNIT_DIS) /* disabled? */ return SCPE_UDIS; if (!(uptr->flags & UNIT_ATTABLE)) /* not attachable? */ return SCPE_NOATT; if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_NOATT; if (sim_switches & SWMASK ('F')) { /* format spec? */ char gbuf[CBUFSIZE]; cptr = get_glyph (cptr, gbuf, 0); /* get spec */ if (*cptr == 0) /* must be more */ return SCPE_2FARG; if (sim_disk_set_fmt (uptr, 0, gbuf, NULL) != SCPE_OK) return sim_messagef (SCPE_ARG, "Invalid Disk Format: %s\n", gbuf); sim_switches = sim_switches & ~(SWMASK ('F')); /* Record Format specifier already processed */ auto_format = TRUE; } if (sim_switches & SWMASK ('D')) { /* create difference disk? */ char gbuf[CBUFSIZE]; FILE *vhd; sim_switches = sim_switches & ~(SWMASK ('D')); cptr = get_glyph_nc (cptr, gbuf, 0); /* get spec */ if (*cptr == 0) /* must be more */ return SCPE_2FARG; vhd = sim_vhd_disk_create_diff (gbuf, cptr); if (vhd) { sim_vhd_disk_close (vhd); return sim_disk_attach (uptr, gbuf, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay); } return sim_messagef (SCPE_ARG, "Unable to create differencing VHD: %s\n", gbuf); } if (sim_switches & SWMASK ('C')) { /* create vhd disk & copy contents? */ char gbuf[CBUFSIZE]; FILE *vhd; int saved_sim_switches = sim_switches; int32 saved_sim_quiet = sim_quiet; uint32 capac_factor; t_stat r; sim_switches = sim_switches & ~(SWMASK ('C')); cptr = get_glyph_nc (cptr, gbuf, 0); /* get spec */ if (*cptr == 0) /* must be more */ return SCPE_2FARG; sim_switches |= SWMASK ('R') | SWMASK ('E'); sim_quiet = TRUE; /* First open the source of the copy operation */ r = sim_disk_attach (uptr, cptr, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay); sim_quiet = saved_sim_quiet; if (r != SCPE_OK) { sim_switches = saved_sim_switches; return sim_messagef (r, "Can't open source VHD: %s\n", cptr); } if (!sim_quiet) { sim_printf ("%s%d: creating new virtual disk '%s'\n", sim_dname (dptr), (int)(uptr-dptr->units), gbuf); } capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* capacity units (word: 2, byte: 1) */ vhd = sim_vhd_disk_create (gbuf, ((t_offset)uptr->capac)*capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1)); if (!vhd) { return sim_messagef (r, "%s%d: can't create virtual disk '%s'\n", sim_dname (dptr), (int)(uptr-dptr->units), gbuf); } else { uint8 *copy_buf = (uint8*) malloc (1024*1024); t_lba lba; t_seccnt sectors_per_buffer = (t_seccnt)((1024*1024)/sector_size); t_lba total_sectors = (t_lba)((uptr->capac*capac_factor)/(sector_size/((dptr->flags & DEV_SECTORS) ? 512 : 1))); t_seccnt sects = sectors_per_buffer; if (!copy_buf) { sim_vhd_disk_close(vhd); (void)remove (gbuf); return SCPE_MEM; } for (lba = 0; (lba < total_sectors) && (r == SCPE_OK); lba += sects) { if (!sim_quiet) sim_printf ("%s%d: Copied %dMB. %d%% complete.\r", sim_dname (dptr), (int)(uptr-dptr->units), (int)((((float)lba)*sector_size)/1000000), (int)((((float)lba)*100)/total_sectors)); sects = sectors_per_buffer; if (lba + sects > total_sectors) sects = total_sectors - lba; r = sim_disk_rdsect (uptr, lba, copy_buf, NULL, sects); if (r == SCPE_OK) { uint32 saved_unit_flags = uptr->flags; FILE *save_unit_fileref = uptr->fileref; sim_disk_set_fmt (uptr, 0, "VHD", NULL); uptr->fileref = vhd; r = sim_disk_wrsect (uptr, lba, copy_buf, NULL, sects); uptr->fileref = save_unit_fileref; uptr->flags = saved_unit_flags; } } if (!sim_quiet) { if (r == SCPE_OK) sim_printf ("\n%s%d: Copied %dMB. Done.\n", sim_dname (dptr), (int)(uptr-dptr->units), (int)(((t_offset)lba*sector_size)/1000000)); else sim_printf ("\n%s%d: Error copying: %s.\n", sim_dname (dptr), (int)(uptr-dptr->units), sim_error_text (r)); } if ((r == SCPE_OK) && (sim_switches & SWMASK ('V'))) { uint8 *verify_buf = (uint8*) malloc (1024*1024); if (!verify_buf) { sim_vhd_disk_close(vhd); (void)remove (gbuf); free (copy_buf); return SCPE_MEM; } for (lba = 0; (lba < total_sectors) && (r == SCPE_OK); lba += sects) { if (!sim_quiet) sim_printf ("%s%d: Verified %dMB. %d%% complete.\r", sim_dname (dptr), (int)(uptr-dptr->units), (int)((((float)lba)*sector_size)/1000000), (int)((((float)lba)*100)/total_sectors)); sects = sectors_per_buffer; if (lba + sects > total_sectors) sects = total_sectors - lba; r = sim_disk_rdsect (uptr, lba, copy_buf, NULL, sects); if (r == SCPE_OK) { uint32 saved_unit_flags = uptr->flags; FILE *save_unit_fileref = uptr->fileref; sim_disk_set_fmt (uptr, 0, "VHD", NULL); uptr->fileref = vhd; r = sim_disk_rdsect (uptr, lba, verify_buf, NULL, sects); uptr->fileref = save_unit_fileref; uptr->flags = saved_unit_flags; if (r == SCPE_OK) { if (0 != memcmp (copy_buf, verify_buf, 1024*1024)) r = SCPE_IOERR; } } } if (!sim_quiet) { if (r == SCPE_OK) sim_printf ("\n%s%d: Verified %dMB. Done.\n", sim_dname (dptr), (int)(uptr-dptr->units), (int)(((t_offset)lba*sector_size)/1000000)); else { t_lba i; uint32 save_dctrl = dptr->dctrl; FILE *save_sim_deb = sim_deb; for (i = 0; i < (1024*1024/sector_size); ++i) if (0 != memcmp (copy_buf+i*sector_size, verify_buf+i*sector_size, sector_size)) break; sim_printf ("\n%s%d: Verification Error on lbn %d.\n", sim_dname (dptr), (int)(uptr-dptr->units), lba+i); dptr->dctrl = 0xFFFFFFFF; sim_deb = stdout; sim_disk_data_trace (uptr, copy_buf+i*sector_size, lba+i, sector_size, "Expected", TRUE, 1); sim_disk_data_trace (uptr, verify_buf+i*sector_size, lba+i, sector_size, "Found", TRUE, 1); dptr->dctrl = save_dctrl; sim_deb = save_sim_deb; } } free (verify_buf); } free (copy_buf); sim_vhd_disk_close (vhd); sim_disk_detach (uptr); if (r == SCPE_OK) { created = TRUE; copied = TRUE; tbuf[sizeof(tbuf)-1] = '\0'; strncpy (tbuf, gbuf, sizeof(tbuf)-1); cptr = tbuf; sim_disk_set_fmt (uptr, 0, "VHD", NULL); sim_switches = saved_sim_switches; } else return r; /* fall through and open/return the newly created & copied vhd */ } } else if (sim_switches & SWMASK ('M')) { /* merge difference disk? */ char gbuf[CBUFSIZE], *Parent = NULL; FILE *vhd; sim_switches = sim_switches & ~(SWMASK ('M')); get_glyph_nc (cptr, gbuf, 0); /* get spec */ vhd = sim_vhd_disk_merge (gbuf, &Parent); if (vhd) { t_stat r; sim_vhd_disk_close (vhd); r = sim_disk_attach (uptr, Parent, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay); free (Parent); return r; } return SCPE_ARG; } switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_STD: /* SIMH format */ if (NULL == (uptr->fileref = sim_vhd_disk_open (cptr, "rb"))) { if (errno == EBADF) /* VHD but broken */ return SCPE_OPENERR; open_function = sim_fopen; size_function = sim_fsize_ex; break; } sim_disk_set_fmt (uptr, 0, "VHD", NULL); /* set file format to VHD */ sim_vhd_disk_close (uptr->fileref); /* close vhd file*/ auto_format = TRUE; uptr->fileref = NULL; /* Fall through to normal VHD processing */ case DKUF_F_VHD: /* VHD format */ open_function = sim_vhd_disk_open; create_function = sim_vhd_disk_create; size_function = sim_vhd_disk_size; break; case DKUF_F_RAW: /* Raw Physical Disk Access */ open_function = sim_os_disk_open_raw; size_function = sim_os_disk_size_raw; storage_function = sim_os_disk_info_raw; break; default: return SCPE_IERR; } uptr->filename = (char *) calloc (CBUFSIZE, sizeof (char));/* alloc name buf */ uptr->disk_ctx = ctx = (struct disk_context *)calloc(1, sizeof(struct disk_context)); if ((uptr->filename == NULL) || (uptr->disk_ctx == NULL)) return _err_return (uptr, SCPE_MEM); strncpy (uptr->filename, cptr, CBUFSIZE); /* save name */ ctx->sector_size = (uint32)sector_size; /* save sector_size */ ctx->capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* save capacity units (word: 2, byte: 1) */ ctx->xfer_element_size = (uint32)xfer_element_size; /* save xfer_element_size */ ctx->dptr = dptr; /* save DEVICE pointer */ ctx->dbit = dbit; /* save debug bit */ sim_debug (ctx->dbit, ctx->dptr, "sim_disk_attach(unit=%d,filename='%s')\n", (int)(uptr-ctx->dptr->units), uptr->filename); ctx->auto_format = auto_format; /* save that we auto selected format */ ctx->storage_sector_size = (uint32)sector_size; /* Default */ if ((sim_switches & SWMASK ('R')) || /* read only? */ ((uptr->flags & UNIT_RO) != 0)) { if (((uptr->flags & UNIT_ROABLE) == 0) && /* allowed? */ ((uptr->flags & UNIT_RO) == 0)) return _err_return (uptr, SCPE_NORO); /* no, error */ uptr->fileref = open_function (cptr, "rb"); /* open rd only */ if (uptr->fileref == NULL) /* open fail? */ return _err_return (uptr, SCPE_OPENERR); /* yes, error */ uptr->flags = uptr->flags | UNIT_RO; /* set rd only */ if (!sim_quiet) { sim_printf ("%s%d: unit is read only\n", sim_dname (dptr), (int)(uptr-dptr->units)); } } else { /* normal */ uptr->fileref = open_function (cptr, "rb+"); /* open r/w */ if (uptr->fileref == NULL) { /* open fail? */ if ((errno == EROFS) || (errno == EACCES)) { /* read only? */ if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ return _err_return (uptr, SCPE_NORO); /* no error */ uptr->fileref = open_function (cptr, "rb"); /* open rd only */ if (uptr->fileref == NULL) /* open fail? */ return _err_return (uptr, SCPE_OPENERR);/* yes, error */ uptr->flags = uptr->flags | UNIT_RO; /* set rd only */ if (!sim_quiet) sim_printf ("%s%d: unit is read only\n", sim_dname (dptr), (int)(uptr-dptr->units)); } else { /* doesn't exist */ if (sim_switches & SWMASK ('E')) /* must exist? */ return _err_return (uptr, SCPE_OPENERR); /* yes, error */ if (create_function) uptr->fileref = create_function (cptr, ((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1));/* create new file */ else uptr->fileref = open_function (cptr, "wb+");/* open new file */ if (uptr->fileref == NULL) /* open fail? */ return _err_return (uptr, SCPE_OPENERR);/* yes, error */ if (!sim_quiet) sim_printf ("%s%d: creating new file\n", sim_dname (dptr), (int)(uptr-dptr->units)); created = TRUE; } } /* end if null */ } /* end else */ if (DK_GET_FMT (uptr) == DKUF_F_VHD) { if ((created) && dtype) sim_vhd_disk_set_dtype (uptr->fileref, dtype); if (dtype && strcmp (dtype, sim_vhd_disk_get_dtype (uptr->fileref))) { char cmd[32]; sprintf (cmd, "%s%d %s", dptr->name, (int)(uptr-dptr->units), sim_vhd_disk_get_dtype (uptr->fileref)); set_cmd (0, cmd); } } uptr->flags = uptr->flags | UNIT_ATT; uptr->pos = 0; /* Get Device attributes if they are available */ if (storage_function) storage_function (uptr->fileref, &ctx->storage_sector_size, &ctx->removable); if ((created) && (!copied)) { t_stat r = SCPE_OK; uint8 *secbuf = (uint8 *)calloc (128, ctx->sector_size); /* alloc temp sector buf */ /* On a newly created disk, we write a zero sector to the last and the first sectors. This serves 3 purposes: 1) it avoids strange allocation delays writing newly allocated storage at the end of the disk during simulator operation 2) it allocates storage for the whole disk at creation time to avoid strange failures which may happen during simulator execution if the containing disk is full 3) it leaves a Sinh Format disk at the intended size so it may subsequently be autosized with the correct size. */ if (secbuf == NULL) r = SCPE_MEM; if (r == SCPE_OK) { /* Write all blocks */ t_lba lba; t_lba total_lbas = (t_lba)((((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))/ctx->sector_size); for (lba = 0; (r == SCPE_OK) && (lba < total_lbas); lba += 128) { t_seccnt sectors = ((lba + 128) <= total_lbas) ? 128 : total_lbas - lba; r = sim_disk_wrsect (uptr, lba, secbuf, NULL, sectors); } } free (secbuf); if (r != SCPE_OK) { sim_disk_detach (uptr); /* report error now */ (void)remove (cptr); /* remove the created file */ return SCPE_OPENERR; } if (sim_switches & SWMASK ('I')) { /* Initialize To Sector Address */ uint8 *init_buf = (uint8*) malloc (1024*1024); t_lba lba, sect; uint32 capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* capacity units (word: 2, byte: 1) */ t_seccnt sectors_per_buffer = (t_seccnt)((1024*1024)/sector_size); t_lba total_sectors = (t_lba)((uptr->capac*capac_factor)/(sector_size/((dptr->flags & DEV_SECTORS) ? 512 : 1))); t_seccnt sects = sectors_per_buffer; if (!init_buf) { sim_disk_detach (uptr); /* report error now */ (void)remove (cptr); return SCPE_MEM; } for (lba = 0; (lba < total_sectors) && (r == SCPE_OK); lba += sects) { sects = sectors_per_buffer; if (lba + sects > total_sectors) sects = total_sectors - lba; for (sect = 0; sect < sects; sect++) { t_lba offset; for (offset = 0; offset < sector_size; offset += sizeof(uint32)) *((uint32 *)&init_buf[sect*sector_size + offset]) = (uint32)(lba + sect); } r = sim_disk_wrsect (uptr, lba, init_buf, NULL, sects); if (r != SCPE_OK) { free (init_buf); sim_disk_detach (uptr); /* report error now */ (void)remove (cptr); /* remove the created file */ return SCPE_OPENERR; } if (!sim_quiet) sim_printf ("%s%d: Initialized To Sector Address %dMB. %d%% complete.\r", sim_dname (dptr), (int)(uptr-dptr->units), (int)((((float)lba)*sector_size)/1000000), (int)((((float)lba)*100)/total_sectors)); } if (!sim_quiet) sim_printf ("%s%d: Initialized To Sector Address %dMB. 100%% complete.\n", sim_dname (dptr), (int)(uptr-dptr->units), (int)((((float)lba)*sector_size)/1000000)); free (init_buf); } if (pdp11tracksize) sim_disk_pdp11_bad_block (uptr, pdp11tracksize, sector_size/sizeof(uint16)); } if (sim_switches & SWMASK ('K')) { t_stat r = SCPE_OK; t_lba lba, sect; uint32 capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* capacity units (word: 2, byte: 1) */ t_seccnt sectors_per_buffer = (t_seccnt)((1024*1024)/sector_size); t_lba total_sectors = (t_lba)((uptr->capac*capac_factor)/(sector_size/((dptr->flags & DEV_SECTORS) ? 512 : 1))); t_seccnt sects = sectors_per_buffer; uint8 *verify_buf = (uint8*) malloc (1024*1024); if (!verify_buf) { sim_disk_detach (uptr); /* report error now */ return SCPE_MEM; } for (lba = 0; (lba < total_sectors) && (r == SCPE_OK); lba += sects) { sects = sectors_per_buffer; if (lba + sects > total_sectors) sects = total_sectors - lba; r = sim_disk_rdsect (uptr, lba, verify_buf, NULL, sects); if (r == SCPE_OK) { for (sect = 0; sect < sects; sect++) { t_lba offset; t_bool sect_error = FALSE; for (offset = 0; offset < sector_size; offset += sizeof(uint32)) { if (*((uint32 *)&verify_buf[sect*sector_size + offset]) != (uint32)(lba + sect)) { sect_error = TRUE; break; } } if (sect_error) { uint32 save_dctrl = dptr->dctrl; FILE *save_sim_deb = sim_deb; sim_printf ("\n%s%d: Verification Error on lbn %d(0x%X) of %d(0x%X).\n", sim_dname (dptr), (int)(uptr-dptr->units), (int)(lba+sect), (int)(lba+sect), (int)total_sectors, (int)total_sectors); dptr->dctrl = 0xFFFFFFFF; sim_deb = stdout; sim_disk_data_trace (uptr, verify_buf+sect*sector_size, lba+sect, sector_size, "Found", TRUE, 1); dptr->dctrl = save_dctrl; sim_deb = save_sim_deb; } } } if (!sim_quiet) sim_printf ("%s%d: Verified containing Sector Address %dMB. %d%% complete.\r", sim_dname (dptr), (int)(uptr-dptr->units), (int)((((float)lba)*sector_size)/1000000), (int)((((float)lba)*100)/total_sectors)); } if (!sim_quiet) sim_printf ("%s%d: Verified containing Sector Address %dMB. 100%% complete.\n", sim_dname (dptr), (int)(uptr-dptr->units), (int)((((float)lba)*sector_size)/1000000)); free (verify_buf); uptr->dynflags |= UNIT_DISK_CHK; } filesystem_capac = get_filesystem_size (uptr); capac = size_function (uptr->fileref); if (capac && (capac != (t_offset)-1)) { if (dontautosize) { t_addr saved_capac = uptr->capac; if ((filesystem_capac != (t_offset)-1) && (filesystem_capac > (((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1)))) { if (!sim_quiet) { uptr->capac = (t_addr)(filesystem_capac/(ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))); sim_printf ("%s%d: The file system on the disk %s is larger than simulated device (%s > ", sim_dname (dptr), (int)(uptr-dptr->units), cptr, sprint_capac (dptr, uptr)); uptr->capac = saved_capac; sim_printf ("%s)\n", sprint_capac (dptr, uptr)); } sim_disk_detach (uptr); return SCPE_OPENERR; } if ((capac < (((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))) && (DKUF_F_STD != DK_GET_FMT (uptr))) { if (!sim_quiet) { uptr->capac = (t_addr)(capac/(ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))); sim_printf ("%s%d: non expandable disk %s is smaller than simulated device (%s < ", sim_dname (dptr), (int)(uptr-dptr->units), cptr, sprint_capac (dptr, uptr)); uptr->capac = saved_capac; sim_printf ("%s)\n", sprint_capac (dptr, uptr)); } sim_disk_detach (uptr); return SCPE_OPENERR; } } else { if ((filesystem_capac != (t_offset)-1) && (filesystem_capac > capac)) capac = filesystem_capac; if ((capac != (((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))) || (DKUF_F_STD != DK_GET_FMT (uptr))) uptr->capac = (t_addr)(capac/(ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))); } } #if defined (SIM_ASYNCH_IO) sim_disk_set_async (uptr, completion_delay); #endif uptr->io_flush = _sim_disk_io_flush; return SCPE_OK; } t_stat sim_disk_detach (UNIT *uptr) { struct disk_context *ctx; int (*close_function)(FILE *f); FILE *fileref; t_bool auto_format; if ((uptr == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_NOTATT; ctx = (struct disk_context *)uptr->disk_ctx; fileref = uptr->fileref; sim_debug (ctx->dbit, ctx->dptr, "sim_disk_detach(unit=%d,filename='%s')\n", (int)(uptr-ctx->dptr->units), uptr->filename); switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_STD: /* Simh */ close_function = fclose; break; case DKUF_F_VHD: /* Virtual Disk */ close_function = sim_vhd_disk_close; break; case DKUF_F_RAW: /* Physical */ close_function = sim_os_disk_close_raw; break; default: return SCPE_IERR; } if (!(uptr->flags & UNIT_ATTABLE)) /* attachable? */ return SCPE_NOATT; if (!(uptr->flags & UNIT_ATT)) /* attached? */ return SCPE_OK; if (NULL == find_dev_from_unit (uptr)) return SCPE_OK; auto_format = ctx->auto_format; if (uptr->io_flush) uptr->io_flush (uptr); /* flush buffered data */ sim_disk_clr_async (uptr); uptr->flags &= ~(UNIT_ATT | UNIT_RO); uptr->dynflags &= ~(UNIT_NO_FIO | UNIT_DISK_CHK); free (uptr->filename); uptr->filename = NULL; uptr->fileref = NULL; free (uptr->disk_ctx); uptr->disk_ctx = NULL; uptr->io_flush = NULL; if (auto_format) sim_disk_set_fmt (uptr, 0, "SIMH", NULL); /* restore file format */ if (close_function (fileref) == EOF) return SCPE_IOERR; return SCPE_OK; } t_stat sim_disk_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { fprintf (st, "%s Disk Attach Help\n\n", dptr->name); fprintf (st, "Disk container files can be one of 3 different types:\n\n"); fprintf (st, " SIMH A disk is an unstructured binary file of the size appropriate\n"); fprintf (st, " for the disk drive being simulated\n"); fprintf (st, " VHD Virtual Disk format which is described in the \"Microsoft\n"); fprintf (st, " Virtual Hard Disk (VHD) Image Format Specification\". The\n"); fprintf (st, " VHD implementation includes support for 1) Fixed (Preallocated)\n"); fprintf (st, " disks, 2) Dynamically Expanding disks, and 3) Differencing disks.\n"); fprintf (st, " RAW platform specific access to physical disk or CDROM drives\n\n"); fprintf (st, "Virtual (VHD) Disks supported conform to \"Virtual Hard Disk Image Format\n"); fprintf (st, "Specification\", Version 1.0 October 11, 2006.\n"); fprintf (st, "Dynamically expanding disks never change their \"Virtual Size\", but they don't\n"); fprintf (st, "consume disk space on the containing storage until the virtual sectors in the\n"); fprintf (st, "disk are actually written to (i.e. a 2GB Dynamic disk container file with only\n"); fprintf (st, "30MB of data will initially be about 30MB in size and this size will grow up to\n"); fprintf (st, "2GB as different sectors are written to. The VHD format contains metadata\n"); fprintf (st, "which describes the drive size and the simh device type in use when the VHD\n"); fprintf (st, "was created. This metadata is therefore available whenever that VHD is\n"); fprintf (st, "attached to an emulated disk device in the future so the device type and\n"); fprintf (st, "size can be automatically be configured.\n\n"); if (0 == (uptr-dptr->units)) { if (dptr->numunits > 1) { uint32 i; for (i=0; i < dptr->numunits; ++i) if (dptr->units[i].flags & UNIT_ATTABLE) fprintf (st, " sim> ATTACH {switches} %s%d diskfile\n", dptr->name, i); } else fprintf (st, " sim> ATTACH {switches} %s diskfile\n", dptr->name); } else fprintf (st, " sim> ATTACH {switches} %s diskfile\n\n", dptr->name); fprintf (st, "\n%s attach command switches\n", dptr->name); fprintf (st, " -R Attach Read Only.\n"); fprintf (st, " -E Must Exist (if not specified an attempt to create the indicated\n"); fprintf (st, " disk container will be attempted).\n"); fprintf (st, " -F Open the indicated disk container in a specific format (default\n"); fprintf (st, " is to autodetect VHD defaulting to simh if the indicated\n"); fprintf (st, " container is not a VHD).\n"); fprintf (st, " -I Initialize newly created disk so that each sector contains its\n"); fprintf (st, " sector address\n"); fprintf (st, " -K Verify that the disk contents contain the sector address in each\n"); fprintf (st, " sector. Whole disk checked at attach time and each sector is\n"); fprintf (st, " checked when written.\n"); fprintf (st, " -C Create a VHD and copy its contents from another disk (simh, VHD,\n"); fprintf (st, " or RAW format). Add a -V switch to verify a copy operation.\n"); fprintf (st, " -V Perform a verification pass to confirm successful data copy\n"); fprintf (st, " operation.\n"); fprintf (st, " -X When creating a VHD, create a fixed sized VHD (vs a Dynamically\n"); fprintf (st, " expanding one).\n"); fprintf (st, " -D Create a Differencing VHD (relative to an already existing VHD\n"); fprintf (st, " disk)\n"); fprintf (st, " -M Merge a Differencing VHD into its parent VHD disk\n"); fprintf (st, " -O Override consistency checks when attaching differencing disks\n"); fprintf (st, " which have unexpected parent disk GUID or timestamps\n\n"); fprintf (st, " -U Fix inconsistencies which are overridden by the -O switch\n"); fprintf (st, " -Y Answer Yes to prompt to overwrite last track (on disk create)\n"); fprintf (st, " -N Answer No to prompt to overwrite last track (on disk create)\n"); fprintf (st, "Examples:\n"); fprintf (st, " sim> show rq\n"); fprintf (st, " RQ, address=20001468-2000146B*, no vector, 4 units\n"); fprintf (st, " RQ0, 159MB, not attached, write enabled, RD54, autosize, SIMH format\n"); fprintf (st, " RQ1, 159MB, not attached, write enabled, RD54, autosize, SIMH format\n"); fprintf (st, " RQ2, 159MB, not attached, write enabled, RD54, autosize, SIMH format\n"); fprintf (st, " RQ3, 409KB, not attached, write enabled, RX50, autosize, SIMH format\n"); fprintf (st, " sim> atta rq0 RA81.vhd\n"); fprintf (st, " sim> show rq0\n"); fprintf (st, " RQ0, 456MB, attached to RA81.vhd, write enabled, RA81, autosize, VHD format\n"); fprintf (st, " sim> set rq2 ra92\n"); fprintf (st, " sim> att rq2 -f vhd RA92.vhd\n"); fprintf (st, " RQ2: creating new file\n"); fprintf (st, " sim> sho rq2\n"); fprintf (st, " RQ2, 1505MB, attached to RA92.vhd, write enabled, RA92, autosize, VHD format\n"); fprintf (st, " sim> ! dir RA92.vhd\n"); fprintf (st, " Volume in drive H is New Volume\n"); fprintf (st, " Volume Serial Number is F8DE-510C\n\n"); fprintf (st, " Directory of H:\\Data\n\n"); fprintf (st, " 04/14/2011 12:57 PM 5,120 RA92.vhd\n"); fprintf (st, " 1 File(s) 5,120 bytes\n"); fprintf (st, " sim> atta rq3 -d RA92-1-Diff.vhd RA92.vhd\n"); fprintf (st, " sim> atta rq3 -c RA92-1.vhd RA92.vhd\n"); fprintf (st, " RQ3: creating new virtual disk 'RA92-1.vhd'\n"); fprintf (st, " RQ3: Copied 1505MB. 99%% complete.\n"); fprintf (st, " RQ3: Copied 1505MB. Done.\n"); fprintf (st, " sim> sh rq3\n"); fprintf (st, " RQ3, 1505MB, attached to RA92-1.vhd, write enabled, RA92, autosize, VHD format\n"); fprintf (st, " sim> ! dir RA92*\n"); fprintf (st, " Volume in drive H is New Volume\n"); fprintf (st, " Volume Serial Number is F8DE-510C\n\n"); fprintf (st, " Directory of H:\\Data\n\n"); fprintf (st, " 04/14/2011 01:12 PM 5,120 RA92-1.vhd\n"); fprintf (st, " 04/14/2011 12:58 PM 5,120 RA92.vhd\n"); fprintf (st, " 2 File(s) 10,240 bytes\n"); fprintf (st, " sim> sho rq2\n"); fprintf (st, " RQ2, 1505MB, not attached, write enabled, RA92, autosize, VHD format\n"); fprintf (st, " sim> set rq2 ra81\n"); fprintf (st, " sim> set rq2 noauto\n"); fprintf (st, " sim> sho rq2\n"); fprintf (st, " RQ2, 456MB, not attached, write enabled, RA81, noautosize, VHD format\n"); fprintf (st, " sim> set rq2 format=simh\n"); fprintf (st, " sim> sho rq2\n"); fprintf (st, " RQ2, 456MB, not attached, write enabled, RA81, noautosize, SIMH format\n"); fprintf (st, " sim> atta rq2 -c RA81-Copy.vhd VMS055.dsk\n"); fprintf (st, " RQ2: creating new virtual disk 'RA81-Copy.vhd'\n"); fprintf (st, " RQ2: Copied 456MB. 99%% complete.\n"); fprintf (st, " RQ2: Copied 456MB. Done.\n"); fprintf (st, " sim> sho rq2\n"); fprintf (st, " RQ2, 456MB, attached to RA81-Copy.vhd, write enabled, RA81, noautosize, VHD format\n"); return SCPE_OK; } t_bool sim_disk_vhd_support (void) { return SCPE_OK == sim_vhd_disk_implemented (); } t_bool sim_disk_raw_support (void) { return SCPE_OK == sim_os_disk_implemented_raw (); } t_stat sim_disk_reset (UNIT *uptr) { struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; if (!(uptr->flags & UNIT_ATT)) /* attached? */ return SCPE_OK; sim_debug (ctx->dbit, ctx->dptr, "sim_disk_reset(unit=%d)\n", (int)(uptr-ctx->dptr->units)); _sim_disk_io_flush(uptr); AIO_VALIDATE; AIO_UPDATE_QUEUE; return SCPE_OK; } t_stat sim_disk_perror (UNIT *uptr, const char *msg) { int saved_errno = errno; if (!(uptr->flags & UNIT_ATTABLE)) /* not attachable? */ return SCPE_NOATT; switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_STD: /* SIMH format */ case DKUF_F_VHD: /* VHD format */ case DKUF_F_RAW: /* Raw Physical Disk Access */ perror (msg); sim_printf ("%s %s: %s\n", sim_uname(uptr), msg, strerror(saved_errno)); default: ; } return SCPE_OK; } t_stat sim_disk_clearerr (UNIT *uptr) { if (!(uptr->flags & UNIT_ATTABLE)) /* not attachable? */ return SCPE_NOATT; switch (DK_GET_FMT (uptr)) { /* case on format */ case DKUF_F_STD: /* SIMH format */ clearerr (uptr->fileref); break; case DKUF_F_VHD: /* VHD format */ sim_vhd_disk_clearerr (uptr); break; default: ; } return SCPE_OK; } /* Factory bad block table creation routine This routine writes a DEC standard 144 compliant bad block table on the last track of the specified unit as described in: EL-00144_B_DEC_STD_144_Disk_Standard_for_Recording_and_Handling_Bad_Sectors_Nov76.pdf The bad block table consists of 10 repetitions of the same table, formatted as follows: words 0-1 pack id number words 2-3 cylinder/sector/surface specifications : words n-n+1 end of table (-1,-1) Inputs: uptr = pointer to unit sec = number of sectors per surface wds = number of words per sector Outputs: sta = status code */ t_stat sim_disk_pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds) { struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; int32 i; t_addr da; uint16 *buf; DEVICE *dptr; char *namebuf, *c; uint32 packid; t_stat stat = SCPE_OK; if ((sec < 2) || (wds < 16)) return SCPE_ARG; if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_NOATT; if (uptr->flags & UNIT_RO) return SCPE_RO; if (!get_yn ("Overwrite last track? [N]", FALSE)) return SCPE_OK; if ((buf = (uint16 *) malloc (wds * sizeof (uint16))) == NULL) return SCPE_MEM; namebuf = uptr->filename; if ((c = strrchr (namebuf, '/'))) namebuf = c+1; if ((c = strrchr (namebuf, '\\'))) namebuf = c+1; if ((c = strrchr (namebuf, ']'))) namebuf = c+1; packid = eth_crc32(0, namebuf, strlen (namebuf)); buf[0] = (uint16)packid; buf[1] = (uint16)(packid >> 16) & 0x7FFF; /* Make sure MSB is clear */ buf[2] = buf[3] = 0; for (i = 4; i < wds; i++) buf[i] = 0177777u; da = (uptr->capac*((dptr->flags & DEV_SECTORS) ? 512 : 1)) - (sec * wds); for (i = 0; (stat == SCPE_OK) && (i < sec) && (i < 10); i++, da += wds) if (ctx) stat = sim_disk_wrsect (uptr, (t_lba)(da/wds), (uint8 *)buf, NULL, 1); else { if (sim_fseek (uptr->fileref, da, SEEK_SET)) { stat = SCPE_IOERR; break; } if (wds != sim_fwrite (buf, sizeof (uint16), wds, uptr->fileref)) stat = SCPE_IOERR; } free (buf); return stat; } void sim_disk_data_trace(UNIT *uptr, const uint8 *data, size_t lba, size_t len, const char* txt, int detail, uint32 reason) { DEVICE *dptr = find_dev_from_unit (uptr); if (sim_deb && (dptr->dctrl & reason)) { char pos[32]; sprintf (pos, "lbn: %08X ", (unsigned int)lba); sim_data_trace(dptr, uptr, (detail ? data : NULL), pos, len, txt, reason); } } /* OS Specific RAW Disk I/O support */ #if defined _WIN32 static void _set_errno_from_status (DWORD dwStatus) { switch (dwStatus) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: case ERROR_INVALID_DRIVE: case ERROR_NO_MORE_FILES: case ERROR_BAD_NET_NAME: case ERROR_BAD_NETPATH: case ERROR_BAD_PATHNAME: case ERROR_FILENAME_EXCED_RANGE: errno = ENOENT; return; case ERROR_INVALID_ACCESS: case ERROR_INVALID_DATA: case ERROR_INVALID_FUNCTION: case ERROR_INVALID_PARAMETER: case ERROR_NEGATIVE_SEEK: errno = EINVAL; return; case ERROR_ARENA_TRASHED: case ERROR_NOT_ENOUGH_MEMORY: case ERROR_INVALID_BLOCK: case ERROR_NOT_ENOUGH_QUOTA: errno = ENOMEM; return; case ERROR_TOO_MANY_OPEN_FILES: errno = EMFILE; return; case ERROR_ACCESS_DENIED: case ERROR_CURRENT_DIRECTORY: case ERROR_LOCK_VIOLATION: case ERROR_NETWORK_ACCESS_DENIED: case ERROR_CANNOT_MAKE: case ERROR_FAIL_I24: case ERROR_DRIVE_LOCKED: case ERROR_SEEK_ON_DEVICE: case ERROR_NOT_LOCKED: case ERROR_LOCK_FAILED: errno = EACCES; return; case ERROR_ALREADY_EXISTS: case ERROR_FILE_EXISTS: errno = EEXIST; return; case ERROR_INVALID_HANDLE: case ERROR_INVALID_TARGET_HANDLE: case ERROR_DIRECT_ACCESS_HANDLE: errno = EBADF; return; case ERROR_DIR_NOT_EMPTY: errno = ENOTEMPTY; return; case ERROR_BAD_ENVIRONMENT: errno = E2BIG; return; case ERROR_BAD_FORMAT: errno = ENOEXEC; return; case ERROR_NOT_SAME_DEVICE: errno = EXDEV; return; case ERROR_BROKEN_PIPE: errno = EPIPE; return; case ERROR_DISK_FULL: errno = ENOSPC; return; case ERROR_WAIT_NO_CHILDREN: case ERROR_CHILD_NOT_COMPLETE: errno = ECHILD; return; case ERROR_NO_PROC_SLOTS: case ERROR_MAX_THRDS_REACHED: case ERROR_NESTING_NOT_ALLOWED: errno = EAGAIN; return; } if ((dwStatus >= ERROR_WRITE_PROTECT) && (dwStatus <= ERROR_SHARING_BUFFER_EXCEEDED)) { errno = EACCES; return; } if ((dwStatus >= ERROR_INVALID_STARTING_CODESEG) && (dwStatus <= ERROR_INFLOOP_IN_RELOC_CHAIN)) { errno = ENOEXEC; return; } errno = EINVAL; } #if defined(__GNUC__) #include <ddk/ntddstor.h> #include <ddk/ntdddisk.h> #else #include <winioctl.h> #endif #if defined(__cplusplus) extern "C" { #endif WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize); #if defined(__cplusplus) } #endif struct _device_type { int32 Type; const char *desc; } DeviceTypes[] = { {FILE_DEVICE_8042_PORT, "8042_PORT"}, {FILE_DEVICE_ACPI, "ACPI"}, {FILE_DEVICE_BATTERY, "BATTERY"}, {FILE_DEVICE_BEEP, "BEEP"}, #ifdef FILE_DEVICE_BLUETOOTH {FILE_DEVICE_BLUETOOTH, "BLUETOOTH"}, #endif {FILE_DEVICE_BUS_EXTENDER, "BUS_EXTENDER"}, {FILE_DEVICE_CD_ROM, "CD_ROM"}, {FILE_DEVICE_CD_ROM_FILE_SYSTEM, "CD_ROM_FILE_SYSTEM"}, {FILE_DEVICE_CHANGER, "CHANGER"}, {FILE_DEVICE_CONTROLLER, "CONTROLLER"}, #ifdef FILE_DEVICE_CRYPT_PROVIDER {FILE_DEVICE_CRYPT_PROVIDER, "CRYPT_PROVIDER"}, #endif {FILE_DEVICE_DATALINK, "DATALINK"}, {FILE_DEVICE_DFS, "DFS"}, {FILE_DEVICE_DFS_FILE_SYSTEM, "DFS_FILE_SYSTEM"}, {FILE_DEVICE_DFS_VOLUME, "DFS_VOLUME"}, {FILE_DEVICE_DISK, "DISK"}, {FILE_DEVICE_DISK_FILE_SYSTEM, "DISK_FILE_SYSTEM"}, {FILE_DEVICE_DVD, "DVD"}, {FILE_DEVICE_FILE_SYSTEM, "FILE_SYSTEM"}, #ifdef FILE_DEVICE_FIPS {FILE_DEVICE_FIPS, "FIPS"}, #endif {FILE_DEVICE_FULLSCREEN_VIDEO, "FULLSCREEN_VIDEO"}, #ifdef FILE_DEVICE_INFINIBAND {FILE_DEVICE_INFINIBAND, "INFINIBAND"}, #endif {FILE_DEVICE_INPORT_PORT, "INPORT_PORT"}, {FILE_DEVICE_KEYBOARD, "KEYBOARD"}, {FILE_DEVICE_KS, "KS"}, {FILE_DEVICE_KSEC, "KSEC"}, {FILE_DEVICE_MAILSLOT, "MAILSLOT"}, {FILE_DEVICE_MASS_STORAGE, "MASS_STORAGE"}, {FILE_DEVICE_MIDI_IN, "MIDI_IN"}, {FILE_DEVICE_MIDI_OUT, "MIDI_OUT"}, {FILE_DEVICE_MODEM, "MODEM"}, {FILE_DEVICE_MOUSE, "MOUSE"}, {FILE_DEVICE_MULTI_UNC_PROVIDER, "MULTI_UNC_PROVIDER"}, {FILE_DEVICE_NAMED_PIPE, "NAMED_PIPE"}, {FILE_DEVICE_NETWORK, "NETWORK"}, {FILE_DEVICE_NETWORK_BROWSER, "NETWORK_BROWSER"}, {FILE_DEVICE_NETWORK_FILE_SYSTEM, "NETWORK_FILE_SYSTEM"}, {FILE_DEVICE_NETWORK_REDIRECTOR, "NETWORK_REDIRECTOR"}, {FILE_DEVICE_NULL, "NULL"}, {FILE_DEVICE_PARALLEL_PORT, "PARALLEL_PORT"}, {FILE_DEVICE_PHYSICAL_NETCARD, "PHYSICAL_NETCARD"}, {FILE_DEVICE_PRINTER, "PRINTER"}, {FILE_DEVICE_SCANNER, "SCANNER"}, {FILE_DEVICE_SCREEN, "SCREEN"}, {FILE_DEVICE_SERENUM, "SERENUM"}, {FILE_DEVICE_SERIAL_MOUSE_PORT, "SERIAL_MOUSE_PORT"}, {FILE_DEVICE_SERIAL_PORT, "SERIAL_PORT"}, {FILE_DEVICE_SMARTCARD, "SMARTCARD"}, {FILE_DEVICE_SMB, "SMB"}, {FILE_DEVICE_SOUND, "SOUND"}, {FILE_DEVICE_STREAMS, "STREAMS"}, {FILE_DEVICE_TAPE, "TAPE"}, {FILE_DEVICE_TAPE_FILE_SYSTEM, "TAPE_FILE_SYSTEM"}, {FILE_DEVICE_TERMSRV, "TERMSRV"}, {FILE_DEVICE_TRANSPORT, "TRANSPORT"}, {FILE_DEVICE_UNKNOWN, "UNKNOWN"}, {FILE_DEVICE_VDM, "VDM"}, {FILE_DEVICE_VIDEO, "VIDEO"}, {FILE_DEVICE_VIRTUAL_DISK, "VIRTUAL_DISK"}, #ifdef FILE_DEVICE_VMBUS {FILE_DEVICE_VMBUS, "VMBUS"}, #endif {FILE_DEVICE_WAVE_IN, "WAVE_IN"}, {FILE_DEVICE_WAVE_OUT, "WAVE_OUT"}, #ifdef FILE_DEVICE_WPD {FILE_DEVICE_WPD, "WPD"}, #endif {0, NULL}}; static const char *_device_type_name (int DeviceType) { int i; for (i=0; DeviceTypes[i].desc; i++) if (DeviceTypes[i].Type == DeviceType) return DeviceTypes[i].desc; return "Unknown"; } static t_stat sim_os_disk_implemented_raw (void) { return sim_toffset_64 ? SCPE_OK : SCPE_NOFNC; } static FILE *sim_os_disk_open_raw (const char *rawdevicename, const char *openmode) { HANDLE Handle; DWORD DesiredAccess = 0; if (strchr (openmode, 'r')) DesiredAccess |= GENERIC_READ; if (strchr (openmode, 'w') || strchr (openmode, '+')) DesiredAccess |= GENERIC_WRITE; /* SCP Command Line parsing replaces \\ with \ presuming this is an escape sequence. This only affecdts RAW device names and UNC paths. We handle the RAW device name case here by prepending paths beginning with \.\ with an extra \. */ if (!memcmp ("\\.\\", rawdevicename, 3)) { char *tmpname = (char *)malloc (2 + strlen (rawdevicename)); if (tmpname == NULL) return NULL; *tmpname = '\\'; strcpy (tmpname + 1, rawdevicename); Handle = CreateFileA (tmpname, DesiredAccess, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS|FILE_FLAG_WRITE_THROUGH, NULL); free (tmpname); if (Handle != INVALID_HANDLE_VALUE) return (FILE *)Handle; } Handle = CreateFileA (rawdevicename, DesiredAccess, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS|FILE_FLAG_WRITE_THROUGH, NULL); if (Handle == INVALID_HANDLE_VALUE) { _set_errno_from_status (GetLastError ()); return NULL; } return (FILE *)Handle; } static int sim_os_disk_close_raw (FILE *f) { if (!CloseHandle ((HANDLE)f)) { _set_errno_from_status (GetLastError ()); return EOF; } return 0; } static void sim_os_disk_flush_raw (FILE *f) { FlushFileBuffers ((HANDLE)f); } static t_offset sim_os_disk_size_raw (FILE *Disk) { DWORD IoctlReturnSize; LARGE_INTEGER Size; if (GetFileSizeEx((HANDLE)Disk, &Size)) return (t_offset)(Size.QuadPart); #ifdef IOCTL_STORAGE_READ_CAPACITY if (1) { STORAGE_READ_CAPACITY S; ZeroMemory (&S, sizeof (S)); S.Version = sizeof (STORAGE_READ_CAPACITY); if (DeviceIoControl((HANDLE)Disk, /* handle to volume */ IOCTL_STORAGE_READ_CAPACITY, /* dwIoControlCode */ NULL, /* lpInBuffer */ 0, /* nInBufferSize */ (LPVOID) &S, /* output buffer */ (DWORD) sizeof(S), /* size of output buffer */ (LPDWORD) &IoctlReturnSize, /* number of bytes returned */ (LPOVERLAPPED) NULL)) /* OVERLAPPED structure */ return (t_offset)(S.DiskLength.QuadPart); } #endif #ifdef IOCTL_DISK_GET_DRIVE_GEOMETRY_EX if (1) { DISK_GEOMETRY_EX G; ZeroMemory (&G, sizeof (G)); if (DeviceIoControl((HANDLE)Disk, /* handle to volume */ IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, /* dwIoControlCode */ NULL, /* lpInBuffer */ 0, /* nInBufferSize */ (LPVOID) &G, /* output buffer */ (DWORD) sizeof(G), /* size of output buffer */ (LPDWORD) &IoctlReturnSize, /* number of bytes returned */ (LPOVERLAPPED) NULL)) /* OVERLAPPED structure */ return (t_offset)(G.DiskSize.QuadPart); } #endif #ifdef IOCTL_DISK_GET_DRIVE_GEOMETRY if (1) { DISK_GEOMETRY G; if (DeviceIoControl((HANDLE)Disk, /* handle to volume */ IOCTL_DISK_GET_DRIVE_GEOMETRY, /* dwIoControlCode */ NULL, /* lpInBuffer */ 0, /* nInBufferSize */ (LPVOID) &G, /* output buffer */ (DWORD) sizeof(G), /* size of output buffer */ (LPDWORD) &IoctlReturnSize, /* number of bytes returned */ (LPOVERLAPPED) NULL)) /* OVERLAPPED structure */ return (t_offset)(G.Cylinders.QuadPart*G.TracksPerCylinder*G.SectorsPerTrack*G.BytesPerSector); } #endif _set_errno_from_status (GetLastError ()); return (t_offset)-1; } static t_stat sim_os_disk_unload_raw (FILE *Disk) { #ifdef IOCTL_STORAGE_EJECT_MEDIA DWORD BytesReturned; uint32 Removable = FALSE; sim_os_disk_info_raw (Disk, NULL, &Removable); if (Removable) { if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */ IOCTL_STORAGE_EJECT_MEDIA, /* dwIoControlCode */ NULL, /* lpInBuffer */ 0, /* nInBufferSize */ NULL, /* lpOutBuffer */ 0, /* nOutBufferSize */ (LPDWORD) &BytesReturned, /* number of bytes returned */ (LPOVERLAPPED) NULL)) { /* OVERLAPPED structure */ _set_errno_from_status (GetLastError ()); return SCPE_IOERR; } } return SCPE_OK; #else return SCPE_NOFNC; #endif } static t_bool sim_os_disk_isavailable_raw (FILE *Disk) { #ifdef IOCTL_STORAGE_EJECT_MEDIA DWORD BytesReturned; uint32 Removable = FALSE; sim_os_disk_info_raw (Disk, NULL, &Removable); if (Removable) { if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */ IOCTL_STORAGE_CHECK_VERIFY, /* dwIoControlCode */ NULL, /* lpInBuffer */ 0, /* nInBufferSize */ NULL, /* lpOutBuffer */ 0, /* nOutBufferSize */ (LPDWORD) &BytesReturned, /* number of bytes returned */ (LPOVERLAPPED) NULL)) { /* OVERLAPPED structure */ _set_errno_from_status (GetLastError ()); return FALSE; } } #endif return TRUE; } static t_stat sim_os_disk_info_raw (FILE *Disk, uint32 *sector_size, uint32 *removable) { DWORD IoctlReturnSize; STORAGE_DEVICE_NUMBER Device; ZeroMemory (&Device, sizeof (Device)); if (DeviceIoControl((HANDLE)Disk, /* handle to volume */ IOCTL_STORAGE_GET_DEVICE_NUMBER, /* dwIoControlCode */ NULL, /* lpInBuffer */ 0, /* nInBufferSize */ (LPVOID) &Device, /* output buffer */ (DWORD) sizeof(Device), /* size of output buffer */ (LPDWORD) &IoctlReturnSize, /* number of bytes returned */ (LPOVERLAPPED) NULL)) /* OVERLAPPED structure */ sim_printf ("Device OK - Type: %s, Number: %d\n", _device_type_name (Device.DeviceType), (int)Device.DeviceNumber); if (sector_size) *sector_size = 512; if (removable) *removable = 0; #ifdef IOCTL_STORAGE_READ_CAPACITY if (1) { STORAGE_READ_CAPACITY S; ZeroMemory (&S, sizeof (S)); S.Version = sizeof (STORAGE_READ_CAPACITY); if (DeviceIoControl((HANDLE)Disk, /* handle to volume */ IOCTL_STORAGE_READ_CAPACITY, /* dwIoControlCode */ NULL, /* lpInBuffer */ 0, /* nInBufferSize */ (LPVOID) &S, /* output buffer */ (DWORD) sizeof(S), /* size of output buffer */ (LPDWORD) &IoctlReturnSize, /* number of bytes returned */ (LPOVERLAPPED) NULL)) /* OVERLAPPED structure */ if (sector_size) *sector_size = S.BlockLength; } #endif #ifdef IOCTL_DISK_GET_DRIVE_GEOMETRY_EX if (1) { DISK_GEOMETRY_EX G; ZeroMemory (&G, sizeof (G)); if (DeviceIoControl((HANDLE)Disk, /* handle to volume */ IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, /* dwIoControlCode */ NULL, /* lpInBuffer */ 0, /* nInBufferSize */ (LPVOID) &G, /* output buffer */ (DWORD) sizeof(G), /* size of output buffer */ (LPDWORD) &IoctlReturnSize, /* number of bytes returned */ (LPOVERLAPPED) NULL)) /* OVERLAPPED structure */ if (sector_size) *sector_size = G.Geometry.BytesPerSector; } #endif #ifdef IOCTL_DISK_GET_DRIVE_GEOMETRY if (1) { DISK_GEOMETRY G; if (DeviceIoControl((HANDLE)Disk, /* handle to volume */ IOCTL_DISK_GET_DRIVE_GEOMETRY, /* dwIoControlCode */ NULL, /* lpInBuffer */ 0, /* nInBufferSize */ (LPVOID) &G, /* output buffer */ (DWORD) sizeof(G), /* size of output buffer */ (LPDWORD) &IoctlReturnSize, /* number of bytes returned */ (LPOVERLAPPED) NULL)) /* OVERLAPPED structure */ if (sector_size) *sector_size = G.BytesPerSector; } #endif #ifdef IOCTL_STORAGE_GET_HOTPLUG_INFO if (1) { STORAGE_HOTPLUG_INFO H; ZeroMemory (&H, sizeof (H)); if (DeviceIoControl((HANDLE)Disk, /* handle to volume */ IOCTL_STORAGE_GET_HOTPLUG_INFO, /* dwIoControlCode */ NULL, /* lpInBuffer */ 0, /* nInBufferSize */ (LPVOID) &H, /* output buffer */ (DWORD) sizeof(H), /* size of output buffer */ (LPDWORD) &IoctlReturnSize, /* number of bytes returned */ (LPOVERLAPPED) NULL)) /* OVERLAPPED structure */ if (removable) *removable = H.MediaRemovable; } #endif if (removable && *removable) sim_printf ("Removable Device\n"); return SCPE_OK; } static t_stat sim_os_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects) { OVERLAPPED pos; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; long long addr; sim_debug (ctx->dbit, ctx->dptr, "sim_os_disk_rdsect(unit=%d, lba=0x%X, sects=%d)\n", (int)(uptr-ctx->dptr->units), lba, sects); addr = ((long long)lba) * ctx->sector_size; memset (&pos, 0, sizeof (pos)); pos.Offset = (DWORD)addr; pos.OffsetHigh = (DWORD)(addr >> 32); if (ReadFile ((HANDLE)(uptr->fileref), buf, sects * ctx->sector_size, (LPDWORD)sectsread, &pos)) { if (sectsread) *sectsread /= ctx->sector_size; return SCPE_OK; } _set_errno_from_status (GetLastError ()); return SCPE_IOERR; } static t_stat sim_os_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects) { OVERLAPPED pos; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; long long addr; sim_debug (ctx->dbit, ctx->dptr, "sim_os_disk_wrsect(unit=%d, lba=0x%X, sects=%d)\n", (int)(uptr-ctx->dptr->units), lba, sects); addr = ((long long)lba) * ctx->sector_size; memset (&pos, 0, sizeof (pos)); pos.Offset = (DWORD)addr; pos.OffsetHigh = (DWORD)(addr >> 32); if (WriteFile ((HANDLE)(uptr->fileref), buf, sects * ctx->sector_size, (LPDWORD)sectswritten, &pos)) { if (sectswritten) *sectswritten /= ctx->sector_size; return SCPE_OK; } _set_errno_from_status (GetLastError ()); return SCPE_IOERR; } #elif defined (__linux) || defined (__linux__) || defined (__sun) || defined (__sun__) || defined (__hpux) || defined (_AIX) #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> static t_stat sim_os_disk_implemented_raw (void) { return sim_toffset_64 ? SCPE_OK : SCPE_NOFNC; } static FILE *sim_os_disk_open_raw (const char *rawdevicename, const char *openmode) { int mode = 0; if (strchr (openmode, 'r') && (strchr (openmode, '+') || strchr (openmode, 'w'))) mode = O_RDWR; else if (strchr (openmode, 'r')) mode = O_RDONLY; #ifdef O_LARGEFILE mode |= O_LARGEFILE; #endif #ifdef O_DSYNC mode |= O_DSYNC; #endif return (FILE *)((long)open (rawdevicename, mode, 0)); } static int sim_os_disk_close_raw (FILE *f) { return close ((int)((long)f)); } static void sim_os_disk_flush_raw (FILE *f) { fsync ((int)((long)f)); } static t_offset sim_os_disk_size_raw (FILE *f) { t_offset pos, size; pos = (t_offset)lseek ((int)((long)f), (off_t)0, SEEK_CUR); size = (t_offset)lseek ((int)((long)f), (off_t)0, SEEK_END); if (pos != (t_offset)-1) (void)lseek ((int)((long)f), (off_t)pos, SEEK_SET); return size; } static t_stat sim_os_disk_unload_raw (FILE *f) { return SCPE_IOERR; } static t_bool sim_os_disk_isavailable_raw (FILE *Disk) { return TRUE; } static t_stat sim_os_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects) { struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; off_t addr; ssize_t bytesread; sim_debug (ctx->dbit, ctx->dptr, "sim_os_disk_rdsect(unit=%d, lba=0x%X, sects=%d)\n", (int)(uptr-ctx->dptr->units), lba, sects); addr = ((off_t)lba) * ctx->sector_size; bytesread = pread((int)((long)uptr->fileref), buf, sects * ctx->sector_size, addr); if (bytesread < 0) { if (sectsread) *sectsread = 0; return SCPE_IOERR; } if (sectsread) *sectsread = bytesread / ctx->sector_size; return SCPE_OK; } static t_stat sim_os_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects) { struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; off_t addr; ssize_t byteswritten; sim_debug (ctx->dbit, ctx->dptr, "sim_os_disk_wrsect(unit=%d, lba=0x%X, sects=%d)\n", (int)(uptr-ctx->dptr->units), lba, sects); addr = ((off_t)lba) * ctx->sector_size; byteswritten = pwrite((int)((long)uptr->fileref), buf, sects * ctx->sector_size, addr); if (byteswritten < 0) { if (sectswritten) *sectswritten = 0; return SCPE_IOERR; } if (sectswritten) *sectswritten = byteswritten / ctx->sector_size; return SCPE_OK; } static t_stat sim_os_disk_info_raw (FILE *f, uint32 *sector_size, uint32 *removable) { if (sector_size) *sector_size = 512; if (removable) *removable = 0; return SCPE_OK; } #else /*============================================================================*/ /* Non-implemented versions */ /*============================================================================*/ static t_stat sim_os_disk_implemented_raw (void) { return SCPE_NOFNC; } static FILE *sim_os_disk_open_raw (const char *rawdevicename, const char *openmode) { return NULL; } static int sim_os_disk_close_raw (FILE *f) { return EOF; } static void sim_os_disk_flush_raw (FILE *f) { } static t_offset sim_os_disk_size_raw (FILE *f) { return (t_offset)-1; } static t_stat sim_os_disk_unload_raw (FILE *f) { return SCPE_NOFNC; } static t_bool sim_os_disk_isavailable_raw (FILE *Disk) { return FALSE; } static t_stat sim_os_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects) { return SCPE_NOFNC; } static t_stat sim_os_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects) { return SCPE_NOFNC; } static t_stat sim_os_disk_info_raw (FILE *f, uint32 *sector_size, uint32 *removable) { return SCPE_NOFNC; } #endif /* OS Independent Disk Virtual Disk (VHD) I/O support */ #if (defined (VMS) && !(defined (__ALPHA) || defined (__ia64))) #define DONT_DO_VHD_SUPPORT /* VAX/VMS compilers don't have 64 bit integers */ #endif #if defined (DONT_DO_VHD_SUPPORT) /*============================================================================*/ /* Non-implemented version */ /* This is only for hody systems which don't have 64 bit integer types */ /*============================================================================*/ static t_stat sim_vhd_disk_implemented (void) { return SCPE_NOFNC; } static FILE *sim_vhd_disk_open (const char *vhdfilename, const char *openmode) { return NULL; } static FILE *sim_vhd_disk_merge (const char *szVHDPath, char **ParentVHD) { return NULL; } static FILE *sim_vhd_disk_create (const char *szVHDPath, t_offset desiredsize) { return NULL; } static FILE *sim_vhd_disk_create_diff (const char *szVHDPath, const char *szParentVHDPath) { return NULL; } static int sim_vhd_disk_close (FILE *f) { return -1; } static void sim_vhd_disk_flush (FILE *f) { } static t_offset sim_vhd_disk_size (FILE *f) { return (t_offset)-1; } static t_stat sim_vhd_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects) { return SCPE_IOERR; } static t_stat sim_vhd_disk_clearerr (UNIT *uptr) { return SCPE_IOERR; } static t_stat sim_vhd_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects) { return SCPE_IOERR; } static t_stat sim_vhd_disk_set_dtype (FILE *f, const char *dtype) { return SCPE_NOFNC; } static const char *sim_vhd_disk_get_dtype (FILE *f) { return NULL; } #else /*++ This code follows the details specified in the "Virtual Hard Disk Image Format Specification", Version 1.0 October 11, 2006. This format specification is available for anyone to implement under the "Microsoft Open Specification Promise" described at: http://www.microsoft.com/interop/osp/default.mspx. --*/ typedef t_uint64 uint64; typedef t_int64 int64; typedef struct _VHD_Footer { /* Cookies are used to uniquely identify the original creator of the hard disk image. The values are case-sensitive. Microsoft uses the "conectix" string to identify this file as a hard disk image created by Microsoft Virtual Server, Virtual PC, and predecessor products. The cookie is stored as an eight-character ASCII string with the "c" in the first byte, the "o" in the second byte, and so on. */ char Cookie[8]; /* This is a bit field used to indicate specific feature support. The following table displays the list of features. Any fields not listed are reserved. Feature Value: No features enabled 0x00000000 Temporary 0x00000001 Reserved 0x00000002 No features enabled. The hard disk image has no special features enabled in it. Temporary. This bit is set if the current disk is a temporary disk. A temporary disk designation indicates to an application that this disk is a candidate for deletion on shutdown. Reserved. This bit must always be set to 1. All other bits are also reserved and should be set to 0. */ uint32 Features; /* This field is divided into a major/minor version and matches the version of the specification used in creating the file. The most-significant two bytes are for the major version. The least-significant two bytes are the minor version. This must match the file format specification. For the current specification, this field must be initialized to 0x00010000. The major version will be incremented only when the file format is modified in such a way that it is no longer compatible with older versions of the file format. */ uint32 FileFormatVersion; /* This field holds the absolute byte offset, from the beginning of the file, to the next structure. This field is used for dynamic disks and differencing disks, but not fixed disks. For fixed disks, this field should be set to 0xFFFFFFFF. */ uint64 DataOffset; /* This field stores the creation time of a hard disk image. This is the number of seconds since January 1, 2000 12:00:00 AM in UTC/GMT. */ uint32 TimeStamp; /* This field is used to document which application created the hard disk. The field is a left-justified text field. It uses a single-byte character set. If the hard disk is created by Microsoft Virtual PC, "vpc " is written in this field. If the hard disk image is created by Microsoft Virtual Server, then "vs " is written in this field. Other applications should use their own unique identifiers. */ char CreatorApplication[4]; /* This field holds the major/minor version of the application that created the hard disk image. Virtual Server 2004 sets this value to 0x00010000 and Virtual PC 2004 sets this to 0x00050000. */ uint32 CreatorVersion; /* This field stores the type of host operating system this disk image is created on. Host OS type Value Windows 0x5769326B (Wi2k) Macintosh 0x4D616320 (Mac ) */ uint8 CreatorHostOS[4]; /* This field stores the size of the hard disk in bytes, from the perspective of the virtual machine, at creation time. This field is for informational purposes. */ uint64 OriginalSize; /* This field stores the current size of the hard disk, in bytes, from the perspective of the virtual machine. This value is same as the original size when the hard disk is created. This value can change depending on whether the hard disk is expanded. */ uint64 CurrentSize; /* This field stores the cylinder, heads, and sectors per track value for the hard disk. Disk Geometry field Size (bytes) Cylinder 2 Heads 1 Sectors per track/cylinder 1 When a hard disk is configured as an ATA hard disk, the CHS values (that is, Cylinder, Heads, Sectors per track) are used by the ATA controller to determine the size of the disk. When the user creates a hard disk of a certain size, the size of the hard disk image in the virtual machine is smaller than that created by the user. This is because CHS value calculated from the hard disk size is rounded down. The pseudo-code for the algorithm used to determine the CHS values can be found in the appendix of this document. */ uint32 DiskGeometry; /* Disk Type field Value None 0 Reserved (deprecated) 1 Fixed hard disk 2 Dynamic hard disk 3 Differencing hard disk 4 Reserved (deprecated) 5 Reserved (deprecated) 6 */ uint32 DiskType; /* This field holds a basic checksum of the hard disk footer. It is just a one's complement of the sum of all the bytes in the footer without the checksum field. If the checksum verification fails, the Virtual PC and Virtual Server products will instead use the header. If the checksum in the header also fails, the file should be assumed to be corrupt. The pseudo-code for the algorithm used to determine the checksum can be found in the appendix of this document. */ uint32 Checksum; /* Every hard disk has a unique ID stored in the hard disk. This is used to identify the hard disk. This is a 128-bit universally unique identifier (UUID). This field is used to associate a parent hard disk image with its differencing hard disk image(s). */ uint8 UniqueID[16]; /* This field holds a one-byte flag that describes whether the system is in saved state. If the hard disk is in the saved state the value is set to 1. Operations such as compaction and expansion cannot be performed on a hard disk in a saved state. */ uint8 SavedState; /* This field contains zeroes. It is 427 bytes in size. */ uint8 Reserved1[11]; /* This field is an extension to the VHD spec and includes a simh drive type name as a nul terminated string. */ uint8 DriveType[16]; /* This field contains zeroes. It is 400 bytes in size. */ uint8 Reserved[400]; } VHD_Footer; /* For dynamic and differencing disk images, the "Data Offset" field within the image footer points to a secondary structure that provides additional information about the disk image. The dynamic disk header should appear on a sector (512-byte) boundary. */ typedef struct _VHD_DynamicDiskHeader { /* This field holds the value "cxsparse". This field identifies the header. */ char Cookie[8]; /* This field contains the absolute byte offset to the next structure in the hard disk image. It is currently unused by existing formats and should be set to 0xFFFFFFFF. */ uint64 DataOffset; /* This field stores the absolute byte offset of the Block Allocation Table (BAT) in the file. */ uint64 TableOffset; /* This field stores the version of the dynamic disk header. The field is divided into Major/Minor version. The least-significant two bytes represent the minor version, and the most-significant two bytes represent the major version. This must match with the file format specification. For this specification, this field must be initialized to 0x00010000. The major version will be incremented only when the header format is modified in such a way that it is no longer compatible with older versions of the product. */ uint32 HeaderVersion; /* This field holds the maximum entries present in the BAT. This should be equal to the number of blocks in the disk (that is, the disk size divided by the block size). */ uint32 MaxTableEntries; /* A block is a unit of expansion for dynamic and differencing hard disks. It is stored in bytes. This size does not include the size of the block bitmap. It is only the size of the data section of the block. The sectors per block must always be a power of two. The default value is 0x00200000 (indicating a block size of 2 MB). */ uint32 BlockSize; /* This field holds a basic checksum of the dynamic header. It is a one's complement of the sum of all the bytes in the header without the checksum field. If the checksum verification fails the file should be assumed to be corrupt. */ uint32 Checksum; /* This field is used for differencing hard disks. A differencing hard disk stores a 128-bit UUID of the parent hard disk. For more information, see "Creating Differencing Hard Disk Images" later in this paper. */ uint8 ParentUniqueID[16]; /* This field stores the modification time stamp of the parent hard disk. This is the number of seconds since January 1, 2000 12:00:00 AM in UTC/GMT. */ uint32 ParentTimeStamp; /* This field should be set to zero. */ uint32 Reserved0; /* This field contains a Unicode string (UTF-16) of the parent hard disk filename. */ char ParentUnicodeName[512]; /* These entries store an absolute byte offset in the file where the parent locator for a differencing hard disk is stored. This field is used only for differencing disks and should be set to zero for dynamic disks. */ struct VHD_ParentLocator { /* The platform code describes which platform-specific format is used for the file locator. For Windows, a file locator is stored as a path (for example. "c:\disksimages\ParentDisk.vhd"). On a Macintosh system, the file locator is a binary large object (blob) that contains an "alias." The parent locator table is used to support moving hard disk images across platforms. Some current platform codes include the following: Platform Code Description None (0x0) Wi2r (0x57693272) [deprecated] Wi2k (0x5769326B) [deprecated] W2ru (0x57327275) Unicode pathname (UTF-16) on Windows relative to the differencing disk pathname. W2ku (0x57326B75) Absolute Unicode (UTF-16) pathname on Windows. Mac (0x4D616320) (Mac OS alias stored as a blob) MacX(0x4D616358) A file URL with UTF-8 encoding conforming to RFC 2396. */ uint8 PlatformCode[4]; /* This field stores the number of 512-byte sectors needed to store the parent hard disk locator. */ uint32 PlatformDataSpace; /* This field stores the actual length of the parent hard disk locator in bytes. */ uint32 PlatformDataLength; /* This field must be set to zero. */ uint32 Reserved; /* This field stores the absolute file offset in bytes where the platform specific file locator data is stored. */ uint64 PlatformDataOffset; /* This field stores the absolute file offset in bytes where the platform specific file locator data is stored. */ } ParentLocatorEntries[8]; /* This must be initialized to zeroes. */ char Reserved[256]; } VHD_DynamicDiskHeader; #define VHD_BAT_FREE_ENTRY (0xFFFFFFFF) #define VHD_DATA_BLOCK_ALIGNMENT ((uint64)4096) /* Optimum when underlying storage has 4k sectors */ #define VHD_DT_Fixed 2 /* Fixed hard disk */ #define VHD_DT_Dynamic 3 /* Dynamic hard disk */ #define VHD_DT_Differencing 4 /* Differencing hard disk */ static uint32 NtoHl(uint32 value); static uint64 NtoHll(uint64 value); typedef struct VHD_IOData *VHDHANDLE; static t_stat ReadFilePosition(FILE *File, void *buf, size_t bufsize, size_t *bytesread, uint64 position) { uint32 err = sim_fseeko (File, (t_offset)position, SEEK_SET); size_t i; if (bytesread) *bytesread = 0; if (!err) { i = fread (buf, 1, bufsize, File); err = ferror (File); if ((!err) && bytesread) *bytesread = i; } return (err ? SCPE_IOERR : SCPE_OK); } static t_stat WriteFilePosition(FILE *File, void *buf, size_t bufsize, size_t *byteswritten, uint64 position) { uint32 err = sim_fseeko (File, (t_offset)position, SEEK_SET); size_t i; if (byteswritten) *byteswritten = 0; if (!err) { i = fwrite (buf, 1, bufsize, File); err = ferror (File); if ((!err) && byteswritten) *byteswritten = i; } return (err ? SCPE_IOERR : SCPE_OK); } static uint32 CalculateVhdFooterChecksum(void *data, size_t size) { uint32 sum = 0; uint8 *c = (uint8 *)data; while (size--) sum += *c++; return ~sum; } #if defined(_WIN32) || defined (__ALPHA) || defined (__ia64) || defined (VMS) #ifndef __BYTE_ORDER__ #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ #endif #endif #ifndef __BYTE_ORDER__ #define __BYTE_ORDER__ UNKNOWN #endif #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ static uint32 NtoHl(uint32 value) { uint8 *l = (uint8 *)&value; return (uint32)l[3] | ((uint32)l[2]<<8) | ((uint32)l[1]<<16) | ((uint32)l[0]<<24); } static uint64 NtoHll(uint64 value) { uint8 *l = (uint8 *)&value; uint64 highresult = (uint64)l[3] | ((uint64)l[2]<<8) | ((uint64)l[1]<<16) | ((uint64)l[0]<<24); uint32 lowresult = (uint64)l[7] | ((uint64)l[6]<<8) | ((uint64)l[5]<<16) | ((uint64)l[4]<<24); return (highresult << 32) | lowresult; } #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ static uint32 NtoHl(uint32 value) { return value; } static uint64 NtoHll(uint64 value) { return value; } #else static uint32 NtoHl(uint32 value) { uint8 *l = (uint8 *)&value; if (sim_end) return l[3] | (l[2]<<8) | (l[1]<<16) | (l[0]<<24); return value; } static uint64 NtoHll(uint64 value) { uint8 *l = (uint8 *)&value; if (sim_end) { uint64 highresult = l[3] | (l[2]<<8) | (l[1]<<16) | (l[0]<<24); uint32 lowresult = l[7] | (l[6]<<8) | (l[5]<<16) | (l[4]<<24); return (highresult << 32) | lowresult; } return value; } #endif static int GetVHDFooter(const char *szVHDPath, VHD_Footer *sFooter, VHD_DynamicDiskHeader *sDynamic, uint32 **aBAT, uint32 *ModifiedTimeStamp, char *szParentVHDPath, size_t ParentVHDPathSize) { FILE *File = NULL; uint64 position; uint32 sum, saved_sum; int Return = 0; VHD_Footer sHeader; struct stat statb; memset(sFooter, '\0', sizeof(*sFooter)); if (sDynamic) memset(sDynamic, '\0', sizeof(*sDynamic)); if (aBAT) *aBAT = NULL; File = sim_fopen (szVHDPath, "rb"); if (!File) { Return = errno; goto Return_Cleanup; } if (ModifiedTimeStamp) { if (fstat (fileno (File), &statb)) { Return = errno; goto Return_Cleanup; } else *ModifiedTimeStamp = NtoHl ((uint32)(statb.st_mtime-946684800)); } position = sim_fsize_ex (File); if (((int64)position) == -1) { Return = errno; goto Return_Cleanup; } position -= sizeof(*sFooter); if (ReadFilePosition(File, sFooter, sizeof(*sFooter), NULL, position)) { Return = errno; goto Return_Cleanup; } saved_sum = NtoHl(sFooter->Checksum); sFooter->Checksum = 0; sum = CalculateVhdFooterChecksum(sFooter, sizeof(*sFooter)); sFooter->Checksum = NtoHl(saved_sum); if ((sum != saved_sum) || (memcmp("conectix", sFooter->Cookie, sizeof(sFooter->Cookie)))) { Return = EINVAL; /* File Corrupt */ goto Return_Cleanup; } if (ReadFilePosition(File, &sHeader, sizeof(sHeader), NULL, (uint64)0)) { Return = errno; goto Return_Cleanup; } if ((NtoHl(sFooter->DiskType) != VHD_DT_Dynamic) && (NtoHl(sFooter->DiskType) != VHD_DT_Differencing) && (NtoHl(sFooter->DiskType) != VHD_DT_Fixed)) { Return = EINVAL; /* File Corrupt */ goto Return_Cleanup; } if (((NtoHl(sFooter->DiskType) == VHD_DT_Dynamic) || (NtoHl(sFooter->DiskType) == VHD_DT_Differencing)) && memcmp(sFooter, &sHeader, sizeof(sHeader))) { Return = EINVAL; /* File Corrupt */ goto Return_Cleanup; } if ((sDynamic) && ((NtoHl(sFooter->DiskType) == VHD_DT_Dynamic) || (NtoHl(sFooter->DiskType) == VHD_DT_Differencing))) { if (ReadFilePosition(File, sDynamic, sizeof (*sDynamic), NULL, NtoHll (sFooter->DataOffset))) { Return = errno; goto Return_Cleanup; } saved_sum = NtoHl (sDynamic->Checksum); sDynamic->Checksum = 0; sum = CalculateVhdFooterChecksum (sDynamic, sizeof(*sDynamic)); sDynamic->Checksum = NtoHl (saved_sum); if ((sum != saved_sum) || (memcmp ("cxsparse", sDynamic->Cookie, sizeof (sDynamic->Cookie)))) { Return = errno; goto Return_Cleanup; } if (aBAT) { *aBAT = (uint32*) malloc(512*((sizeof(**aBAT)*NtoHl(sDynamic->MaxTableEntries)+511)/512)); if (ReadFilePosition(File, *aBAT, sizeof (**aBAT)*NtoHl(sDynamic->MaxTableEntries), NULL, NtoHll (sDynamic->TableOffset))) { Return = EINVAL; /* File Corrupt */ goto Return_Cleanup; } } if (szParentVHDPath && ParentVHDPathSize) { VHD_Footer sParentFooter; memset (szParentVHDPath, '\0', ParentVHDPathSize); if (NtoHl (sFooter->DiskType) == VHD_DT_Differencing) { size_t i, j; for (j=0; j<8; ++j) { uint8 *Pdata; uint32 PdataSize; char ParentName[512]; char CheckPath[512]; uint32 ParentModificationTime; if ('\0' == sDynamic->ParentLocatorEntries[j].PlatformCode[0]) continue; memset (ParentName, '\0', sizeof(ParentName)); memset (CheckPath, '\0', sizeof(CheckPath)); PdataSize = NtoHl(sDynamic->ParentLocatorEntries[j].PlatformDataSpace); Pdata = (uint8*) calloc (1, PdataSize+2); if (!Pdata) continue; if (ReadFilePosition(File, Pdata, PdataSize, NULL, NtoHll (sDynamic->ParentLocatorEntries[j].PlatformDataOffset))) { free (Pdata); continue; } for (i=0; i<NtoHl(sDynamic->ParentLocatorEntries[j].PlatformDataLength); i+=2) if ((Pdata[i] == '\0') && (Pdata[i+1] == '\0')) { ParentName[i/2] = '\0'; break; } else ParentName[i/2] = Pdata[i] ? Pdata[i] : Pdata[i+1]; free (Pdata); if (0 == memcmp (sDynamic->ParentLocatorEntries[j].PlatformCode, "W2ku", 4)) strncpy (CheckPath, ParentName, sizeof (CheckPath)-1); else if (0 == memcmp (sDynamic->ParentLocatorEntries[j].PlatformCode, "W2ru", 4)) { const char *c; if ((c = strrchr (szVHDPath, '\\'))) { memcpy (CheckPath, szVHDPath, c-szVHDPath+1); strncpy (CheckPath+strlen(CheckPath), ParentName, sizeof (CheckPath)-(strlen (CheckPath)+1)); } } VhdPathToHostPath (CheckPath, CheckPath, sizeof (CheckPath)); if (0 == GetVHDFooter(CheckPath, &sParentFooter, NULL, NULL, &ParentModificationTime, NULL, 0)) { if ((0 == memcmp (sDynamic->ParentUniqueID, sParentFooter.UniqueID, sizeof (sParentFooter.UniqueID))) && ((sDynamic->ParentTimeStamp == ParentModificationTime) || ((NtoHl(sDynamic->ParentTimeStamp)-NtoHl(ParentModificationTime)) == 3600) || (sim_switches & SWMASK ('O')))) strncpy (szParentVHDPath, CheckPath, ParentVHDPathSize); else { if (0 != memcmp (sDynamic->ParentUniqueID, sParentFooter.UniqueID, sizeof (sParentFooter.UniqueID))) sim_printf ("Error Invalid Parent VHD '%s' for Differencing VHD: %s\n", CheckPath, szVHDPath); else sim_printf ("Error Parent VHD '%s' has been modified since Differencing VHD: %s was created\n", CheckPath, szVHDPath); Return = EINVAL; /* File Corrupt/Invalid */ } break; } else { struct stat statb; if (0 == stat (CheckPath, &statb)) { sim_printf ("Parent VHD '%s' corrupt for Differencing VHD: %s\n", CheckPath, szVHDPath); Return = EBADF; /* File Corrupt/Invalid */ break; } } } if (!*szParentVHDPath) { if (Return != EINVAL) /* File Not Corrupt? */ sim_printf ("Missing Parent VHD for Differencing VHD: %s\n", szVHDPath); Return = EBADF; } } } } Return_Cleanup: if (File) fclose(File); if (aBAT && (0 != Return)) { free (*aBAT); *aBAT = NULL; } return errno = Return; } struct VHD_IOData { VHD_Footer Footer; VHD_DynamicDiskHeader Dynamic; uint32 *BAT; FILE *File; char ParentVHDPath[512]; struct VHD_IOData *Parent; }; static t_stat sim_vhd_disk_implemented (void) { return SCPE_OK; } static t_stat sim_vhd_disk_set_dtype (FILE *f, const char *dtype) { VHDHANDLE hVHD = (VHDHANDLE)f; int Status = 0; memset (hVHD->Footer.DriveType, '\0', sizeof hVHD->Footer.DriveType); memcpy (hVHD->Footer.DriveType, dtype, ((1+strlen (dtype)) < sizeof (hVHD->Footer.DriveType)) ? (1+strlen (dtype)) : sizeof (hVHD->Footer.DriveType)); hVHD->Footer.Checksum = 0; hVHD->Footer.Checksum = NtoHl (CalculateVhdFooterChecksum (&hVHD->Footer, sizeof(hVHD->Footer))); if (NtoHl (hVHD->Footer.DiskType) == VHD_DT_Fixed) { if (WriteFilePosition(hVHD->File, &hVHD->Footer, sizeof(hVHD->Footer), NULL, NtoHll (hVHD->Footer.CurrentSize))) Status = errno; goto Cleanup_Return; } else { uint64 position; position = sim_fsize_ex (hVHD->File); if (((int64)position) == -1) { Status = errno; goto Cleanup_Return; } position -= sizeof(hVHD->Footer); /* Update both copies on a dynamic disk */ if (WriteFilePosition(hVHD->File, &hVHD->Footer, sizeof(hVHD->Footer), NULL, (uint64)0)) { Status = errno; goto Cleanup_Return; } if (WriteFilePosition(hVHD->File, &hVHD->Footer, sizeof(hVHD->Footer), NULL, position)) { Status = errno; goto Cleanup_Return; } } Cleanup_Return: if (Status) return SCPE_IOERR; return SCPE_OK; } static const char *sim_vhd_disk_get_dtype (FILE *f) { VHDHANDLE hVHD = (VHDHANDLE)f; return (char *)(&hVHD->Footer.DriveType[0]); } static FILE *sim_vhd_disk_open (const char *szVHDPath, const char *DesiredAccess) { VHDHANDLE hVHD = (VHDHANDLE) calloc (1, sizeof(*hVHD)); int NeedUpdate = FALSE; int Status; if (!hVHD) return (FILE *)hVHD; Status = GetVHDFooter (szVHDPath, &hVHD->Footer, &hVHD->Dynamic, &hVHD->BAT, NULL, hVHD->ParentVHDPath, sizeof (hVHD->ParentVHDPath)); if (Status) goto Cleanup_Return; if (NtoHl (hVHD->Footer.DiskType) == VHD_DT_Differencing) { uint32 ParentModifiedTimeStamp; VHD_Footer ParentFooter; VHD_DynamicDiskHeader ParentDynamic; hVHD->Parent = (VHDHANDLE)sim_vhd_disk_open (hVHD->ParentVHDPath, "rb"); if (!hVHD->Parent) { Status = errno; goto Cleanup_Return; } Status = GetVHDFooter (hVHD->ParentVHDPath, &ParentFooter, &ParentDynamic, NULL, &ParentModifiedTimeStamp, NULL, 0); if (Status) goto Cleanup_Return; if ((0 != memcmp (hVHD->Dynamic.ParentUniqueID, ParentFooter.UniqueID, sizeof (ParentFooter.UniqueID))) || (ParentModifiedTimeStamp != hVHD->Dynamic.ParentTimeStamp)) { if (sim_switches & SWMASK ('O')) { /* OVERRIDE consistency checks? */ if ((sim_switches & SWMASK ('U')) && /* FIX (UPDATE) consistency checks AND */ (strchr (DesiredAccess, '+'))) { /* open for write/update? */ memcpy (hVHD->Dynamic.ParentUniqueID, ParentFooter.UniqueID, sizeof (ParentFooter.UniqueID)); hVHD->Dynamic.ParentTimeStamp = ParentModifiedTimeStamp; hVHD->Dynamic.Checksum = 0; hVHD->Dynamic.Checksum = NtoHl (CalculateVhdFooterChecksum (&hVHD->Dynamic, sizeof(hVHD->Dynamic))); NeedUpdate = TRUE; } } else { Status = EBADF; goto Cleanup_Return; } } } if (hVHD->Footer.SavedState) { Status = EAGAIN; /* Busy */ goto Cleanup_Return; } hVHD->File = sim_fopen (szVHDPath, DesiredAccess); if (!hVHD->File) { Status = errno; goto Cleanup_Return; } Cleanup_Return: if (Status) { sim_vhd_disk_close ((FILE *)hVHD); hVHD = NULL; } else { if (NeedUpdate) { /* Update Differencing Disk Header? */ if (WriteFilePosition(hVHD->File, &hVHD->Dynamic, sizeof (hVHD->Dynamic), NULL, NtoHll (hVHD->Footer.DataOffset))) { sim_vhd_disk_close ((FILE *)hVHD); hVHD = NULL; } } } errno = Status; return (FILE *)hVHD; } static t_stat WriteVirtualDiskSectors(VHDHANDLE hVHD, uint8 *buf, t_seccnt sects, t_seccnt *sectswritten, uint32 SectorSize, t_lba lba); static FILE *sim_vhd_disk_merge (const char *szVHDPath, char **ParentVHD) { VHDHANDLE hVHD = (VHDHANDLE) calloc (1, sizeof(*hVHD)); VHDHANDLE Parent = NULL; int Status; uint32 SectorSize, SectorsPerBlock, BlockSize, BlockNumber, BitMapBytes, BitMapSectors, BlocksToMerge, NeededBlock; uint64 BlockOffset; size_t BytesRead; t_seccnt SectorsWritten; void *BlockData = NULL; if (!hVHD) return (FILE *)hVHD; if (0 != (Status = GetVHDFooter (szVHDPath, &hVHD->Footer, &hVHD->Dynamic, &hVHD->BAT, NULL, hVHD->ParentVHDPath, sizeof (hVHD->ParentVHDPath)))) goto Cleanup_Return; if (NtoHl (hVHD->Footer.DiskType) != VHD_DT_Differencing) { Status = EINVAL; goto Cleanup_Return; } if (hVHD->Footer.SavedState) { Status = EAGAIN; /* Busy */ goto Cleanup_Return; } SectorSize = 512; BlockSize = NtoHl (hVHD->Dynamic.BlockSize); BlockData = malloc (BlockSize*SectorSize); if (NULL == BlockData) { Status = errno; goto Cleanup_Return; } Parent = (VHDHANDLE)sim_vhd_disk_open (hVHD->ParentVHDPath, "rb+"); if (!Parent) { Status = errno; goto Cleanup_Return; } hVHD->File = sim_fopen (szVHDPath, "rb"); if (!hVHD->File) { Status = errno; goto Cleanup_Return; } SectorsPerBlock = NtoHl (hVHD->Dynamic.BlockSize)/SectorSize; BitMapBytes = (7+(NtoHl (hVHD->Dynamic.BlockSize)/SectorSize))/8; BitMapSectors = (BitMapBytes+SectorSize-1)/SectorSize; for (BlockNumber=BlocksToMerge=0; BlockNumber< NtoHl (hVHD->Dynamic.MaxTableEntries); ++BlockNumber) { if (hVHD->BAT[BlockNumber] == VHD_BAT_FREE_ENTRY) continue; ++BlocksToMerge; } if (!sim_quiet) sim_printf ("Merging %s\ninto %s\n", szVHDPath, hVHD->ParentVHDPath); for (BlockNumber=NeededBlock=0; BlockNumber < NtoHl (hVHD->Dynamic.MaxTableEntries); ++BlockNumber) { uint32 BlockSectors = SectorsPerBlock; if (hVHD->BAT[BlockNumber] == VHD_BAT_FREE_ENTRY) continue; ++NeededBlock; BlockOffset = SectorSize*((uint64)(NtoHl (hVHD->BAT[BlockNumber]) + BitMapSectors)); if (((uint64)BlockNumber*SectorsPerBlock + BlockSectors) > ((uint64)NtoHll (hVHD->Footer.CurrentSize))/SectorSize) BlockSectors = (uint32)(((uint64)NtoHll (hVHD->Footer.CurrentSize))/SectorSize - (BlockNumber*SectorsPerBlock)); if (ReadFilePosition(hVHD->File, BlockData, SectorSize*BlockSectors, &BytesRead, BlockOffset)) break; if (WriteVirtualDiskSectors (Parent, (uint8*)BlockData, BlockSectors, &SectorsWritten, SectorSize, SectorsPerBlock*BlockNumber)) break; if (!sim_quiet) sim_printf ("Merged %dMB. %d%% complete.\r", (int)((((float)NeededBlock)*SectorsPerBlock)*SectorSize/1000000), (int)((((float)NeededBlock)*100)/BlocksToMerge)); hVHD->BAT[BlockNumber] = VHD_BAT_FREE_ENTRY; } if (BlockNumber < NtoHl (hVHD->Dynamic.MaxTableEntries)) { Status = errno; } else { Status = 0; if (!sim_quiet) sim_printf ("Merged %dMB. 100%% complete.\n", (int)((((float)NeededBlock)*SectorsPerBlock)*SectorSize/1000000)); fclose (hVHD->File); hVHD->File = NULL; (void)remove (szVHDPath); *ParentVHD = (char*) malloc (strlen (hVHD->ParentVHDPath)+1); strcpy (*ParentVHD, hVHD->ParentVHDPath); } Cleanup_Return: free (BlockData); if (hVHD->File) fclose (hVHD->File); if (Status) { free (hVHD->BAT); free (hVHD); hVHD = NULL; sim_vhd_disk_close ((FILE *)Parent); } else { free (hVHD->BAT); free (hVHD); hVHD = Parent; } errno = Status; return (FILE *)hVHD; } static int sim_vhd_disk_close (FILE *f) { VHDHANDLE hVHD = (VHDHANDLE)f; if (NULL != hVHD) { if (hVHD->Parent) sim_vhd_disk_close ((FILE *)hVHD->Parent); free (hVHD->BAT); if (hVHD->File) { fflush (hVHD->File); fclose (hVHD->File); } free (hVHD); return 0; } return -1; } static void sim_vhd_disk_flush (FILE *f) { VHDHANDLE hVHD = (VHDHANDLE)f; if ((NULL != hVHD) && (hVHD->File)) fflush (hVHD->File); } static t_offset sim_vhd_disk_size (FILE *f) { VHDHANDLE hVHD = (VHDHANDLE)f; return (t_offset)(NtoHll (hVHD->Footer.CurrentSize)); } #include <stdlib.h> #include <time.h> static void _rand_uuid_gen (void *uuidaddr) { int i; uint8 *b = (uint8 *)uuidaddr; uint32 timenow = (uint32)time (NULL); memcpy (uuidaddr, &timenow, sizeof (timenow)); srand ((unsigned)timenow); for (i=4; i<16; i++) { b[i] = (uint8)rand(); } } #if defined (_WIN32) static void uuid_gen (void *uuidaddr) { static RPC_STATUS (RPC_ENTRY *UuidCreate_c) (void *); if (!UuidCreate_c) { HINSTANCE hDll; hDll = LoadLibraryA("rpcrt4.dll"); UuidCreate_c = (RPC_STATUS (RPC_ENTRY *) (void *))GetProcAddress(hDll, "UuidCreate"); } if (UuidCreate_c) UuidCreate_c(uuidaddr); else _rand_uuid_gen (uuidaddr); } #elif defined (HAVE_DLOPEN) #include <dlfcn.h> static void uuid_gen (void *uuidaddr) { void (*uuid_generate_c) (void *) = NULL; void *handle; #define S__STR_QUOTE(tok) #tok #define S__STR(tok) S__STR_QUOTE(tok) handle = dlopen("libuuid." S__STR(HAVE_DLOPEN), RTLD_NOW|RTLD_GLOBAL); if (handle) uuid_generate_c = (void (*)(void *))((size_t)dlsym(handle, "uuid_generate")); if (uuid_generate_c) uuid_generate_c(uuidaddr); else _rand_uuid_gen (uuidaddr); if (handle) dlclose(handle); } #else static void uuid_gen (void *uuidaddr) { _rand_uuid_gen (uuidaddr); } #endif static VHDHANDLE CreateVirtualDisk(const char *szVHDPath, uint32 SizeInSectors, uint32 BlockSize, t_bool bFixedVHD) { VHD_Footer Footer; VHD_DynamicDiskHeader Dynamic; uint32 *BAT = NULL; time_t now; uint32 i; FILE *File = NULL; uint32 Status = 0; uint32 BytesPerSector = 512; uint64 SizeInBytes = ((uint64)SizeInSectors)*BytesPerSector; uint64 TableOffset; uint32 MaxTableEntries; VHDHANDLE hVHD = NULL; if (SizeInBytes > ((uint64)(1024*1024*1024))*2040) { Status = EFBIG; goto Cleanup_Return; } File = sim_fopen (szVHDPath, "rb"); if (File) { fclose (File); File = NULL; Status = EEXIST; goto Cleanup_Return; } File = sim_fopen (szVHDPath, "wb"); if (!File) { Status = errno; goto Cleanup_Return; } memset (&Footer, 0, sizeof(Footer)); memcpy (Footer.Cookie, "conectix", 8); Footer.Features = NtoHl (0x00000002);; Footer.FileFormatVersion = NtoHl (0x00010000);; Footer.DataOffset = NtoHll (bFixedVHD ? ((long long)-1) : (long long)(sizeof(Footer))); time (&now); Footer.TimeStamp = NtoHl ((uint32)(now-946684800)); memcpy (Footer.CreatorApplication, "simh", 4); Footer.CreatorVersion = NtoHl (0x00040000); memcpy (Footer.CreatorHostOS, "Wi2k", 4); Footer.OriginalSize = NtoHll (SizeInBytes); Footer.CurrentSize = NtoHll (SizeInBytes); uuid_gen (Footer.UniqueID); Footer.DiskType = NtoHl (bFixedVHD ? VHD_DT_Fixed : VHD_DT_Dynamic); Footer.DiskGeometry = NtoHl (0xFFFF10FF); if (1) { /* CHS Calculation */ uint32 totalSectors = (uint32)(SizeInBytes/BytesPerSector);/* Total data sectors present in the disk image */ uint32 cylinders; /* Number of cylinders present on the disk */ uint32 heads; /* Number of heads present on the disk */ uint32 sectorsPerTrack; /* Sectors per track on the disk */ uint32 cylinderTimesHeads; /* Cylinders x heads */ if (totalSectors > 65535 * 16 * 255) totalSectors = 65535 * 16 * 255; if (totalSectors >= 65535 * 16 * 63) { sectorsPerTrack = 255; heads = 16; cylinderTimesHeads = totalSectors / sectorsPerTrack; } else { sectorsPerTrack = 17; cylinderTimesHeads = totalSectors / sectorsPerTrack; heads = (cylinderTimesHeads + 1023) / 1024; if (heads < 4) heads = 4; if (cylinderTimesHeads >= (heads * 1024) || heads > 16) { sectorsPerTrack = 31; heads = 16; cylinderTimesHeads = totalSectors / sectorsPerTrack; } if (cylinderTimesHeads >= (heads * 1024)) { sectorsPerTrack = 63; heads = 16; cylinderTimesHeads = totalSectors / sectorsPerTrack; } } cylinders = cylinderTimesHeads / heads; Footer.DiskGeometry = NtoHl ((cylinders<<16)|(heads<<8)|sectorsPerTrack); } Footer.Checksum = NtoHl (CalculateVhdFooterChecksum(&Footer, sizeof(Footer))); if (bFixedVHD) { if (WriteFilePosition(File, &Footer, sizeof(Footer), NULL, SizeInBytes)) Status = errno; goto Cleanup_Return; } /* Dynamic Disk */ memset (&Dynamic, 0, sizeof(Dynamic)); memcpy (Dynamic.Cookie, "cxsparse", 8); Dynamic.DataOffset = NtoHll ((uint64)0xFFFFFFFFFFFFFFFFLL); TableOffset = NtoHll(Footer.DataOffset)+sizeof(Dynamic); Dynamic.TableOffset = NtoHll (TableOffset); Dynamic.HeaderVersion = NtoHl (0x00010000); if (0 == BlockSize) BlockSize = 2*1024*1024; Dynamic.BlockSize = NtoHl (BlockSize); MaxTableEntries = (uint32)((SizeInBytes+BlockSize-1)/BlockSize); Dynamic.MaxTableEntries = NtoHl (MaxTableEntries); Dynamic.Checksum = NtoHl (CalculateVhdFooterChecksum(&Dynamic, sizeof(Dynamic))); BAT = (uint32*) malloc (BytesPerSector*((MaxTableEntries*sizeof(*BAT)+BytesPerSector-1)/BytesPerSector)); memset (BAT, 0, BytesPerSector*((MaxTableEntries*sizeof(*BAT)+BytesPerSector-1)/BytesPerSector)); for (i=0; i<MaxTableEntries; ++i) BAT[i] = VHD_BAT_FREE_ENTRY; if (WriteFilePosition(File, &Footer, sizeof(Footer), NULL, 0)) { Status = errno; goto Cleanup_Return; } if (WriteFilePosition(File, &Dynamic, sizeof(Dynamic), NULL, NtoHll(Footer.DataOffset))) { Status = errno; goto Cleanup_Return; } if (WriteFilePosition(File, BAT, BytesPerSector*((MaxTableEntries*sizeof(*BAT)+BytesPerSector-1)/BytesPerSector), NULL, NtoHll(Dynamic.TableOffset))) { Status = errno; goto Cleanup_Return; } if (WriteFilePosition(File, &Footer, sizeof(Footer), NULL, NtoHll(Dynamic.TableOffset)+BytesPerSector*((MaxTableEntries*sizeof(*BAT)+BytesPerSector-1)/BytesPerSector))) { Status = errno; goto Cleanup_Return; } Cleanup_Return: free (BAT); if (File) fclose (File); if (Status) { if (Status != EEXIST) (void)remove (szVHDPath); } else { hVHD = (VHDHANDLE)sim_vhd_disk_open (szVHDPath, "rb+"); if (!hVHD) Status = errno; } errno = Status; return hVHD; } #if defined(__CYGWIN__) || defined(VMS) || defined(__APPLE__) || defined(__linux) || defined(__linux__) || defined(__unix__) #include <unistd.h> #endif static void ExpandToFullPath (const char *szFileSpec, char *szFullFileSpecBuffer, size_t BufferSize) { char *c; #ifdef _WIN32 for (c = strchr (szFullFileSpecBuffer, '/'); c; c = strchr (szFullFileSpecBuffer, '/')) *c = '\\'; GetFullPathNameA (szFileSpec, (DWORD)BufferSize, szFullFileSpecBuffer, NULL); for (c = strchr (szFullFileSpecBuffer, '\\'); c; c = strchr (szFullFileSpecBuffer, '\\')) *c = '/'; #else char buffer[PATH_MAX]; char *wd = getcwd(buffer, PATH_MAX); if ((szFileSpec[0] != '/') || (strchr (szFileSpec, ':'))) snprintf (szFullFileSpecBuffer, BufferSize, "%s/%s", wd, szFileSpec); else strncpy (szFullFileSpecBuffer, szFileSpec, BufferSize); if ((c = strstr (szFullFileSpecBuffer, "]/"))) memmove (c+1, c+2, strlen(c+2)+1); memset (szFullFileSpecBuffer + strlen (szFullFileSpecBuffer), 0, BufferSize - strlen (szFullFileSpecBuffer)); #endif } static char * HostPathToVhdPath (const char *szHostPath, char *szVhdPath, size_t VhdPathSize) { char *c, *d; strncpy (szVhdPath, szHostPath, VhdPathSize-1); if ((szVhdPath[1] == ':') && islower(szVhdPath[0])) szVhdPath[0] = toupper(szVhdPath[0]); szVhdPath[VhdPathSize-1] = '\0'; if ((c = strrchr (szVhdPath, ']'))) { *c = '\0'; if (!(d = strchr (szVhdPath, '['))) return d; *d = '/'; while ((d = strchr (d, '.'))) *d = '/'; *c = '/'; } while ((c = strchr (szVhdPath, '/'))) *c = '\\'; for (c = strstr (szVhdPath, "\\.\\"); c; c = strstr (szVhdPath, "\\.\\")) memmove (c, c+2, strlen(c+2)+1); for (c = strstr (szVhdPath, "\\\\"); c; c = strstr (szVhdPath, "\\\\")) memmove (c, c+1, strlen(c+1)+1); while ((c = strstr (szVhdPath, "\\..\\"))) { *c = '\0'; d = strrchr (szVhdPath, '\\'); if (d) memmove (d, c+3, strlen(c+3)+1); else return d; } memset (szVhdPath + strlen (szVhdPath), 0, VhdPathSize - strlen (szVhdPath)); return szVhdPath; } static char * VhdPathToHostPath (const char *szVhdPath, char *szHostPath, size_t HostPathSize) { char *c; char *d = szHostPath; strncpy (szHostPath, szVhdPath, HostPathSize-1); szHostPath[HostPathSize-1] = '\0'; #if defined(VMS) c = strchr (szVhdPath, ':'); if (*(c+1) != '\\') return NULL; *(c+1) = '['; d = strrchr (c+2, '\\'); if (d) { *d = ']'; while ((d = strrchr (c+2, '\\'))) *d = '.'; } else return NULL; #else while ((c = strchr (d, '\\'))) *c = '/'; #endif memset (szHostPath + strlen (szHostPath), 0, HostPathSize - strlen (szHostPath)); return szHostPath; } static VHDHANDLE CreateDifferencingVirtualDisk(const char *szVHDPath, const char *szParentVHDPath) { uint32 BytesPerSector = 512; VHDHANDLE hVHD = NULL; VHD_Footer ParentFooter; VHD_DynamicDiskHeader ParentDynamic; uint32 ParentTimeStamp; uint32 Status = 0; char *RelativeParentVHDPath = NULL; char *FullParentVHDPath = NULL; char *RelativeParentVHDPathUnicode = NULL; char *FullParentVHDPathUnicode = NULL; char *FullVHDPath = NULL; char *TempPath = NULL; size_t i, RelativeMatch, UpDirectories, LocatorsWritten = 0; int64 LocatorPosition; if ((Status = GetVHDFooter (szParentVHDPath, &ParentFooter, &ParentDynamic, NULL, &ParentTimeStamp, NULL, 0))) goto Cleanup_Return; hVHD = CreateVirtualDisk (szVHDPath, (uint32)(NtoHll(ParentFooter.CurrentSize)/BytesPerSector), NtoHl(ParentDynamic.BlockSize), FALSE); if (!hVHD) { Status = errno; goto Cleanup_Return; } LocatorPosition = ((sizeof (hVHD->Footer) + BytesPerSector - 1)/BytesPerSector + (sizeof (hVHD->Dynamic) + BytesPerSector - 1)/BytesPerSector)*BytesPerSector; hVHD->Dynamic.Checksum = 0; RelativeParentVHDPath = (char*) calloc (1, BytesPerSector+2); FullParentVHDPath = (char*) calloc (1, BytesPerSector+2); RelativeParentVHDPathUnicode = (char*) calloc (1, BytesPerSector+2); FullParentVHDPathUnicode = (char*) calloc (1, BytesPerSector+2); FullVHDPath = (char*) calloc (1, BytesPerSector+2); TempPath = (char*) calloc (1, BytesPerSector+2); ExpandToFullPath (szParentVHDPath, TempPath, BytesPerSector); HostPathToVhdPath (TempPath, FullParentVHDPath, BytesPerSector); for (i=0; i < strlen (FullParentVHDPath); i++) hVHD->Dynamic.ParentUnicodeName[i*2+1] = FullParentVHDPath[i]; /* Big Endian Unicode */ for (i=0; i < strlen (FullParentVHDPath); i++) FullParentVHDPathUnicode[i*2] = FullParentVHDPath[i]; /* Little Endian Unicode */ ExpandToFullPath (szVHDPath, TempPath, BytesPerSector); HostPathToVhdPath (TempPath, FullVHDPath, BytesPerSector); for (i=0, RelativeMatch=UpDirectories=0; i<strlen(FullVHDPath); i++) if (FullVHDPath[i] == '\\') { if (memcmp (FullVHDPath, FullParentVHDPath, i+1)) ++UpDirectories; else RelativeMatch = i; } if (RelativeMatch) { char UpDir[4] = "..\\"; UpDir[2] = FullParentVHDPath[RelativeMatch]; if (UpDirectories) for (i=0; i<UpDirectories; i++) strcpy (RelativeParentVHDPath+strlen (RelativeParentVHDPath), UpDir); else strcpy (RelativeParentVHDPath+strlen (RelativeParentVHDPath), UpDir+1); strcpy (RelativeParentVHDPath+strlen (RelativeParentVHDPath), &FullParentVHDPath[RelativeMatch+1]); } for (i=0; i < strlen(RelativeParentVHDPath); i++) RelativeParentVHDPathUnicode[i*2] = RelativeParentVHDPath[i]; hVHD->Dynamic.ParentTimeStamp = ParentTimeStamp; memcpy (hVHD->Dynamic.ParentUniqueID, ParentFooter.UniqueID, sizeof (hVHD->Dynamic.ParentUniqueID)); /* There are two potential parent locators on current vhds */ memcpy (hVHD->Dynamic.ParentLocatorEntries[0].PlatformCode, "W2ku", 4); hVHD->Dynamic.ParentLocatorEntries[0].PlatformDataSpace = NtoHl (BytesPerSector); hVHD->Dynamic.ParentLocatorEntries[0].PlatformDataLength = NtoHl ((uint32)(2*strlen(FullParentVHDPath))); hVHD->Dynamic.ParentLocatorEntries[0].Reserved = 0; hVHD->Dynamic.ParentLocatorEntries[0].PlatformDataOffset = NtoHll (LocatorPosition+LocatorsWritten*BytesPerSector); ++LocatorsWritten; if (RelativeMatch) { memcpy (hVHD->Dynamic.ParentLocatorEntries[1].PlatformCode, "W2ru", 4); hVHD->Dynamic.ParentLocatorEntries[1].PlatformDataSpace = NtoHl (BytesPerSector); hVHD->Dynamic.ParentLocatorEntries[1].PlatformDataLength = NtoHl ((uint32)(2*strlen(RelativeParentVHDPath))); hVHD->Dynamic.ParentLocatorEntries[1].Reserved = 0; hVHD->Dynamic.ParentLocatorEntries[1].PlatformDataOffset = NtoHll (LocatorPosition+LocatorsWritten*BytesPerSector); ++LocatorsWritten; } hVHD->Dynamic.TableOffset = NtoHll (((LocatorPosition+LocatorsWritten*BytesPerSector + VHD_DATA_BLOCK_ALIGNMENT - 1)/VHD_DATA_BLOCK_ALIGNMENT)*VHD_DATA_BLOCK_ALIGNMENT); hVHD->Dynamic.Checksum = 0; hVHD->Dynamic.Checksum = NtoHl (CalculateVhdFooterChecksum (&hVHD->Dynamic, sizeof(hVHD->Dynamic))); hVHD->Footer.Checksum = 0; hVHD->Footer.DiskType = NtoHl (VHD_DT_Differencing); memcpy (hVHD->Footer.DriveType, ParentFooter.DriveType, sizeof (hVHD->Footer.DriveType)); hVHD->Footer.Checksum = NtoHl (CalculateVhdFooterChecksum (&hVHD->Footer, sizeof(hVHD->Footer))); if (WriteFilePosition (hVHD->File, &hVHD->Footer, sizeof (hVHD->Footer), NULL, 0)) { Status = errno; goto Cleanup_Return; } if (WriteFilePosition (hVHD->File, &hVHD->Dynamic, sizeof (hVHD->Dynamic), NULL, NtoHll (hVHD->Footer.DataOffset))) { Status = errno; goto Cleanup_Return; } if (WriteFilePosition (hVHD->File, hVHD->BAT, BytesPerSector*((NtoHl (hVHD->Dynamic.MaxTableEntries)*sizeof(*hVHD->BAT)+BytesPerSector-1)/BytesPerSector), NULL, NtoHll (hVHD->Dynamic.TableOffset))) { Status = errno; goto Cleanup_Return; } if (WriteFilePosition (hVHD->File, &hVHD->Footer, sizeof (hVHD->Footer), NULL, NtoHll (hVHD->Dynamic.TableOffset)+BytesPerSector*((NtoHl (hVHD->Dynamic.MaxTableEntries)*sizeof(*hVHD->BAT)+BytesPerSector-1)/BytesPerSector))) { Status = errno; goto Cleanup_Return; } if (hVHD->Dynamic.ParentLocatorEntries[0].PlatformDataLength) if (WriteFilePosition (hVHD->File, FullParentVHDPathUnicode, BytesPerSector, NULL, NtoHll (hVHD->Dynamic.ParentLocatorEntries[0].PlatformDataOffset))) { Status = errno; goto Cleanup_Return; } if (hVHD->Dynamic.ParentLocatorEntries[1].PlatformDataLength) if (WriteFilePosition (hVHD->File, RelativeParentVHDPathUnicode, BytesPerSector, NULL, NtoHll (hVHD->Dynamic.ParentLocatorEntries[1].PlatformDataOffset))) { Status = errno; goto Cleanup_Return; } Cleanup_Return: free (RelativeParentVHDPath); free (FullParentVHDPath); free (RelativeParentVHDPathUnicode); free (FullParentVHDPathUnicode); free (FullVHDPath); free (TempPath); sim_vhd_disk_close ((FILE *)hVHD); hVHD = NULL; if (Status) { if ((EEXIST != Status) && (ENOENT != Status)) (void)remove (szVHDPath); } else { hVHD = (VHDHANDLE)sim_vhd_disk_open (szVHDPath, "rb+"); if (!hVHD) Status = errno; } errno = Status; return hVHD; } static FILE *sim_vhd_disk_create (const char *szVHDPath, t_offset desiredsize) { return (FILE *)CreateVirtualDisk (szVHDPath, (uint32)(desiredsize/512), 0, (sim_switches & SWMASK ('X'))); } static FILE *sim_vhd_disk_create_diff (const char *szVHDPath, const char *szParentVHDPath) { return (FILE *)CreateDifferencingVirtualDisk (szVHDPath, szParentVHDPath); } static t_stat ReadVirtualDiskSectors(VHDHANDLE hVHD, uint8 *buf, t_seccnt sects, t_seccnt *sectsread, uint32 SectorSize, t_lba lba) { uint64 BlockOffset = ((uint64)lba)*SectorSize; uint32 BlocksRead = 0; uint32 SectorsInRead; size_t BytesRead = 0; if (!hVHD || (hVHD->File == NULL)) { errno = EBADF; return SCPE_IOERR; } if ((BlockOffset + sects*SectorSize) > (uint64)NtoHll (hVHD->Footer.CurrentSize)) { errno = ERANGE; return SCPE_IOERR; } if (NtoHl (hVHD->Footer.DiskType) == VHD_DT_Fixed) { if (ReadFilePosition(hVHD->File, buf, sects*SectorSize, &BytesRead, BlockOffset)) { if (sectsread) *sectsread = (t_seccnt)(BytesRead/SectorSize); return SCPE_IOERR; } if (sectsread) *sectsread /= SectorSize; return SCPE_OK; } /* We are now dealing with a Dynamically expanding or differencing disk */ while (sects) { uint32 SectorsPerBlock = NtoHl (hVHD->Dynamic.BlockSize)/SectorSize; uint64 BlockNumber = lba/SectorsPerBlock; uint32 BitMapBytes = (7+(NtoHl (hVHD->Dynamic.BlockSize)/SectorSize))/8; uint32 BitMapSectors = (BitMapBytes+SectorSize-1)/SectorSize; SectorsInRead = SectorsPerBlock - lba%SectorsPerBlock; if (SectorsInRead > sects) SectorsInRead = sects; if (hVHD->BAT[BlockNumber] == VHD_BAT_FREE_ENTRY) { if (!hVHD->Parent) memset (buf, 0, SectorSize*SectorsInRead); else { if (ReadVirtualDiskSectors(hVHD->Parent, buf, SectorsInRead, NULL, SectorSize, lba)) { if (sectsread) *sectsread = BlocksRead; return FALSE; } } } else { BlockOffset = SectorSize*((uint64)(NtoHl (hVHD->BAT[BlockNumber]) + lba%SectorsPerBlock + BitMapSectors)); if (ReadFilePosition(hVHD->File, buf, SectorsInRead*SectorSize, NULL, BlockOffset)) { if (sectsread) *sectsread = BlocksRead; return SCPE_IOERR; } } sects -= SectorsInRead; buf = (uint8 *)(((char *)buf) + SectorSize*SectorsInRead); lba += SectorsInRead; BlocksRead += SectorsInRead; } if (sectsread) *sectsread = BlocksRead; return SCPE_OK; } static t_stat sim_vhd_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects) { VHDHANDLE hVHD = (VHDHANDLE)uptr->fileref; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; return ReadVirtualDiskSectors(hVHD, buf, sects, sectsread, ctx->sector_size, lba); } static t_stat sim_vhd_disk_clearerr (UNIT *uptr) { VHDHANDLE hVHD = (VHDHANDLE)uptr->fileref; clearerr (hVHD->File); return SCPE_OK; } static t_bool BufferIsZeros(void *Buffer, size_t BufferSize) { size_t i; char *c = (char *)Buffer; for (i=0; i<BufferSize; ++i) if (c[i]) return FALSE; return TRUE; } static t_stat WriteVirtualDiskSectors(VHDHANDLE hVHD, uint8 *buf, t_seccnt sects, t_seccnt *sectswritten, uint32 SectorSize, t_lba lba) { uint64 BlockOffset = ((uint64)lba)*SectorSize; uint32 BlocksWritten = 0; uint32 SectorsInWrite; size_t BytesWritten = 0; if (!hVHD || !hVHD->File) { errno = EBADF; return SCPE_IOERR; } if ((BlockOffset + sects*SectorSize) > (uint64)NtoHll(hVHD->Footer.CurrentSize)) { errno = ERANGE; return SCPE_IOERR; } if (NtoHl(hVHD->Footer.DiskType) == VHD_DT_Fixed) { if (WriteFilePosition(hVHD->File, buf, sects*SectorSize, &BytesWritten, BlockOffset)) { if (sectswritten) *sectswritten = (t_seccnt)(BytesWritten/SectorSize); return SCPE_IOERR; } if (sectswritten) *sectswritten /= SectorSize; return SCPE_OK; } /* We are now dealing with a Dynamically expanding or differencing disk */ while (sects) { uint32 SectorsPerBlock = NtoHl(hVHD->Dynamic.BlockSize)/SectorSize; uint64 BlockNumber = lba/SectorsPerBlock; uint32 BitMapBytes = (7+(NtoHl(hVHD->Dynamic.BlockSize)/SectorSize))/8; uint32 BitMapSectors = (BitMapBytes+SectorSize-1)/SectorSize; if (BlockNumber >= NtoHl(hVHD->Dynamic.MaxTableEntries)) { if (sectswritten) *sectswritten = BlocksWritten; return SCPE_EOF; } SectorsInWrite = 1; if (hVHD->BAT[BlockNumber] == VHD_BAT_FREE_ENTRY) { uint8 *BitMap = NULL; uint32 BitMapBufferSize = VHD_DATA_BLOCK_ALIGNMENT; uint8 *BitMapBuffer = NULL; void *BlockData = NULL; uint8 *BATUpdateBufferAddress; uint32 BATUpdateBufferSize; uint64 BATUpdateStorageAddress; if (!hVHD->Parent && BufferIsZeros(buf, SectorSize)) goto IO_Done; /* Need to allocate a new Data Block. */ BlockOffset = sim_fsize_ex (hVHD->File); if (((int64)BlockOffset) == -1) return SCPE_IOERR; if (BitMapSectors*SectorSize > BitMapBufferSize) BitMapBufferSize = BitMapSectors*SectorSize; BitMapBuffer = (uint8 *)calloc(1, BitMapBufferSize + SectorSize*SectorsPerBlock); if (BitMapBufferSize > BitMapSectors*SectorSize) BitMap = BitMapBuffer + BitMapBufferSize-BitMapBytes; else BitMap = BitMapBuffer; memset(BitMap, 0xFF, BitMapBytes); BlockOffset -= sizeof(hVHD->Footer); if (0 == (BlockOffset & ~(VHD_DATA_BLOCK_ALIGNMENT-1))) { // Already aligned, so use padded BitMapBuffer if (WriteFilePosition(hVHD->File, BitMapBuffer, BitMapBufferSize + SectorSize*SectorsPerBlock, NULL, BlockOffset)) { free (BitMapBuffer); return SCPE_IOERR; } BlockOffset += BitMapBufferSize; } else { // align the data portion of the block to the desired alignment // compute the address of the data portion of the block BlockOffset += BitMapSectors*SectorSize; // round up this address to the desired alignment BlockOffset += VHD_DATA_BLOCK_ALIGNMENT-1; BlockOffset &= ~(VHD_DATA_BLOCK_ALIGNMENT-1); BlockOffset -= BitMapSectors*SectorSize; if (WriteFilePosition(hVHD->File, BitMap, SectorSize * (BitMapSectors + SectorsPerBlock), NULL, BlockOffset)) { free (BitMapBuffer); return SCPE_IOERR; } BlockOffset += BitMapSectors*SectorSize; } free(BitMapBuffer); BitMapBuffer = BitMap = NULL; /* the BAT block address is the beginning of the block bitmap */ BlockOffset -= BitMapSectors*SectorSize; hVHD->BAT[BlockNumber] = NtoHl((uint32)(BlockOffset/SectorSize)); BlockOffset += SectorSize * (SectorsPerBlock + BitMapSectors); if (WriteFilePosition(hVHD->File, &hVHD->Footer, sizeof(hVHD->Footer), NULL, BlockOffset)) goto Fatal_IO_Error; /* Since a large VHD can have a pretty large BAT, and we've only changed one longword bat entry in the current BAT, we write just the aligned sector which contains the updated BAT entry */ BATUpdateBufferAddress = (uint8 *)hVHD->BAT - (size_t)NtoHll(hVHD->Dynamic.TableOffset) + (size_t)((((size_t)&hVHD->BAT[BlockNumber]) - (size_t)hVHD->BAT + (size_t)NtoHll(hVHD->Dynamic.TableOffset)) & ~(VHD_DATA_BLOCK_ALIGNMENT-1)); /* If the starting of the BAT isn't on a VHD_DATA_BLOCK_ALIGNMENT boundary and we've just updated a BAT entry early in the array, the buffer computed address might be before the start of the BAT table. If so, only write the BAT data needed */ if (BATUpdateBufferAddress < (uint8 *)hVHD->BAT) { BATUpdateBufferAddress = (uint8 *)hVHD->BAT; BATUpdateBufferSize = (uint32)((((size_t)&hVHD->BAT[BlockNumber]) - (size_t)hVHD->BAT) + 512) & ~511; BATUpdateStorageAddress = NtoHll(hVHD->Dynamic.TableOffset); } else { BATUpdateBufferSize = VHD_DATA_BLOCK_ALIGNMENT; BATUpdateStorageAddress = NtoHll(hVHD->Dynamic.TableOffset) + BATUpdateBufferAddress - ((uint8 *)hVHD->BAT); } /* If the total BAT is smaller than one VHD_DATA_BLOCK_ALIGNMENT, then be sure to only write out the BAT data */ if ((size_t)(BATUpdateBufferAddress - (uint8 *)hVHD->BAT + BATUpdateBufferSize) > 512*((sizeof(*hVHD->BAT)*NtoHl(hVHD->Dynamic.MaxTableEntries) + 511)/512)) BATUpdateBufferSize = (uint32)(512*((sizeof(*hVHD->BAT)*NtoHl(hVHD->Dynamic.MaxTableEntries) + 511)/512) - (BATUpdateBufferAddress - ((uint8 *)hVHD->BAT))); if (WriteFilePosition(hVHD->File, BATUpdateBufferAddress, BATUpdateBufferSize, NULL, BATUpdateStorageAddress)) goto Fatal_IO_Error; if (hVHD->Parent) { /* Need to populate data block contents from parent VHD */ uint32 BlockSectors = SectorsPerBlock; BlockData = malloc(SectorsPerBlock*SectorSize); if (((lba/SectorsPerBlock)*SectorsPerBlock + BlockSectors) > ((uint64)NtoHll (hVHD->Footer.CurrentSize))/SectorSize) BlockSectors = (uint32)(((uint64)NtoHll (hVHD->Footer.CurrentSize))/SectorSize - (lba/SectorsPerBlock)*SectorsPerBlock); if (ReadVirtualDiskSectors(hVHD->Parent, (uint8*) BlockData, BlockSectors, NULL, SectorSize, (lba/SectorsPerBlock)*SectorsPerBlock)) goto Fatal_IO_Error; if (WriteVirtualDiskSectors(hVHD, (uint8*) BlockData, BlockSectors, NULL, SectorSize, (lba/SectorsPerBlock)*SectorsPerBlock)) goto Fatal_IO_Error; free(BlockData); } continue; Fatal_IO_Error: free (BitMap); free (BlockData); fclose (hVHD->File); hVHD->File = NULL; return SCPE_IOERR; } else { BlockOffset = 512*((uint64)(NtoHl(hVHD->BAT[BlockNumber]) + lba%SectorsPerBlock + BitMapSectors)); SectorsInWrite = SectorsPerBlock - lba%SectorsPerBlock; if (SectorsInWrite > sects) SectorsInWrite = sects; if (WriteFilePosition(hVHD->File, buf, SectorsInWrite*SectorSize, NULL, BlockOffset)) { if (sectswritten) *sectswritten = BlocksWritten; return SCPE_IOERR; } } IO_Done: sects -= SectorsInWrite; buf = (uint8 *)(((char *)buf) + SectorsInWrite*SectorSize); lba += SectorsInWrite; BlocksWritten += SectorsInWrite; } if (sectswritten) *sectswritten = BlocksWritten; return SCPE_OK; } static t_stat sim_vhd_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects) { VHDHANDLE hVHD = (VHDHANDLE)uptr->fileref; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; return WriteVirtualDiskSectors(hVHD, buf, sects, sectswritten, ctx->sector_size, lba); } #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | /* sim_disk.h: simulator disk support library definitions Copyright (c) 2011, Mark Pizzolato Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the names of Robert M Supnik and Mark Pizzolato shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik and Mark Pizzolato. 25-Jan-11 MP Initial Implemementation */ #ifndef SIM_DISK_H_ #define SIM_DISK_H_ 0 #ifdef __cplusplus extern "C" { #endif /* SIMH/Disk format */ typedef uint32 t_seccnt; /* disk sector count */ typedef uint32 t_lba; /* disk logical block address */ /* Unit flags */ #define DKUF_V_WLK (UNIT_V_UF + 0) /* write locked */ #define DKUF_V_FMT (UNIT_V_UF + 1) /* disk file format */ #define DKUF_W_FMT 2 /* 2b of formats */ #define DKUF_N_FMT (1u << DKUF_W_FMT) /* number of formats */ #define DKUF_M_FMT ((1u << DKUF_W_FMT) - 1) #define DKUF_F_STD 0 /* SIMH format */ #define DKUF_F_RAW 1 /* Raw Physical Disk Access */ #define DKUF_F_VHD 2 /* VHD format */ #define DKUF_V_UF (DKUF_V_FMT + DKUF_W_FMT) #define DKUF_WLK (1u << DKUF_V_WLK) #define DKUF_FMT (DKUF_M_FMT << DKUF_V_FMT) #define DKUF_WRP (DKUF_WLK | UNIT_RO) #define DK_F_STD (DKUF_F_STD << DKUF_V_FMT) #define DK_F_RAW (DKUF_F_RAW << DKUF_V_FMT) #define DK_F_VHD (DKUF_F_VHD << DKUF_V_FMT) #define DK_GET_FMT(u) (((u)->flags >> DKUF_V_FMT) & DKUF_M_FMT) /* Return status codes */ #define DKSE_OK 0 /* no error */ typedef void (*DISK_PCALLBACK)(UNIT *unit, t_stat status); /* Prototypes */ t_stat sim_disk_attach (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize, uint32 debugbit, const char *drivetype, uint32 pdp11_tracksize, int completion_delay); t_stat sim_disk_detach (UNIT *uptr); t_stat sim_disk_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); t_stat sim_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects); t_stat sim_disk_rdsect_a (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects, DISK_PCALLBACK callback); t_stat sim_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects); t_stat sim_disk_wrsect_a (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects, DISK_PCALLBACK callback); t_stat sim_disk_unload (UNIT *uptr); t_stat sim_disk_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_disk_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat sim_disk_set_capac (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_disk_show_capac (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat sim_disk_set_asynch (UNIT *uptr, int latency); t_stat sim_disk_clr_asynch (UNIT *uptr); t_stat sim_disk_reset (UNIT *uptr); t_stat sim_disk_perror (UNIT *uptr, const char *msg); t_stat sim_disk_clearerr (UNIT *uptr); t_bool sim_disk_isavailable (UNIT *uptr); t_bool sim_disk_isavailable_a (UNIT *uptr, DISK_PCALLBACK callback); t_bool sim_disk_wrp (UNIT *uptr); t_stat sim_disk_pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds); t_offset sim_disk_size (UNIT *uptr); t_bool sim_disk_vhd_support (void); t_bool sim_disk_raw_support (void); void sim_disk_data_trace (UNIT *uptr, const uint8 *data, size_t lba, size_t len, const char* txt, int detail, uint32 reason); #ifdef __cplusplus } #endif #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 | /* sim_ether.c: OS-dependent network routines ------------------------------------------------------------------------------ Copyright (c) 2002-2007, David T. Hittner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the author shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. ------------------------------------------------------------------------------ This ethernet simulation is based on the PCAP and WinPcap packages. PCAP/WinPcap was chosen as the basis for network code since it is the most "universal" of the various network packages available. Using this style has allowed rapid network development for the major SIMH platforms. Developing a network package specifically for SIMH was rejected due to the time required; the advantage would be a more easily compiled and integrated code set. There are various problems associated with use of ethernet networking, which would be true regardless of the network package used, since there are no universally accepted networking methods. The most serious of these is getting the proper networking package loaded onto the system, since most environments do not come with the network interface packages loaded. The second most serious network issue relates to security. The network simulation needs to simulate operating system level functionality (packet driving). However, the host network programming interfaces tend to operate at the user level of functionality, so getting to the full functionality of the network interface usually requires that the person executing the network code be a privileged user of the host system. See the PCAP/WinPcap documentation for the appropriate host platform if unprivileged use of networking is needed - there may be known workarounds. Define one of the two macros below to enable networking: USE_NETWORK - Create statically linked network code USE_SHARED - Create dynamically linked network code ------------------------------------------------------------------------------ Supported/Tested Platforms: Windows(NT,2K,XP,2K3,Vista,Win7) WinPcap V3.0+ Linux libpcap at least 0.9 OpenBSD,FreeBSD,NetBSD libpcap at least 0.9 MAC OS/X libpcap at least 0.9 Solaris Sparc libpcap at least 0.9 Solaris Intel libpcap at least 0.9 AIX ?? HP/UX ?? Compaq Tru64 Unix ?? VMS Alpha/Itanium VMS only, needs VMS libpcap WinPcap is available from: http://winpcap.polito.it/ libpcap for VMS is available from: http://simh.trailing-edge.com/sources/vms-pcap.zip libpcap for other Unix platforms is available at: NOTE: As of the release of this version of sim_ether.c ALL current *nix platforms ship with a sufficiently new version of libpcap, and ALL provide a libpcap-dev package for developing libpcap based applications. The OS vendor supplied version of libpcap AND the libpcap-dev components are preferred for proper operation of both simh AND other applications on the host system which use libpcap. Current Version: http://www.tcpdump.org/daily/libpcap-current.tar.gz Released Version: http://www.tcpdump.org/release/ When necessary (see NOTE above about vendor supplied libpcap), we've gotten the tarball, unpacked, built and installed it with: gzip -dc libpcap-current.tar.gz | tar xvf - cd libpcap-directory-name ./configure make make install Note: The "make install" step generally will have to be done as root. This will install libpcap in /usr/local/lib and /usr/local/include The current simh makefile will do the right thing to locate and reference the OS provided libpcap or the one just installed. Note: Building for the platforms indicated above, with the indicated libpcap, should automatically leverage the appropriate mechanisms contained here. Things are structured so that it is likely to work for any other as yet untested platform. If it works for you, please let the author know so we can update the table above. If it doesn't work, then the following #define variables can influence the operation on an untested platform. USE_BPF - Determines if this code leverages a libpcap/WinPcap provided bpf packet filtering facility. All tested environments have bpf facilities that work the way we need them to. However a new one might not. undefine this variable to let this code do its own filtering. USE_SETNONBLOCK - Specifies whether the libpcap environment's non-blocking semantics are to be leveraged. This helps to manage the varying behaviours of the kernel packet facilities leveraged by libpcap. USE_READER_THREAD - Specifies that packet reading should be done in the context of a separate thread. The Posix threading APIs are used. This option is less efficient than the default non-threaded approach, but it exists since some platforms don't want to work with nonblocking libpcap semantics. OpenBSD and NetBSD either don't have pthread APIs available, or they are too buggy to be useful. Using the threaded approach may require special compile and/or link time switches (i.e. -lpthread or -pthread, etc.) Consult the documentation for your platform as needed. Although this may be 'less efficient' than the non-threaded approach, the efficiency is an overall system efficiency not necessarily a simulator efficiency. This means that work is removed from the thread executing simulated instructions so the simulated system will most likely run faster (given that modern host CPUs are multi-core and have someplace to do this work in parallel). MUST_DO_SELECT - Specifies that, when USE_READER_THREAD is active, select() should be used to determine when available packets are ready for reading. Otherwise, we depend on the libpcap/kernel packet timeout specified on pcap_open_live. If USE_READER_THREAD is not set, then MUST_DO_SELECT is irrelevant HAVE_TAP_NETWORK - Specifies that support for tap networking should be included. This can be leveraged, along with OS bridging capabilities to share a single LAN interface. This allows device names of the form tap:tap0 to be specified at open time. This functionality is only useful/needed on *nix platforms since native sharing of Windows NIC devices works with no external magic. HAVE_VDE_NETWORK - Specifies that support for vde networking should be included. This can be leveraged, along with OS bridging capabilities to share a single LAN interface. It also can allow a simulator to have useful networking functionality when running without root access. This allows device names of the form vde:/tmp/switch to be specified at open time. This functionality is only available on *nix platforms since the vde api isn't available on Windows. HAVE_SLIRP_NETWORK- Specifies that support for SLiRP networking should be included. This can be leveraged to provide User Mode IP NAT connectivity for simulators. NEED_PCAP_SENDPACKET - Specifies that you are using an older version of libpcap which doesn't provide a pcap_sendpacket API. NOTE: Changing these defines is done in either sim_ether.h OR on the global compiler command line which builds all of the modules included in a simulator. ------------------------------------------------------------------------------ Modification history: 30-Mar-12 MP Added host NIC address determination on supported VMS platforms 01-Mar-12 MP Made host NIC address determination on *nix platforms more robust. 01-Mar-12 MP Added host NIC address determination work when building under Cygwin 01-Mar-12 AGN Add conditionals for Cygwin dynamic loading of wpcap.dll 01-Mar-12 AGN Specify the full /usr/lib for dlopen under Apple Mac OS X. 17-Nov-11 MP Added dynamic loading of libpcap on *nix platforms 30-Oct-11 MP Added support for vde (Virtual Distributed Ethernet) networking 29-Oct-11 MP Added support for integrated Tap networking interfaces on OSX 12-Aug-11 MP Cleaned up payload length determination Fixed race condition detecting reflections when threaded reading and writing is enabled 18-Apr-11 MP Fixed race condition with self loopback packets in multithreaded environments 09-Jan-11 MP Fixed missing crc data when USE_READER_THREAD is defined and crc's are needed (only the pdp11_xu) 16-Dec-10 MP added priority boost for read and write threads when USE_READER_THREAD does I/O in separate threads. This helps throughput since it allows these I/O bound threads to preempt the main thread (which is executing simulated instructions). 09-Dec-10 MP allowed more flexible parsing of MAC address strings 09-Dec-10 MP Added support to determine if network address conflicts exist 07-Dec-10 MP Reworked DECnet self detection to the more general approach of loopback self when a Physical Address is being set. 04-Dec-10 MP Changed eth_write to do nonblocking writes when USE_READER_THREAD is defined. 20-Aug-10 TVO Fix for Mac OSX 10.6 17-Jun-10 MP Fixed bug in the AUTODIN II hash filtering. 14-Jun-10 MP Added support for integrated Tap networking interfaces on BSD platforms. 13-Jun-10 MP Added support for integrated Tap networking interfaces on Linux platforms. 31-May-10 MP Added support for more TOE (TCP Offload Engine) features for IPv4 network traffic from the host and/or from hosts on the LAN. These new TOE features are: LSO (Large Send Offload) and Jumbo packet fragmentation support. These features allow a simulated network device to support traffic when a host leverages a NIC's Large Send Offload capabilities to fregment and/or segment outgoing network traffic. Additionally a simulated network device can reasonably exist on a LAN which is configured to use Jumbo frames. 21-May-10 MP Added functionality to fixup IP header checksums to accomodate packets from a host with a NIC which has TOE (TCP Offload Engine) enabled which is expected to implement the checksum computations in hardware. Since we catch packets before they arrive at the NIC the expected checksum insertions haven't been performed yet. This processing is only done for packets sent from the hoat to the guest we're supporting. In general this will be a relatively small number of packets so it is done for all IP frame packets coming from the hoat to the guest. In order to make the determination of packets specifically arriving from the host we need to know the hardware MAC address of the host NIC. Currently determining a NIC's MAC address is relatively easy on Windows. The non-windows code works on linux and may work on other *nix platforms either as is or with slight modifications. The code, as implemented, only messes with this activity if the host interface MAC address can be determined. 20-May-10 MP Added general support to deal with receiving packets smaller than ETH_MIN_PACKET in length. These come from packets looped back by some bridging mechanism and need to be padded to the minimum frame size. A real NIC won't pass us any packets like that. This fix belongs here since this layer is responsible for interfacing to they physical layer devices, AND it belongs here to get CRC processing right. 05-Mar-08 MP Added optional multicast filtering support for doing LANCE style AUTODIN II based hashed filtering. 07-Feb-08 MP Added eth_show_dev to display ethernet state Changed the return value from eth_read to return whether or not a packet was read. No existing callers used or checked constant return value that previously was being supplied. 29-Jan-08 MP Added eth_set_async to provide a mechanism (when USE_READER_THREAD is enabled) to allow packet reception to dynamically update the simulator event queue and potentially avoid polling for I/O. This provides a minimal overhead (no polling) maximal responsiveness for network activities. 29-Jan-08 MP Properly sequenced activities in eth_close to avoid a race condition when USE_READER_THREAD is enabled. 25-Jan-08 MP Changed the following when USE_READER_THREAD is enabled: - Fixed bug when the simulated device doesn't need crc in packet data which is read. - Added call to pcap_setmintocopy to minimize packet delivery latencies. - Added ethq_destroy and used it to avoid a memory leak in eth_close. - Properly cleaned up pthread mutexes in eth_close. Migrated to using sim_os_ms_sleep for a delay instead of a call to select(). Fixed the bpf filter used when no traffic is to be matched. Reworked eth_add_packet_crc32 implementation to avoid an extra buffer copy while reading packets. Fixedup #ifdef's relating to USE_SHARED so that setting USE_SHARED or USE_NETWORK will build a working network environment. 23-Jan-08 MP Reworked eth_packet_trace and eth_packet_trace_ex to allow only output ethernet header+crc and provide a mechanism for the simulated device to display full packet data debugging. 17-May-07 DTH Fixed non-ethernet device removal loop (from Naoki Hamada) 15-May-07 DTH Added dynamic loading of wpcap.dll; Corrected exceed max index bug in ethX lookup 04-May-07 DTH Corrected failure to look up ethernet device names in the registry on Windows XP x64 10-Jul-06 RMS Fixed linux conditionalization (from Chaskiel Grundman) 02-Jun-06 JDB Fixed compiler warning for incompatible sscanf parameter 15-Dec-05 DTH Patched eth_host_devices [remove non-ethernet devices] (from Mark Pizzolato and Galen Tackett, 08-Jun-05) Patched eth_open [tun fix](from Antal Ritter, 06-Oct-05) 30-Nov-05 DTH Added option to regenerate CRC on received packets; some ethernet devices need to pass it on to the simulation, and by the time libpcap/winpcap gets the packet, the host OS network layer has already stripped CRC out of the packet 01-Dec-04 DTH Added Windows user-defined adapter names (from Timothe Litt) 25-Mar-04 MP Revised comments and minor #defines to deal with updated libpcap which now provides pcap_sendpacket on all platforms. 04-Feb-04 MP Returned success/fail status from eth_write to support determining if the current libpcap connection can successfully write packets. Added threaded approach to reading packets since this works better on some platforms (solaris intel) than the inconsistently implemented non-blocking read approach. 04-Feb-04 DTH Converted ETH_DEBUG to sim_debug 13-Jan-04 MP tested and fixed on OpenBSD, NetBS and FreeBSD. 09-Jan-04 MP removed the BIOCSHDRCMPLT ioctl() for OS/X 05-Jan-04 DTH Added eth_mac_scan 30-Dec-03 DTH Cleaned up queue routines, added no network support message 26-Dec-03 DTH Added ethernet show and queue functions from pdp11_xq 15-Dec-03 MP polished generic libpcap support. 05-Dec-03 DTH Genericized eth_devices() and #ifdefs 03-Dec-03 MP Added Solaris support 02-Dec-03 DTH Corrected decnet fix to use reflection counting 01-Dec-03 DTH Added BPF source filtering and reflection counting 28-Nov-03 DTH Rewrote eth_devices using universal pcap_findalldevs() 25-Nov-03 DTH Verified DECNET_FIX, reversed ifdef to mainstream code 19-Nov-03 MP Fixed BPF functionality on Linux/BSD. 17-Nov-03 DTH Added xBSD simplification 14-Nov-03 DTH Added #ifdef DECNET_FIX for problematic duplicate detection code 13-Nov-03 DTH Merged in __FreeBSD__ support 21-Oct-03 MP Added enriched packet dumping for debugging 20-Oct-03 MP Added support for multiple ethernet devices on VMS 20-Sep-03 Ankan Add VMS support (Alpha only) 29-Sep-03 MP Changed separator character in eth_fmt_mac to be ":" to format ethernet addresses the way the BPF compile engine wants to see them. Added BPF support to filter packets Added missing printf in eth_close 07-Jun-03 MP Added WIN32 support for DECNET duplicate address detection. 06-Jun-03 MP Fixed formatting of Ethernet Protocol Type in eth_packet_trace 30-May-03 DTH Changed WIN32 to _WIN32 for consistency 07-Mar-03 MP Fixed Linux implementation of PacketGetAdapterNames to also work on Red Hat 6.2-sparc and Debian 3.0r1-sparc. 03-Mar-03 MP Changed logging to be consistent on stdout and sim_log 01-Feb-03 MP Changed type of local variables in eth_packet_trace to conform to the interface needs of eth_mac_fmt wich produces char data instead of unsigned char data. Suggested by the DECC compiler. 15-Jan-03 DTH Corrected PacketGetAdapterNames parameter2 datatype 26-Dec-02 DTH Merged Mark Pizzolato's enhancements with main source Added networking documentation Changed _DEBUG to ETH_DEBUG 20-Dec-02 MP Added display of packet CRC to the eth_packet_trace. This helps distinguish packets with identical lengths and protocols. 05-Dec-02 MP With the goal of draining the input buffer more rapidly changed eth_read to call pcap_dispatch repeatedly until either a timeout returns nothing or a packet allowed by the filter is seen. This more closely reflects how the pcap layer will work when the filtering is actually done by a bpf filter. 31-Oct-02 DTH Added USE_NETWORK conditional Reworked not attached test Added OpenBSD support (from Federico Schwindt) Added ethX detection simplification (from Megan Gentry) Removed sections of temporary code Added parameter validation 23-Oct-02 DTH Beta 5 released 22-Oct-02 DTH Added all_multicast and promiscuous support Fixed not attached behavior 21-Oct-02 DTH Added NetBSD support (from Jason Thorpe) Patched buffer size to make sure entire packet is read in Made 'ethX' check characters passed as well as length Corrected copyright again 16-Oct-02 DTH Beta 4 released Corrected copyright 09-Oct-02 DTH Beta 3 released Added pdp11 write acceleration (from Patrick Caulfield) 08-Oct-02 DTH Beta 2 released Integrated with 2.10-0p4 Added variable vector and copyrights 04-Oct-02 DTH Added linux support (from Patrick Caulfield) 03-Oct-02 DTH Beta version of xq/sim_ether released for SIMH 2.09-11 24-Sep-02 DTH Finished eth_devices, eth_getname 18-Sep-02 DTH Callbacks implemented 13-Sep-02 DTH Basic packet read/write written 20-Aug-02 DTH Created Sim_Ether for O/S independant ethernet implementation ------------------------------------------------------------------------------ */ #include <ctype.h> #include "sim_ether.h" #include "sim_sock.h" #include "sim_timer.h" #if defined(_WIN32) #include <direct.h> #else #include <unistd.h> #endif #define MAX(a,b) (((a) > (b)) ? (a) : (b)) /* Internal routines - forward declarations */ static int _eth_get_system_id (char *buf, size_t buf_size); /*============================================================================*/ /* OS-independant ethernet routines */ /*============================================================================*/ t_stat eth_mac_scan (ETH_MAC* mac, const char* strmac) { return eth_mac_scan_ex (mac, strmac, NULL); } t_stat eth_mac_scan_ex (ETH_MAC* mac, const char* strmac, UNIT *uptr) { unsigned int a[6], g[6]; FILE *f; char filebuf[64] = ""; uint32 i; static const ETH_MAC zeros = {0,0,0,0,0,0}; static const ETH_MAC ones = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; ETH_MAC newmac; struct { uint32 bits; char system_id[37]; char cwd[PATH_MAX]; char file[PATH_MAX]; ETH_MAC base_mac; char uname[64]; char sim[128]; } state; CONST char *cptr, *tptr; uint32 data; /* Allow generated MAC address */ /* XX:XX:XX:XX:XX:XX{/bits{>file}} */ /* bits (if specified) must be from 16 thru 48 */ memset (&state, 0, sizeof(state)); _eth_get_system_id (state.system_id, sizeof(state.system_id)); strncpy (state.sim, sim_name, sizeof(state.sim)); getcwd (state.cwd, sizeof(state.cwd)); if (uptr) strncpy (state.uname, sim_uname (uptr), sizeof(state.uname)-1); cptr = strchr (strmac, '>'); if (cptr) { state.file[sizeof(state.file)-1] = '\0'; strncpy (state.file, cptr + 1, sizeof(state.file)-1); if ((f = fopen (state.file, "r"))) { filebuf[sizeof(filebuf)-1] = '\0'; fgets (filebuf, sizeof(filebuf)-1, f); strmac = filebuf; fclose (f); strcpy (state.file, ""); /* avoid saving */ } } cptr = strchr (strmac, '/'); if (cptr) { state.bits = (uint32)strtotv (cptr + 1, &tptr, 10); if ((state.bits < 16) || (state.bits > 48)) return sim_messagef (SCPE_ARG, "Invalid MAC address bits specifier '%d'. Valid values are from 16 thru 48\n", state.bits); } else state.bits = 48; data = eth_crc32 (0, (void *)&state, sizeof(state)); for (i=g[0]=g[1]=0; i<4; i++) g[i+2] = (data >> (i << 3)) & 0xFF; if ((6 != sscanf(strmac, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5])) && (6 != sscanf(strmac, "%x.%x.%x.%x.%x.%x", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5])) && (6 != sscanf(strmac, "%x-%x-%x-%x-%x-%x", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))) return sim_messagef (SCPE_ARG, "Invalid MAC address format: '%s'\n", strmac); for (i=0; i<6; i++) if (a[i] > 0xFF) return sim_messagef (SCPE_ARG, "Invalid MAC address byte value: %02X\n", a[i]); else { uint32 mask, shift; state.base_mac[i] = a[i]; if (((i + 1) << 3) < state.bits) shift = 0; else shift = ((i + 1) << 3) - state.bits; mask = 0xFF << shift; newmac[i] = (unsigned char)((a[i] & mask) | (g[i] & ~mask)); } /* final check - mac cannot be broadcast or multicast address */ if (!memcmp(newmac, zeros, sizeof(ETH_MAC)) || /* broadcast */ !memcmp(newmac, ones, sizeof(ETH_MAC)) || /* broadcast */ (newmac[0] & 0x01) /* multicast */ ) return sim_messagef (SCPE_ARG, "Can't use Broadcast or MultiCast address as interface MAC address\n"); /* new mac is OK */ /* optionally save */ if (state.file[0]) { /* Save File specified? */ f = fopen (state.file, "w"); if (f == NULL) return sim_messagef (SCPE_ARG, "Can't open MAC address configuration file '%s'.\n", state.file); eth_mac_fmt (&newmac, filebuf); fprintf (f, "%s/48\n", filebuf); fprintf (f, "system-id: %s\n", state.system_id); fprintf (f, "directory: %s\n", state.cwd); fprintf (f, "simulator: %s\n", state.sim); fprintf (f, "device: %s\n", state.uname); fprintf (f, "file: %s\n", state.file); eth_mac_fmt (&state.base_mac, filebuf); fprintf (f, "base-mac: %s\n", filebuf); fprintf (f, "specified: %d bits\n", state.bits); fprintf (f, "generated: %d bits\n", 48-state.bits); fclose (f); } /* copy into passed mac */ memcpy (*mac, newmac, sizeof(ETH_MAC)); return SCPE_OK; } void eth_mac_fmt(ETH_MAC* const mac, char* buff) { const uint8* m = (const uint8*) mac; sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X", m[0], m[1], m[2], m[3], m[4], m[5]); return; } static const uint32 crcTable[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; uint32 eth_crc32(uint32 crc, const void* vbuf, size_t len) { const uint32 mask = 0xFFFFFFFF; const unsigned char* buf = (const unsigned char*)vbuf; crc ^= mask; while (len > 8) { crc = (crc >> 8) ^ crcTable[ (crc ^ (*buf++)) & 0xFF ]; crc = (crc >> 8) ^ crcTable[ (crc ^ (*buf++)) & 0xFF ]; crc = (crc >> 8) ^ crcTable[ (crc ^ (*buf++)) & 0xFF ]; crc = (crc >> 8) ^ crcTable[ (crc ^ (*buf++)) & 0xFF ]; crc = (crc >> 8) ^ crcTable[ (crc ^ (*buf++)) & 0xFF ]; crc = (crc >> 8) ^ crcTable[ (crc ^ (*buf++)) & 0xFF ]; crc = (crc >> 8) ^ crcTable[ (crc ^ (*buf++)) & 0xFF ]; crc = (crc >> 8) ^ crcTable[ (crc ^ (*buf++)) & 0xFF ]; len -= 8; } while (0 != len--) crc = (crc >> 8) ^ crcTable[ (crc ^ (*buf++)) & 0xFF ]; return(crc ^ mask); } int eth_get_packet_crc32_data(const uint8 *msg, int len, uint8 *crcdata) { int crc_len; if (len <= ETH_MAX_PACKET) { uint32 crc = eth_crc32(0, msg, len); /* calculate CRC */ uint32 ncrc = htonl(crc); /* CRC in network order */ int size = sizeof(ncrc); /* size of crc field */ memcpy(crcdata, &ncrc, size); /* append crc to packet */ crc_len = len + size; /* set packet crc length */ } else { crc_len = 0; /* appending crc would destroy packet */ } return crc_len; } int eth_add_packet_crc32(uint8 *msg, int len) { int crc_len; if (len <= ETH_MAX_PACKET) { crc_len = eth_get_packet_crc32_data(msg, len, &msg[len]);/* append crc to packet */ } else { crc_len = 0; /* appending crc would destroy packet */ } return crc_len; } void eth_setcrc(ETH_DEV* dev, int need_crc) { dev->need_crc = need_crc; } void eth_packet_trace_ex(ETH_DEV* dev, const uint8 *msg, int len, const char* txt, int detail, uint32 reason) { if (dev->dptr->dctrl & reason) { char src[20]; char dst[20]; const unsigned short* proto = (const unsigned short*) &msg[12]; uint32 crc = eth_crc32(0, msg, len); eth_mac_fmt((ETH_MAC*)msg, dst); eth_mac_fmt((ETH_MAC*)(msg+6), src); sim_debug(reason, dev->dptr, "%s dst: %s src: %s proto: 0x%04X len: %d crc: %X\n", txt, dst, src, ntohs(*proto), len, crc); if (detail) { int i, same, group, sidx, oidx; char outbuf[80], strbuf[18]; static const char hex[] = "0123456789ABCDEF"; for (i=same=0; i<len; i += 16) { if ((i > 0) && (0 == memcmp(&msg[i], &msg[i-16], 16))) { ++same; continue; } if (same > 0) { sim_debug(reason, dev->dptr, "%04X thru %04X same as above\n", i-(16*same), i-1); same = 0; } group = (((len - i) > 16) ? 16 : (len - i)); for (sidx=oidx=0; sidx<group; ++sidx) { outbuf[oidx++] = ' '; outbuf[oidx++] = hex[(msg[i+sidx]>>4)&0xf]; outbuf[oidx++] = hex[msg[i+sidx]&0xf]; if (isprint(msg[i+sidx])) strbuf[sidx] = msg[i+sidx]; else strbuf[sidx] = '.'; } outbuf[oidx] = '\0'; strbuf[sidx] = '\0'; sim_debug(reason, dev->dptr, "%04X%-48s %s\n", i, outbuf, strbuf); } if (same > 0) { sim_debug(reason, dev->dptr, "%04X thru %04X same as above\n", i-(16*same), len-1); } } } } void eth_packet_trace(ETH_DEV* dev, const uint8 *msg, int len, const char* txt) { eth_packet_trace_ex(dev, msg, len, txt, 0, dev->dbit); } void eth_packet_trace_detail(ETH_DEV* dev, const uint8 *msg, int len, const char* txt) { eth_packet_trace_ex(dev, msg, len, txt, 1 , dev->dbit); } const char* eth_getname(int number, char* name, char *desc) { ETH_LIST list[ETH_MAX_DEVICE]; int count = eth_devices(ETH_MAX_DEVICE, list); if ((number < 0) || (count <= number)) return NULL; if (list[number].eth_api != ETH_API_PCAP) { sim_printf ("Eth: Pcap capable device not found. You may need to run as root\n"); return NULL; } strcpy(name, list[number].name); strcpy(desc, list[number].desc); return name; } const char* eth_getname_bydesc(const char* desc, char* name, char *ndesc) { ETH_LIST list[ETH_MAX_DEVICE]; int count = eth_devices(ETH_MAX_DEVICE, list); int i; size_t j=strlen(desc); for (i=0; i<count; i++) { int found = 1; size_t k = strlen(list[i].desc); if (j != k) continue; for (k=0; k<j; k++) if (tolower(list[i].desc[k]) != tolower(desc[k])) found = 0; if (found == 0) continue; /* found a case-insensitive description match */ strcpy(name, list[i].name); strcpy(ndesc, list[i].desc); return name; } /* not found */ return NULL; } char* eth_getname_byname(const char* name, char* temp, char *desc) { ETH_LIST list[ETH_MAX_DEVICE]; int count = eth_devices(ETH_MAX_DEVICE, list); size_t n; int i, found; found = 0; n = strlen(name); for (i=0; i<count && !found; i++) { if ((n == strlen(list[i].name)) && (sim_strncasecmp(name, list[i].name, n) == 0)) { found = 1; strcpy(temp, list[i].name); /* only case might be different */ strcpy(desc, list[i].desc); } } return (found ? temp : NULL); } char* eth_getdesc_byname(char* name, char* temp) { ETH_LIST list[ETH_MAX_DEVICE]; int count = eth_devices(ETH_MAX_DEVICE, list); size_t n; int i, found; found = 0; n = strlen(name); for (i=0; i<count && !found; i++) { if ((n == strlen(list[i].name)) && (sim_strncasecmp(name, list[i].name, n) == 0)) { found = 1; strcpy(temp, list[i].desc); } } return (found ? temp : NULL); } void eth_zero(ETH_DEV* dev) { /* set all members to NULL OR 0 */ memset(dev, 0, sizeof(ETH_DEV)); dev->reflections = -1; /* not established yet */ } static char* (*p_pcap_lib_version) (void); static ETH_DEV **eth_open_devices = NULL; static int eth_open_device_count = 0; static t_bool eth_show_active = FALSE; #if defined (USE_NETWORK) || defined (USE_SHARED) static void _eth_add_to_open_list (ETH_DEV* dev) { eth_open_devices = (ETH_DEV**)realloc(eth_open_devices, (eth_open_device_count+1)*sizeof(*eth_open_devices)); eth_open_devices[eth_open_device_count++] = dev; } static void _eth_remove_from_open_list (ETH_DEV* dev) { int i, j; for (i=0; i<eth_open_device_count; ++i) if (eth_open_devices[i] == dev) { for (j=i+1; j<eth_open_device_count; ++j) eth_open_devices[j-1] = eth_open_devices[j]; --eth_open_device_count; break; } } #endif t_stat eth_show (FILE* st, UNIT* uptr, int32 val, CONST void* desc) { ETH_LIST list[ETH_MAX_DEVICE]; int number; eth_show_active = TRUE; number = eth_devices(ETH_MAX_DEVICE, list); fprintf(st, "ETH devices:\n"); if (number == -1) fprintf(st, " network support not available in simulator\n"); else if (number == 0) fprintf(st, " no network devices are available\n"); else { size_t min, len; int i; for (i=0, min=0; i<number; i++) if ((len = strlen(list[i].name)) > min) min = len; for (i=0; i<number; i++) fprintf(st," eth%d\t%-*s (%s)\n", i, (int)min, list[i].name, list[i].desc); } if (p_pcap_lib_version) { fprintf(st, "%s\n", p_pcap_lib_version()); } if (eth_open_device_count) { int i; char desc[ETH_DEV_DESC_MAX], *d; fprintf(st,"Open ETH Devices:\n"); for (i=0; i<eth_open_device_count; i++) { d = eth_getdesc_byname(eth_open_devices[i]->name, desc); if (d) fprintf(st, " %-7s%s (%s)\n", eth_open_devices[i]->dptr->name, eth_open_devices[i]->dptr->units[0].filename, d); else fprintf(st, " %-7s%s\n", eth_open_devices[i]->dptr->name, eth_open_devices[i]->dptr->units[0].filename); eth_show_dev (st, eth_open_devices[i]); } } eth_show_active = FALSE; return SCPE_OK; } t_stat eth_show_devices (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char *desc) { return eth_show (st, uptr, val, NULL); } t_stat ethq_init(ETH_QUE* que, int max) { /* create dynamic queue if it does not exist */ if (!que->item) { que->item = (struct eth_item *) calloc(max, sizeof(struct eth_item)); if (!que->item) { /* failed to allocate memory */ sim_printf("EthQ: failed to allocate dynamic queue[%d]\r\n", max); return SCPE_MEM; }; que->max = max; }; ethq_clear(que); return SCPE_OK; } t_stat ethq_destroy(ETH_QUE* que) { /* release dynamic queue if it exists */ ethq_clear(que); que->max = 0; if (que->item) { free(que->item); que->item = NULL; }; return SCPE_OK; } void ethq_clear(ETH_QUE* que) { int i; /* free up any extended packets */ for (i=0; i<que->max; ++i) if (que->item[i].packet.oversize) { free (que->item[i].packet.oversize); que->item[i].packet.oversize = NULL; } /* clear packet array */ memset(que->item, 0, sizeof(struct eth_item) * que->max); /* clear rest of structure */ que->count = que->head = que->tail = 0; } void ethq_remove(ETH_QUE* que) { struct eth_item* item = &que->item[que->head]; if (que->count) { if (item->packet.oversize) free (item->packet.oversize); memset(item, 0, sizeof(struct eth_item)); if (++que->head == que->max) que->head = 0; que->count--; } } void ethq_insert_data(ETH_QUE* que, int32 type, const uint8 *data, int used, size_t len, size_t crc_len, const uint8 *crc_data, int32 status) { struct eth_item* item; /* if queue empty, set pointers to beginning */ if (!que->count) { que->head = 0; que->tail = -1; } /* find new tail of the circular queue */ if (++que->tail == que->max) que->tail = 0; if (++que->count > que->max) { que->count = que->max; /* lose oldest packet */ if (++que->head == que->max) que->head = 0; que->loss++; } if (que->count > que->high) que->high = que->count; /* set information in (new) tail item */ item = &que->item[que->tail]; item->type = type; item->packet.len = len; item->packet.used = used; item->packet.crc_len = crc_len; if (MAX (len, crc_len) <= sizeof (item->packet.msg) - ETH_CRC_SIZE) { memcpy(item->packet.msg, data, ((len > crc_len) ? len : crc_len)); if (crc_data && (crc_len > len)) memcpy(&item->packet.msg[len], crc_data, ETH_CRC_SIZE); } else { item->packet.oversize = (uint8 *)realloc (item->packet.oversize, ((len > crc_len) ? len : crc_len)); memcpy(item->packet.oversize, data, ((len > crc_len) ? len : crc_len)); if (crc_data && (crc_len > len)) memcpy(&item->packet.oversize[len], crc_data, ETH_CRC_SIZE); } item->packet.status = status; } void ethq_insert(ETH_QUE* que, int32 type, ETH_PACK* pack, int32 status) { ethq_insert_data(que, type, pack->oversize ? pack->oversize : pack->msg, pack->used, pack->len, pack->crc_len, NULL, status); } /*============================================================================*/ /* Non-implemented versions */ /*============================================================================*/ #if !defined (USE_NETWORK) && !defined (USE_SHARED) const char *eth_capabilities(void) {return "no Ethernet";} t_stat eth_open(ETH_DEV* dev, const char* name, DEVICE* dptr, uint32 dbit) {return SCPE_NOFNC;} t_stat eth_close (ETH_DEV* dev) {return SCPE_NOFNC;} t_stat eth_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { fprintf (st, "%s attach help\n\n", dptr->name); fprintf (st, "This simulator was not built with ethernet device support\n"); return SCPE_OK; } t_stat eth_check_address_conflict (ETH_DEV* dev, ETH_MAC* const mac) {return SCPE_NOFNC;} t_stat eth_set_throttle (ETH_DEV* dev, uint32 time, uint32 burst, uint32 delay) {return SCPE_NOFNC;} t_stat eth_set_async (ETH_DEV *dev, int latency) {return SCPE_NOFNC;} t_stat eth_clr_async (ETH_DEV *dev) {return SCPE_NOFNC;} t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) {return SCPE_NOFNC;} int eth_read (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) {return SCPE_NOFNC;} t_stat eth_filter (ETH_DEV* dev, int addr_count, ETH_MAC* const addresses, ETH_BOOL all_multicast, ETH_BOOL promiscuous) {return SCPE_NOFNC;} t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, ETH_MAC* const addresses, ETH_BOOL all_multicast, ETH_BOOL promiscuous, ETH_MULTIHASH* const hash) {return SCPE_NOFNC;} int eth_devices (int max, ETH_LIST* dev) {return -1;} void eth_show_dev (FILE* st, ETH_DEV* dev) {} static int _eth_get_system_id (char *buf, size_t buf_size) {memset (buf, 0, buf_size); return 0;} #else /* endif unimplemented */ const char *eth_capabilities(void) { #if defined (USE_READER_THREAD) return "Threaded " #else return "Polled " #endif "Ethernet Packet transports" #if defined (HAVE_PCAP_NETWORK) ":PCAP" #endif #if defined (HAVE_TAP_NETWORK) ":TAP" #endif #if defined (HAVE_VDE_NETWORK) ":VDE" #endif #if defined (HAVE_SLIRP_NETWORK) ":NAT" #endif ":UDP"; } #if (defined (xBSD) || defined (__APPLE__)) && (defined (HAVE_TAP_NETWORK) || defined (HAVE_PCAP_NETWORK)) #include <sys/ioctl.h> #include <net/bpf.h> #endif #if defined (HAVE_PCAP_NETWORK) /*============================================================================*/ /* WIN32, Linux, and xBSD routines use WinPcap and libpcap packages */ /* OpenVMS Alpha uses a WinPcap port and an associated execlet */ /*============================================================================*/ #include <pcap.h> #include <string.h> #else struct pcap_pkthdr { uint32 caplen; /* length of portion present */ uint32 len; /* length this packet (off wire) */ }; #define PCAP_ERRBUF_SIZE 256 typedef void * pcap_t; /* Pseudo Type to avoid compiler errors */ #define DLT_EN10MB 1 /* Dummy Value to avoid compiler errors */ #endif /* HAVE_PCAP_NETWORK */ #ifdef HAVE_TAP_NETWORK #if defined(__linux) || defined(__linux__) #include <sys/ioctl.h> #include <net/if.h> #include <linux/if_tun.h> #elif defined(HAVE_BSDTUNTAP) #include <sys/types.h> #include <net/if_types.h> #include <net/if.h> #else /* We don't know how to do this on the current platform */ #undef HAVE_TAP_NETWORK #endif #endif /* HAVE_TAP_NETWORK */ #ifdef HAVE_VDE_NETWORK #ifdef __cplusplus extern "C" { #endif #include <libvdeplug.h> #ifdef __cplusplus } #endif #endif /* HAVE_VDE_NETWORK */ #ifdef HAVE_SLIRP_NETWORK #include "sim_slirp.h" #endif /* HAVE_SLIRP_NETWORK */ /* Allows windows to look up user-defined adapter names */ #if defined(_WIN32) #include <winreg.h> #endif #ifdef HAVE_DLOPEN #include <dlfcn.h> #endif #if defined(USE_SHARED) && (defined(_WIN32) || defined(HAVE_DLOPEN)) /* Dynamic DLL loading technique and modified source comes from Etherial/WireShark capture_pcap.c */ /* Dynamic DLL load variables */ #ifdef _WIN32 static HINSTANCE hLib = NULL; /* handle to DLL */ #else static void *hLib = 0; /* handle to Library */ #endif static int lib_loaded = 0; /* 0=not loaded, 1=loaded, 2=library load failed, 3=Func load failed */ static const char* lib_name = #if defined(_WIN32) || defined(__CYGWIN__) "wpcap.dll"; #elif defined(__APPLE__) "/usr/lib/libpcap.A.dylib"; #else #define __STR_QUOTE(tok) #tok #define __STR(tok) __STR_QUOTE(tok) "libpcap." __STR(HAVE_DLOPEN); #endif static const char* no_pcap = #if defined(_WIN32) || defined(__CYGWIN__) "wpcap load failure"; #else "libpcap load failure"; #endif /* define pointers to pcap functions needed */ static void (*p_pcap_close) (pcap_t *); static int (*p_pcap_compile) (pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32); static int (*p_pcap_datalink) (pcap_t *); static int (*p_pcap_dispatch) (pcap_t *, int, pcap_handler, u_char *); static int (*p_pcap_findalldevs) (pcap_if_t **, char *); static void (*p_pcap_freealldevs) (pcap_if_t *); static void (*p_pcap_freecode) (struct bpf_program *); static char* (*p_pcap_geterr) (pcap_t *); static int (*p_pcap_lookupnet) (const char *, bpf_u_int32 *, bpf_u_int32 *, char *); static pcap_t* (*p_pcap_open_live) (const char *, int, int, int, char *); #ifdef _WIN32 static int (*p_pcap_setmintocopy) (pcap_t* handle, int); static HANDLE (*p_pcap_getevent) (pcap_t *); #else #ifdef MUST_DO_SELECT static int (*p_pcap_get_selectable_fd) (pcap_t *); #endif static int (*p_pcap_fileno) (pcap_t *); #endif static int (*p_pcap_sendpacket) (pcap_t* handle, const u_char* msg, int len); static int (*p_pcap_setfilter) (pcap_t *, struct bpf_program *); static int (*p_pcap_setnonblock)(pcap_t* a, int nonblock, char *errbuf); /* load function pointer from DLL */ typedef int (*_func)(); static void load_function(const char* function, _func* func_ptr) { #ifdef _WIN32 *func_ptr = (_func)((size_t)GetProcAddress(hLib, function)); #else *func_ptr = (_func)((size_t)dlsym(hLib, function)); #endif if (*func_ptr == 0) { sim_printf ("Eth: Failed to find function '%s' in %s\r\n", function, lib_name); lib_loaded = 3; } } static void try_load_function(const char* function, _func* func_ptr) { #ifdef _WIN32 *func_ptr = (_func)((size_t)GetProcAddress(hLib, function)); #else *func_ptr = (_func)((size_t)dlsym(hLib, function)); #endif } /* load wpcap.dll as required */ int load_pcap(void) { switch(lib_loaded) { case 0: /* not loaded */ /* attempt to load DLL */ #ifdef _WIN32 if (1) { BOOL(WINAPI *p_SetDllDirectory)(LPCTSTR); UINT(WINAPI *p_GetSystemDirectory)(LPTSTR lpBuffer, UINT uSize); p_SetDllDirectory = (BOOL(WINAPI *)(LPCTSTR)) GetProcAddress(GetModuleHandle("kernel32.dll"), "SetDllDirectoryA"); p_GetSystemDirectory = (UINT(WINAPI *)(LPTSTR, UINT)) GetProcAddress(GetModuleHandle("kernel32.dll"), "GetSystemDirectoryA"); if (p_SetDllDirectory && p_GetSystemDirectory) { char npcap_path[512] = ""; if (p_GetSystemDirectory (npcap_path, sizeof(npcap_path) - 7)) sim_strlcat (npcap_path, "\\Npcap", sizeof(npcap_path)); if (p_SetDllDirectory(npcap_path)) hLib = LoadLibraryA(lib_name); p_SetDllDirectory (NULL); } if (hLib == NULL) hLib = LoadLibraryA(lib_name); } #else hLib = dlopen(lib_name, RTLD_NOW); #endif if (hLib == 0) { /* failed to load DLL */ sim_printf ("Eth: Failed to load %s\r\n", lib_name); #ifdef _WIN32 sim_printf ("Eth: You must install Npcap or WinPcap 4.x to use networking\r\n"); #else sim_printf ("Eth: You must install libpcap to use networking\r\n"); #endif lib_loaded = 2; break; } else { /* library loaded OK */ lib_loaded = 1; } /* load required functions; sets dll_load=3 on error */ load_function("pcap_close", (_func *) &p_pcap_close); load_function("pcap_compile", (_func *) &p_pcap_compile); load_function("pcap_datalink", (_func *) &p_pcap_datalink); load_function("pcap_dispatch", (_func *) &p_pcap_dispatch); load_function("pcap_findalldevs", (_func *) &p_pcap_findalldevs); load_function("pcap_freealldevs", (_func *) &p_pcap_freealldevs); load_function("pcap_freecode", (_func *) &p_pcap_freecode); load_function("pcap_geterr", (_func *) &p_pcap_geterr); load_function("pcap_lookupnet", (_func *) &p_pcap_lookupnet); load_function("pcap_open_live", (_func *) &p_pcap_open_live); #ifdef _WIN32 load_function("pcap_setmintocopy", (_func *) &p_pcap_setmintocopy); load_function("pcap_getevent", (_func *) &p_pcap_getevent); #else #ifdef MUST_DO_SELECT load_function("pcap_get_selectable_fd", (_func *) &p_pcap_get_selectable_fd); #endif load_function("pcap_fileno", (_func *) &p_pcap_fileno); #endif load_function("pcap_sendpacket", (_func *) &p_pcap_sendpacket); load_function("pcap_setfilter", (_func *) &p_pcap_setfilter); load_function("pcap_setnonblock", (_func *) &p_pcap_setnonblock); load_function("pcap_lib_version", (_func *) &p_pcap_lib_version); if ((lib_loaded == 1) && (!eth_show_active)) { /* log successful load */ sim_printf("%s\n", p_pcap_lib_version()); } break; default: /* loaded or failed */ break; } return (lib_loaded == 1) ? 1 : 0; } /* define functions with dynamic revectoring */ void pcap_close(pcap_t* a) { if (load_pcap() != 0) { p_pcap_close(a); } } /* Some platforms's pcap.h have an ancient declaration of pcap_compile which doesn't have a const in the bpf string argument */ #if !defined (BPF_CONST_STRING) int pcap_compile(pcap_t* a, struct bpf_program* b, char* c, int d, bpf_u_int32 e) { #else int pcap_compile(pcap_t* a, struct bpf_program* b, const char* c, int d, bpf_u_int32 e) { #endif if (load_pcap() != 0) { return p_pcap_compile(a, b, c, d, e); } else { return 0; } } int pcap_datalink(pcap_t* a) { if (load_pcap() != 0) { return p_pcap_datalink(a); } else { return 0; } } int pcap_dispatch(pcap_t* a, int b, pcap_handler c, u_char* d) { if (load_pcap() != 0) { return p_pcap_dispatch(a, b, c, d); } else { return 0; } } int pcap_findalldevs(pcap_if_t** a, char* b) { if (load_pcap() != 0) { return p_pcap_findalldevs(a, b); } else { *a = 0; strcpy(b, no_pcap); return -1; } } void pcap_freealldevs(pcap_if_t* a) { if (load_pcap() != 0) { p_pcap_freealldevs(a); } } void pcap_freecode(struct bpf_program* a) { if (load_pcap() != 0) { p_pcap_freecode(a); } } char* pcap_geterr(pcap_t* a) { if (load_pcap() != 0) { return p_pcap_geterr(a); } else { return (char*) 0; } } int pcap_lookupnet(const char* a, bpf_u_int32* b, bpf_u_int32* c, char* d) { if (load_pcap() != 0) { return p_pcap_lookupnet(a, b, c, d); } else { return 0; } } pcap_t* pcap_open_live(const char* a, int b, int c, int d, char* e) { if (load_pcap() != 0) { return p_pcap_open_live(a, b, c, d, e); } else { return (pcap_t*) 0; } } #ifdef _WIN32 int pcap_setmintocopy(pcap_t* a, int b) { if (load_pcap() != 0) { return p_pcap_setmintocopy(a, b); } else { return 0; } } HANDLE pcap_getevent(pcap_t* a) { if (load_pcap() != 0) { return p_pcap_getevent(a); } else { return (HANDLE) 0; } } #else #ifdef MUST_DO_SELECT int pcap_get_selectable_fd(pcap_t* a) { if (load_pcap() != 0) { return p_pcap_get_selectable_fd(a); } else { return 0; } } #endif int pcap_fileno(pcap_t * a) { if (load_pcap() != 0) { return p_pcap_fileno(a); } else { return 0; } } #endif int pcap_sendpacket(pcap_t* a, const u_char* b, int c) { if (load_pcap() != 0) { return p_pcap_sendpacket(a, b, c); } else { return 0; } } int pcap_setfilter(pcap_t* a, struct bpf_program* b) { if (load_pcap() != 0) { return p_pcap_setfilter(a, b); } else { return 0; } } int pcap_setnonblock(pcap_t* a, int nonblock, char *errbuf) { if (load_pcap() != 0) { return p_pcap_setnonblock(a, nonblock, errbuf); } else { return 0; } } #endif /* defined(USE_SHARED) && (defined(_WIN32) || defined(HAVE_DLOPEN)) */ /* Some platforms have always had pcap_sendpacket */ #if defined(_WIN32) || defined(__VMS) #define HAS_PCAP_SENDPACKET 1 #else /* The latest libpcap and WinPcap all have pcap_sendpacket */ #if !defined (NEED_PCAP_SENDPACKET) #define HAS_PCAP_SENDPACKET 1 #endif #endif #if !defined (HAS_PCAP_SENDPACKET) /* libpcap has no function to write a packet, so we need to implement pcap_sendpacket() for compatibility with the WinPcap base code. Return value: 0=Success, -1=Failure */ int pcap_sendpacket(pcap_t* handle, const u_char* msg, int len) { #if defined (__linux) || defined (__linux__) return (send(pcap_fileno(handle), msg, len, 0) == len)? 0 : -1; #else return (write(pcap_fileno(handle), msg, len) == len)? 0 : -1; #endif /* linux */ } #endif /* !HAS_PCAP_SENDPACKET */ #if defined(_WIN32) || defined(__CYGWIN__) /* extracted from WinPcap's Packet32.h */ struct _PACKET_OID_DATA { uint32 Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h ///< for a complete list of valid codes. uint32 Length; ///< Length of the data field uint8 Data[1]; ///< variable-lenght field that contains the information passed to or received ///< from the adapter. }; typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA; typedef void **LPADAPTER; #define OID_802_3_CURRENT_ADDRESS 0x01010102 /* Extracted from ntddmdis.h */ static int pcap_mac_if_win32(const char *AdapterName, unsigned char MACAddress[6]) { LPADAPTER lpAdapter; PPACKET_OID_DATA OidData; int Status; int ReturnValue; #ifdef _WIN32 HMODULE hDll; /* handle to DLL */ #else static void *hDll = NULL; /* handle to Library */ typedef int BOOLEAN; #endif LPADAPTER (*p_PacketOpenAdapter)(const char *AdapterName); void (*p_PacketCloseAdapter)(LPADAPTER lpAdapter); int (*p_PacketRequest)(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData); #ifdef _WIN32 hDll = LoadLibraryA("packet.dll"); p_PacketOpenAdapter = (LPADAPTER (*)(const char *AdapterName))GetProcAddress(hDll, "PacketOpenAdapter"); p_PacketCloseAdapter = (void (*)(LPADAPTER lpAdapter))GetProcAddress(hDll, "PacketCloseAdapter"); p_PacketRequest = (int (*)(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData))GetProcAddress(hDll, "PacketRequest"); #else hDll = dlopen("packet.dll", RTLD_NOW); p_PacketOpenAdapter = (LPADAPTER (*)(const char *AdapterName))dlsym(hDll, "PacketOpenAdapter"); p_PacketCloseAdapter = (void (*)(LPADAPTER lpAdapter))dlsym(hDll, "PacketCloseAdapter"); p_PacketRequest = (int (*)(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData))dlsym(hDll, "PacketRequest"); #endif /* Open the selected adapter */ lpAdapter = p_PacketOpenAdapter(AdapterName); if (!lpAdapter || (*lpAdapter == (void *)-1)) { #ifdef _WIN32 FreeLibrary(hDll); #else dlclose(hDll); #endif return -1; } /* Allocate a buffer to get the MAC adress */ OidData = (PACKET_OID_DATA *)malloc(6 + sizeof(PACKET_OID_DATA)); if (OidData == NULL) { p_PacketCloseAdapter(lpAdapter); #ifdef _WIN32 FreeLibrary(hDll); #else dlclose(hDll); #endif return -1; } /* Retrieve the adapter MAC querying the NIC driver */ OidData->Oid = OID_802_3_CURRENT_ADDRESS; OidData->Length = 6; memset(OidData->Data, 0, 6); Status = p_PacketRequest(lpAdapter, FALSE, OidData); if(Status) { memcpy(MACAddress, OidData->Data, 6); ReturnValue = 0; } else ReturnValue = -1; free(OidData); p_PacketCloseAdapter(lpAdapter); #ifdef _WIN32 FreeLibrary(hDll); #else dlclose(hDll); #endif return ReturnValue; } #endif /* defined(_WIN32) || defined(__CYGWIN__) */ #if defined (__VMS) && !defined(__VAX) #include <descrip.h> #include <iodef.h> #include <ssdef.h> #include <starlet.h> #include <stdio.h> #include <stsdef.h> #include <nmadef.h> static int pcap_mac_if_vms(const char *AdapterName, unsigned char MACAddress[6]) { char VMS_Device[16]; $DESCRIPTOR(Device, VMS_Device); unsigned short iosb[4]; unsigned short *w; unsigned char *pha = NULL; unsigned char *hwa = NULL; int tmpval; int status; unsigned short characteristics[512]; long chardesc[] = {sizeof(characteristics), (long)&characteristics}; unsigned short chan; #pragma member_alignment save #pragma nomember_alignment static struct { short fmt; long val_fmt; short pty; long val_pty; short pad; long val_pad; } setup = { NMA$C_PCLI_FMT, NMA$C_LINFM_ETH, NMA$C_PCLI_PTY, 0x0090, NMA$C_PCLI_PAD, NMA$C_STATE_OFF, }; #pragma member_alignment restore long setupdesc[] = {sizeof(setup), (long)&setup}; /* Convert Interface Name to VMS Device Name */ /* This is a name shuffle */ /* WE0 becomes EWA0: */ /* SE1 becomes ESB0: */ /* XE0 becomes EXA0: */ tmpval = (int)(AdapterName[2]-'0'); if ((tmpval < 0) || (tmpval > 25)) return -1; VMS_Device[0] = toupper(AdapterName[1]); VMS_Device[1] = toupper(AdapterName[0]); VMS_Device[2] = 'A' + tmpval; VMS_Device[3] = '0'; VMS_Device[4] = '\0'; VMS_Device[5] = '\0'; Device.dsc$w_length = strlen(VMS_Device); if (!$VMS_STATUS_SUCCESS( sys$assign (&Device, &chan, 0, 0, 0) )) return -1; status = sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRL|IO$M_STARTUP, &iosb, 0, 0, 0, &setupdesc, 0, 0, 0, 0); if ((!$VMS_STATUS_SUCCESS(status)) || (!$VMS_STATUS_SUCCESS(iosb[0]))) { sys$dassgn(chan); return -1; } status = sys$qiow (0, chan, IO$_SENSEMODE|IO$M_CTRL, &iosb, 0, 0, 0, &chardesc, 0, 0, 0, 0); sys$dassgn(chan); if ((!$VMS_STATUS_SUCCESS(status)) || (!$VMS_STATUS_SUCCESS(iosb[0]))) return -1; for (w=characteristics; w < &characteristics[iosb[1]]; ) { if ((((*w)&0xFFF) == NMA$C_PCLI_HWA) && (6 == *(w+1))) hwa = (unsigned char *)(w + 2); if ((((*w)&0xFFF) == NMA$C_PCLI_PHA) && (6 == *(w+1))) pha = (unsigned char *)(w + 2); if (((*w)&0x1000) == 0) w += 3; /* Skip over Longword Parameter */ else w += (2 + ((1 + *(w+1))/2)); /* Skip over String Parameter */ } if (pha != NULL) /* Prefer Physical Address */ memcpy(MACAddress, pha, 6); else if (hwa != NULL) /* Fallback to Hardware Address */ memcpy(MACAddress, hwa, 6); else return -1; return 0; } #endif /* defined (__VMS) && !defined(__VAX) */ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname) { memset(&dev->host_nic_phy_hw_addr, 0, sizeof(dev->host_nic_phy_hw_addr)); dev->have_host_nic_phy_addr = 0; if (dev->eth_api != ETH_API_PCAP) return; #if defined(_WIN32) || defined(__CYGWIN__) if (!pcap_mac_if_win32(devname, dev->host_nic_phy_hw_addr)) dev->have_host_nic_phy_addr = 1; #elif defined (__VMS) && !defined(__VAX) if (!pcap_mac_if_vms(devname, dev->host_nic_phy_hw_addr)) dev->have_host_nic_phy_addr = 1; #elif !defined(__CYGWIN__) && !defined(__VMS) if (1) { char command[1024]; FILE *f; int i; const char *patterns[] = { "grep [0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]", "egrep [0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]", NULL}; memset(command, 0, sizeof(command)); for (i=0; patterns[i] && (0 == dev->have_host_nic_phy_addr); ++i) { snprintf(command, sizeof(command)-1, "ifconfig %s | %s >NIC.hwaddr", devname, patterns[i]); (void)system(command); if (NULL != (f = fopen("NIC.hwaddr", "r"))) { while (0 == dev->have_host_nic_phy_addr) { if (fgets(command, sizeof(command)-1, f)) { char *p1, *p2; p1 = strchr(command, ':'); while (p1) { p2 = strchr(p1+1, ':'); if (p2 <= p1+3) { unsigned int mac_bytes[6]; if (6 == sscanf(p1-2, "%02x:%02x:%02x:%02x:%02x:%02x", &mac_bytes[0], &mac_bytes[1], &mac_bytes[2], &mac_bytes[3], &mac_bytes[4], &mac_bytes[5])) { dev->host_nic_phy_hw_addr[0] = mac_bytes[0]; dev->host_nic_phy_hw_addr[1] = mac_bytes[1]; dev->host_nic_phy_hw_addr[2] = mac_bytes[2]; dev->host_nic_phy_hw_addr[3] = mac_bytes[3]; dev->host_nic_phy_hw_addr[4] = mac_bytes[4]; dev->host_nic_phy_hw_addr[5] = mac_bytes[5]; dev->have_host_nic_phy_addr = 1; } break; } p1 = p2; } } else break; } fclose(f); remove("NIC.hwaddr"); } } } #endif } #if defined(__APPLE__) #include <uuid/uuid.h> #include <unistd.h> static int _eth_get_system_id (char *buf, size_t buf_size) { static struct timespec wait = {5, 0}; /* 5 seconds */ static uuid_t uuid; memset (buf, 0, buf_size); if (buf_size < 37) return -1; if (gethostuuid (uuid, &wait)) memset (uuid, 0, sizeof(uuid)); uuid_unparse_lower(uuid, buf); return 0; } #elif defined(_WIN32) static int _eth_get_system_id (char *buf, size_t buf_size) { LONG status; DWORD reglen, regtype; HKEY reghnd; memset (buf, 0, buf_size); #ifndef KEY_WOW64_64KEY #define KEY_WOW64_64KEY (0x0100) #endif if ((status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Cryptography", 0, KEY_QUERY_VALUE|KEY_WOW64_64KEY, ®hnd)) != ERROR_SUCCESS) return -1; reglen = buf_size; if ((status = RegQueryValueExA (reghnd, "MachineGuid", NULL, ®type, buf, ®len)) != ERROR_SUCCESS) { RegCloseKey (reghnd); return -1; } RegCloseKey (reghnd ); /* make sure value is the right type, bail if not acceptable */ if ((regtype != REG_SZ) || (reglen > buf_size)) return -1; /* registry value seems OK */ return 0; } #else static int _eth_get_system_id (char *buf, size_t buf_size) { FILE *f; memset (buf, 0, buf_size); if ((f = fopen ("/etc/machine-id", "r"))) { fread (buf, 1, buf_size, f); fclose (f); } else { if ((f = popen ("hostname", "r"))) { fread (buf, 1, buf_size, f); pclose (f); } } while ((strlen (buf) > 0) && sim_isspace(buf[strlen (buf) - 1])) buf[strlen (buf) - 1] = '\0'; return 0; } #endif /* Forward declarations */ static void _eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* data); static t_stat _eth_write(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine); static void _eth_error(ETH_DEV* dev, const char* where); #if defined(HAVE_SLIRP_NETWORK) static void _slirp_callback (void *opaque, const unsigned char *buf, int len) { struct pcap_pkthdr header; memset(&header, 0, sizeof(header)); header.caplen = header.len = len; _eth_callback((u_char *)opaque, &header, buf); } #endif #if defined (USE_READER_THREAD) #include <pthread.h> static void * _eth_reader(void *arg) { ETH_DEV* volatile dev = (ETH_DEV*)arg; int status = 0; int sel_ret = 0; int do_select = 0; SOCKET select_fd = 0; #if defined (_WIN32) HANDLE hWait = (dev->eth_api == ETH_API_PCAP) ? pcap_getevent ((pcap_t*)dev->handle) : NULL; #endif switch (dev->eth_api) { case ETH_API_PCAP: #if defined (HAVE_PCAP_NETWORK) #if defined (MUST_DO_SELECT) do_select = 1; select_fd = pcap_get_selectable_fd((pcap_t *)dev->handle); #endif #endif break; case ETH_API_TAP: case ETH_API_VDE: case ETH_API_UDP: case ETH_API_NAT: do_select = 1; select_fd = dev->fd_handle; break; } sim_debug(dev->dbit, dev->dptr, "Reader Thread Starting\n"); /* Boost Priority for this I/O thread vs the CPU instruction execution thread which, in general, won't be readily yielding the processor when this thread needs to run */ sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); while (dev->handle) { #if defined (_WIN32) if (dev->eth_api == ETH_API_PCAP) { if (WAIT_OBJECT_0 == WaitForSingleObject (hWait, 250)) sel_ret = 1; } if ((dev->eth_api == ETH_API_UDP) || (dev->eth_api == ETH_API_NAT)) #endif /* _WIN32 */ if (1) { if (do_select) { #ifdef HAVE_SLIRP_NETWORK if (dev->eth_api == ETH_API_NAT) { sel_ret = sim_slirp_select ((SLIRP*)dev->handle, 250); } else #endif { fd_set setl; struct timeval timeout; FD_ZERO(&setl); FD_SET(select_fd, &setl); timeout.tv_sec = 0; timeout.tv_usec = 250*1000; sel_ret = select(1+select_fd, &setl, NULL, NULL, &timeout); } } else sel_ret = 1; if (sel_ret < 0 && errno != EINTR) break; } if (sel_ret > 0) { if (!dev->handle) break; /* dispatch read request queue available packets */ switch (dev->eth_api) { #ifdef HAVE_PCAP_NETWORK case ETH_API_PCAP: status = pcap_dispatch ((pcap_t*)dev->handle, -1, &_eth_callback, (u_char*)dev); break; #endif #ifdef HAVE_TAP_NETWORK case ETH_API_TAP: if (1) { struct pcap_pkthdr header; int len; u_char buf[ETH_MAX_JUMBO_FRAME]; memset(&header, 0, sizeof(header)); len = read(dev->fd_handle, buf, sizeof(buf)); if (len > 0) { status = 1; header.caplen = header.len = len; _eth_callback((u_char *)dev, &header, buf); } else { if (len < 0) status = -1; else status = 0; } } break; #endif /* HAVE_TAP_NETWORK */ #ifdef HAVE_VDE_NETWORK case ETH_API_VDE: if (1) { struct pcap_pkthdr header; int len; u_char buf[ETH_MAX_JUMBO_FRAME]; memset(&header, 0, sizeof(header)); len = vde_recv((VDECONN *)dev->handle, buf, sizeof(buf), 0); if (len > 0) { status = 1; header.caplen = header.len = len; _eth_callback((u_char *)dev, &header, buf); } else { if (len < 0) status = -1; else status = 0; } } break; #endif /* HAVE_VDE_NETWORK */ #ifdef HAVE_SLIRP_NETWORK case ETH_API_NAT: sim_slirp_dispatch ((SLIRP*)dev->handle); status = 1; break; #endif /* HAVE_SLIRP_NETWORK */ case ETH_API_UDP: if (1) { struct pcap_pkthdr header; int len; u_char buf[ETH_MAX_JUMBO_FRAME]; memset(&header, 0, sizeof(header)); len = (int)sim_read_sock (select_fd, (char *)buf, (int32)sizeof(buf)); if (len > 0) { status = 1; header.caplen = header.len = len; _eth_callback((u_char *)dev, &header, buf); } else { if (len < 0) status = -1; else status = 0; } } break; } if ((status > 0) && (dev->asynch_io)) { int wakeup_needed; pthread_mutex_lock (&dev->lock); wakeup_needed = (dev->read_queue.count != 0); pthread_mutex_unlock (&dev->lock); if (wakeup_needed) { sim_debug(dev->dbit, dev->dptr, "Queueing automatic poll\n"); sim_activate_abs (dev->dptr->units, dev->asynch_io_latency); } } if (status < 0) { ++dev->receive_packet_errors; _eth_error (dev, "_eth_reader"); if (dev->handle) { /* Still attached? */ #if defined (_WIN32) hWait = (dev->eth_api == ETH_API_PCAP) ? pcap_getevent ((pcap_t*)dev->handle) : NULL; #endif if (do_select) { select_fd = dev->fd_handle; #if !defined (_WIN32) && defined(HAVE_PCAP_NETWORK) if (dev->eth_api == ETH_API_PCAP) select_fd = pcap_get_selectable_fd((pcap_t *)dev->handle); #endif } } } } } sim_debug(dev->dbit, dev->dptr, "Reader Thread Exiting\n"); return NULL; } static void * _eth_writer(void *arg) { ETH_DEV* volatile dev = (ETH_DEV*)arg; ETH_WRITE_REQUEST *request; /* Boost Priority for this I/O thread vs the CPU instruction execution thread which in general won't be readily yielding the processor when this thread needs to run */ sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); sim_debug(dev->dbit, dev->dptr, "Writer Thread Starting\n"); pthread_mutex_lock (&dev->writer_lock); while (dev->handle) { pthread_cond_wait (&dev->writer_cond, &dev->writer_lock); while (NULL != (request = dev->write_requests)) { /* Pull buffer off request list */ dev->write_requests = request->next; pthread_mutex_unlock (&dev->writer_lock); if (dev->throttle_delay != ETH_THROT_DISABLED_DELAY) { uint32 packet_delta_time = sim_os_msec() - dev->throttle_packet_time; dev->throttle_events <<= 1; dev->throttle_events += (packet_delta_time < dev->throttle_time) ? 1 : 0; if ((dev->throttle_events & dev->throttle_mask) == dev->throttle_mask) { sim_os_ms_sleep (dev->throttle_delay); ++dev->throttle_count; } dev->throttle_packet_time = sim_os_msec(); } dev->write_status = _eth_write(dev, &request->packet, NULL); pthread_mutex_lock (&dev->writer_lock); /* Put buffer on free buffer list */ request->next = dev->write_buffers; dev->write_buffers = request; } } pthread_mutex_unlock (&dev->writer_lock); sim_debug(dev->dbit, dev->dptr, "Writer Thread Exiting\n"); return NULL; } #endif t_stat eth_set_async (ETH_DEV *dev, int latency) { #if !defined(USE_READER_THREAD) || !defined(SIM_ASYNCH_IO) char *msg = "Eth: can't operate asynchronously, must poll\r\n"; sim_printf ("%s", msg); return SCPE_NOFNC; #else int wakeup_needed; dev->asynch_io = 1; dev->asynch_io_latency = latency; pthread_mutex_lock (&dev->lock); wakeup_needed = (dev->read_queue.count != 0); pthread_mutex_unlock (&dev->lock); if (wakeup_needed) { sim_debug(dev->dbit, dev->dptr, "Queueing automatic poll\n"); sim_activate_abs (dev->dptr->units, dev->asynch_io_latency); } #endif return SCPE_OK; } t_stat eth_clr_async (ETH_DEV *dev) { #if !defined(USE_READER_THREAD) || !defined(SIM_ASYNCH_IO) return SCPE_NOFNC; #else /* make sure device exists */ if (!dev) return SCPE_UNATT; dev->asynch_io = 0; return SCPE_OK; #endif } t_stat eth_set_throttle (ETH_DEV* dev, uint32 time, uint32 burst, uint32 delay) { if (!dev) return SCPE_IERR; dev->throttle_time = time; dev->throttle_burst = burst; dev->throttle_delay = delay; dev->throttle_mask = (1 << dev->throttle_burst) - 1; return SCPE_OK; } static t_stat _eth_open_port(char *savname, int *eth_api, void **handle, SOCKET *fd_handle, char errbuf[PCAP_ERRBUF_SIZE], char *bpf_filter, void *opaque, DEVICE *dptr, uint32 dbit) { int bufsz = (BUFSIZ < ETH_MAX_PACKET) ? ETH_MAX_PACKET : BUFSIZ; if (bufsz < ETH_MAX_JUMBO_FRAME) bufsz = ETH_MAX_JUMBO_FRAME; /* Enable handling of jumbo frames */ *eth_api = 0; *handle = NULL; *fd_handle = 0; /* attempt to connect device */ memset(errbuf, 0, PCAP_ERRBUF_SIZE); if (0 == strncmp("tap:", savname, 4)) { int tun = -1; /* TUN/TAP Socket */ int on = 1; const char *devname = savname + 4; while (isspace(*devname)) ++devname; #if defined(HAVE_TAP_NETWORK) if (!strcmp(savname, "tap:tapN")) { sim_printf ("Eth: Must specify actual tap device name (i.e. tap:tap0)\r\n"); return SCPE_OPENERR | SCPE_NOMESSAGE; } #endif #if (defined(__linux) || defined(__linux__)) && defined(HAVE_TAP_NETWORK) if ((tun = open("/dev/net/tun", O_RDWR)) >= 0) { struct ifreq ifr; /* Interface Requests */ memset(&ifr, 0, sizeof(ifr)); /* Set up interface flags */ strcpy(ifr.ifr_name, devname); ifr.ifr_flags = IFF_TAP|IFF_NO_PI; /* Send interface requests to TUN/TAP driver. */ if (ioctl(tun, TUNSETIFF, &ifr) >= 0) { if (ioctl(tun, FIONBIO, &on)) { strncpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE-1); close(tun); } else { *fd_handle = tun; strcpy(savname, ifr.ifr_name); } } else strncpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE-1); } else strncpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE-1); #elif defined(HAVE_BSDTUNTAP) && defined(HAVE_TAP_NETWORK) if (1) { char dev_name[64] = ""; snprintf(dev_name, sizeof(dev_name)-1, "/dev/%s", devname); dev_name[sizeof(dev_name)-1] = '\0'; if ((tun = open(dev_name, O_RDWR)) >= 0) { if (ioctl(tun, FIONBIO, &on)) { strncpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE-1); close(tun); } else { *fd_handle = tun; strcpy(savname, devname); } #if defined (__APPLE__) if (1) { struct ifreq ifr; int s; memset (&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, savname, sizeof(ifr.ifr_name)); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) >= 0) { ifr.ifr_flags |= IFF_UP; if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr)) { strncpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE-1); close(tun); } } close(s); } } #endif } else strncpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE-1); } #else strncpy(errbuf, "No support for tap: devices", PCAP_ERRBUF_SIZE-1); #endif /* !defined(__linux) && !defined(HAVE_BSDTUNTAP) */ if (0 == errbuf[0]) { *eth_api = ETH_API_TAP; *handle = (void *)1; /* Flag used to indicated open */ } } else { /* !tap: */ if (0 == strncmp("vde:", savname, 4)) { #if defined(HAVE_VDE_NETWORK) struct vde_open_args voa; const char *devname = savname + 4; memset(&voa, 0, sizeof(voa)); if (!strcmp(savname, "vde:vdedevice")) { sim_printf ("Eth: Must specify actual vde device name (i.e. vde:/tmp/switch)\r\n"); return SCPE_OPENERR | SCPE_NOMESSAGE; } while (isspace(*devname)) ++devname; if (!(*handle = (void*) vde_open((char *)devname, (char *)"simh", &voa))) strncpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE-1); else { *eth_api = ETH_API_VDE; *fd_handle = vde_datafd((VDECONN*)(*handle)); } #else strncpy(errbuf, "No support for vde: network devices", PCAP_ERRBUF_SIZE-1); #endif /* defined(HAVE_VDE_NETWORK) */ } else { /* !vde: */ if (0 == strncmp("nat:", savname, 4)) { #if defined(HAVE_SLIRP_NETWORK) const char *devname = savname + 4; while (isspace(*devname)) ++devname; if (!(*handle = (void*) sim_slirp_open(devname, opaque, &_slirp_callback, dptr, dbit))) strncpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE-1); else { *eth_api = ETH_API_NAT; *fd_handle = 0; } #else strncpy(errbuf, "No support for nat: network devices", PCAP_ERRBUF_SIZE-1); #endif /* defined(HAVE_SLIRP_NETWORK) */ } else { /* not nat: */ if (0 == strncmp("udp:", savname, 4)) { char localport[CBUFSIZE], host[CBUFSIZE], port[CBUFSIZE]; char hostport[2*CBUFSIZE]; const char *devname = savname + 4; if (!strcmp(savname, "udp:sourceport:remotehost:remoteport")) { sim_printf ("Eth: Must specify actual udp host and ports(i.e. udp:1224:somehost.com:2234)\r\n"); return SCPE_OPENERR | SCPE_NOMESSAGE; } while (isspace(*devname)) ++devname; if (SCPE_OK != sim_parse_addr_ex (devname, host, sizeof(host), "localhost", port, sizeof(port), localport, sizeof(localport), NULL)) return SCPE_OPENERR; if (localport[0] == '\0') strcpy (localport, port); sprintf (hostport, "%s:%s", host, port); if ((SCPE_OK == sim_parse_addr (hostport, NULL, 0, NULL, NULL, 0, NULL, "localhost")) && (0 == strcmp (localport, port))) { sim_printf ("Eth: Must specify different udp localhost ports\r\n"); return SCPE_OPENERR | SCPE_NOMESSAGE; } *fd_handle = sim_connect_sock_ex (localport, hostport, NULL, NULL, SIM_SOCK_OPT_DATAGRAM); if (INVALID_SOCKET == *fd_handle) return SCPE_OPENERR; *eth_api = ETH_API_UDP; *handle = (void *)1; /* Flag used to indicated open */ } else { /* not udp:, so attempt to open the parameter as if it were an explicit device name */ #if defined(HAVE_PCAP_NETWORK) *handle = (void*) pcap_open_live(savname, bufsz, ETH_PROMISC, PCAP_READ_TIMEOUT, errbuf); if (!*handle) { /* can't open device */ sim_printf ("Eth: pcap_open_live error - %s\r\n", errbuf); return SCPE_OPENERR | SCPE_NOMESSAGE; } *eth_api = ETH_API_PCAP; #if !defined(HAS_PCAP_SENDPACKET) && defined (xBSD) && !defined (__APPLE__) /* Tell the kernel that the header is fully-formed when it gets it. This is required in order to fake the src address. */ if (1) { int one = 1; ioctl(pcap_fileno(*handle), BIOCSHDRCMPLT, &one); } #endif /* xBSD */ #if defined(_WIN32) pcap_setmintocopy ((pcap_t*)(*handle), 0); #endif #if !defined (USE_READER_THREAD) #ifdef USE_SETNONBLOCK /* set ethernet device non-blocking so pcap_dispatch() doesn't hang */ if (pcap_setnonblock (*handle, 1, errbuf) == -1) { sim_printf ("Eth: Failed to set non-blocking: %s\r\n", errbuf); } #endif #if defined (__APPLE__) if (1) { /* Deliver packets immediately, needed for OS X 10.6.2 and later * (Snow-Leopard). * See this thread on libpcap and Mac Os X 10.6 Snow Leopard on * the tcpdump mailinglist: http://seclists.org/tcpdump/2010/q1/110 */ int v = 1; ioctl(pcap_fileno(*handle), BIOCIMMEDIATE, &v); } #endif /* defined (__APPLE__) */ #endif /* !defined (USE_READER_THREAD) */ #else strncpy (errbuf, "Unknown or unsupported network device", PCAP_ERRBUF_SIZE-1); #endif /* defined(HAVE_PCAP_NETWORK) */ } /* not udp:, so attempt to open the parameter as if it were an explicit device name */ } /* !nat: */ } /* !vde: */ } /* !tap: */ if (errbuf[0]) return SCPE_OPENERR; #ifdef USE_BPF if (bpf_filter && (*eth_api == ETH_API_PCAP)) { struct bpf_program bpf; int status; bpf_u_int32 bpf_subnet, bpf_netmask; if (pcap_lookupnet(savname, &bpf_subnet, &bpf_netmask, errbuf)<0) bpf_netmask = 0; /* compile filter string */ if ((status = pcap_compile((pcap_t*)(*handle), &bpf, bpf_filter, 1, bpf_netmask)) < 0) { sprintf(errbuf, "%s", pcap_geterr((pcap_t*)(*handle))); sim_printf("Eth: pcap_compile error: %s\r\n", errbuf); /* show erroneous BPF string */ sim_printf ("Eth: BPF string is: |%s|\r\n", bpf_filter); } else { /* apply compiled filter string */ if ((status = pcap_setfilter((pcap_t*)(*handle), &bpf)) < 0) { sprintf(errbuf, "%s", pcap_geterr((pcap_t*)(*handle))); sim_printf("Eth: pcap_setfilter error: %s\r\n", errbuf); } else { #ifdef USE_SETNONBLOCK /* set file non-blocking */ status = pcap_setnonblock ((pcap_t*)(*handle), 1, errbuf); #endif /* USE_SETNONBLOCK */ } pcap_freecode(&bpf); } } #endif /* USE_BPF */ return SCPE_OK; } t_stat eth_open(ETH_DEV* dev, const char* name, DEVICE* dptr, uint32 dbit) { t_stat r; int bufsz = (BUFSIZ < ETH_MAX_PACKET) ? ETH_MAX_PACKET : BUFSIZ; char errbuf[PCAP_ERRBUF_SIZE]; char temp[1024], desc[1024] = ""; const char* savname = name; char namebuf[4*CBUFSIZE]; int num; if (bufsz < ETH_MAX_JUMBO_FRAME) bufsz = ETH_MAX_JUMBO_FRAME; /* Enable handling of jumbo frames */ /* initialize device */ eth_zero(dev); /* translate name of type "ethX" to real device name */ if ((strlen(name) == 4) && (tolower(name[0]) == 'e') && (tolower(name[1]) == 't') && (tolower(name[2]) == 'h') && isdigit(name[3]) ) { num = atoi(&name[3]); savname = eth_getname(num, temp, desc); if (savname == NULL) /* didn't translate */ return SCPE_OPENERR; } else { /* are they trying to use device description? */ savname = eth_getname_bydesc(name, temp, desc); if (savname == NULL) { /* didn't translate */ /* probably is not ethX and has no description */ savname = eth_getname_byname(name, temp, desc); if (savname == NULL) {/* didn't translate */ savname = name; desc[0] = '\0'; /* no description */ } } } namebuf[sizeof(namebuf)-1] = '\0'; strncpy (namebuf, savname, sizeof(namebuf)-1); savname = namebuf; r = _eth_open_port(namebuf, &dev->eth_api, &dev->handle, &dev->fd_handle, errbuf, NULL, (void *)dev, dptr, dbit); if (errbuf[0]) { sim_printf ("Eth: open error - %s\r\n", errbuf); return SCPE_OPENERR | SCPE_NOMESSAGE; } if (r != SCPE_OK) return r; if (!strcmp (desc, "No description available")) strcpy (desc, ""); sim_printf ("Eth: opened OS device %s%s%s\r\n", savname, desc[0] ? " - " : "", desc); /* get the NIC's hardware MAC address */ eth_get_nic_hw_addr(dev, savname); /* save name of device */ dev->name = (char *)malloc(strlen(savname)+1); strcpy(dev->name, savname); /* save debugging information */ dev->dptr = dptr; dev->dbit = dbit; #if defined (USE_READER_THREAD) if (1) { pthread_attr_t attr; ethq_init (&dev->read_queue, 200); /* initialize FIFO queue */ pthread_mutex_init (&dev->lock, NULL); pthread_mutex_init (&dev->writer_lock, NULL); pthread_mutex_init (&dev->self_lock, NULL); pthread_cond_init (&dev->writer_cond, NULL); pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); #if defined(__hpux) { /* libpcap needs sizeof(long) * 8192 bytes on the stack */ size_t stack_size; const size_t min_stack_size = sizeof(long) * 8192 * 3 / 2; if (!pthread_attr_getstacksize(&attr, &stack_size) && stack_size < min_stack_size) { pthread_attr_setstacksize(&attr, min_stack_size); } } #endif /* defined(__hpux) */ pthread_create (&dev->reader_thread, &attr, _eth_reader, (void *)dev); pthread_create (&dev->writer_thread, &attr, _eth_writer, (void *)dev); pthread_attr_destroy(&attr); } #endif /* defined (USE_READER_THREAD */ _eth_add_to_open_list (dev); return SCPE_OK; } static t_stat _eth_close_port(int eth_api, pcap_t *pcap, SOCKET pcap_fd) { switch (eth_api) { #ifdef HAVE_PCAP_NETWORK case ETH_API_PCAP: pcap_close(pcap); break; #endif #ifdef HAVE_TAP_NETWORK case ETH_API_TAP: close(pcap_fd); break; #endif #ifdef HAVE_VDE_NETWORK case ETH_API_VDE: vde_close((VDECONN*)pcap); break; #endif #ifdef HAVE_SLIRP_NETWORK case ETH_API_NAT: sim_slirp_close((SLIRP*)pcap); break; #endif case ETH_API_UDP: sim_close_sock(pcap_fd); break; } return SCPE_OK; } t_stat eth_close(ETH_DEV* dev) { pcap_t *pcap; SOCKET pcap_fd; /* make sure device exists */ if (!dev) return SCPE_UNATT; /* close the device */ pcap_fd = dev->fd_handle; /* save handle to possibly close later */ pcap = (pcap_t *)dev->handle; dev->handle = NULL; dev->fd_handle = 0; dev->have_host_nic_phy_addr = 0; #if defined (USE_READER_THREAD) pthread_join (dev->reader_thread, NULL); pthread_mutex_destroy (&dev->lock); pthread_cond_signal (&dev->writer_cond); pthread_join (dev->writer_thread, NULL); pthread_mutex_destroy (&dev->self_lock); pthread_mutex_destroy (&dev->writer_lock); pthread_cond_destroy (&dev->writer_cond); if (1) { ETH_WRITE_REQUEST *buffer; while (NULL != (buffer = dev->write_buffers)) { dev->write_buffers = buffer->next; free(buffer); } while (NULL != (buffer = dev->write_requests)) { dev->write_requests = buffer->next; free(buffer); } } ethq_destroy (&dev->read_queue); /* release FIFO queue */ #endif _eth_close_port (dev->eth_api, pcap, pcap_fd); sim_printf ("Eth: closed %s\r\n", dev->name); /* clean up the mess */ free(dev->name); free(dev->bpf_filter); eth_zero(dev); _eth_remove_from_open_list (dev); return SCPE_OK; } t_stat eth_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { fprintf (st, "%s attach help\n\n", dptr->name); fprintf (st, " sim> SHOW ETHERNET\n"); fprintf (st, " libpcap version 1.0.0\n"); fprintf (st, " ETH devices:\n"); fprintf (st, " eth0 en0 (No description available)\n"); #if defined(HAVE_TAP_NETWORK) fprintf (st, " eth1 tap:tapN (Integrated Tun/Tap support)\n"); #endif #if defined(HAVE_SLIRP_NETWORK) fprintf (st, " eth2 vde:device (Integrated VDE support)\n"); #endif #if defined(HAVE_SLIRP_NETWORK) fprintf (st, " eth3 nat:{optional-nat-parameters} (Integrated NAT (SLiRP) support)\n"); #endif fprintf (st, " eth4 udp:sourceport:remotehost:remoteport (Integrated UDP bridge support)\n"); fprintf (st, " sim> ATTACH %s eth0\n\n", dptr->name); fprintf (st, "or equivalently:\n\n"); fprintf (st, " sim> ATTACH %s en0\n\n", dptr->name); #if defined(HAVE_SLIRP_NETWORK) sim_slirp_attach_help (st, dptr, uptr, flag, cptr); #endif return SCPE_OK; } static int _eth_rand_byte() { static int rand_initialized = 0; if (!rand_initialized) srand((unsigned int)sim_os_msec()); return (rand() & 0xFF); } t_stat eth_check_address_conflict (ETH_DEV* dev, ETH_MAC* const mac) { ETH_PACK send, recv; t_stat status; uint32 i; int responses = 0; uint32 offset, function; char mac_string[32]; eth_mac_fmt(mac, mac_string); sim_debug(dev->dbit, dev->dptr, "Determining Address Conflict for MAC address: %s\n", mac_string); /* The process of checking address conflicts is used in two ways: 1) to determine the behavior of the currently running packet delivery facility regarding whether it may receive copies of every packet sent (and how many). 2) to verify if a MAC address which this facility is planning to use as the source address of packets is already in use by some other node on the local network Case #1, doesn't require (and explicitly doesn't want) any interaction or response from other systems on the LAN so therefore no considerations regarding switch packet forwarding are important. Meanwhile, Case #2 does require responses from other components on the LAN to provide useful functionality. The original designers of this mechanism did this when essentially all LANs were single collision domains (i.e. ALL nodes which might be affected by an address conflict were physically present on a single Ethernet cable which might have been extended by a couple of repeaters). Since that time, essentially no networks are single collision domains. Thick and thinwire Ethernet cables don't exist and very few networks even have hubs. Today, essentially all LANs are deployed using one or more layers of network switches. In a switched LAN environment, the switches on the LAN "learn" which ports on the LAN source traffic from which MAC addresses and then forward traffic destined for particular MAC address to the appropriate ports. If a particular MAC address is already in use somewhere on the LAN, then the switches "know" where it is. The host based test using the loopback protocol is poorly designed to detect this condition. This test is performed by the host first changing the device's Physical MAC address to the address which is to be tested, and then sending a loopback packet FROM AND TO this MAC address with a loopback reply to be sent by a system which may be currently using the MAC address. If no reply is received, then the MAC address is presumed to be unused. The sending of this packet will result in its delivery to the right system since the switch port/MAC address tables know where to deliver packets destined to this MAC address, however the response it generates won't be delivered to the system performing the test since the switches on the LAN won't know about the local port being the right target for packets with this MAC address. A better test design to detect these conflicts would be for the testing system to send a loopback packet FROM the current physical MAC address (BEFORE changing it) TO the MAC address being tested with the loopback response coming to the current physical MAC address of the device. If a response is received, then the address is in use and the attempt to change the device's MAC address should fail. Since we can't change the software running in these simulators to implement this better conflict detection approach, we can still "do the right thing" in the sim_ether layer. We're already handling the loopback test packets specially since we always had to avoid receiving the packets which were being sent, but needed to allow for the incoming loopback packets to be properly dealt with. We can extend this current special handling to change outgoing "loopback to self" packets to have source AND loopback destination addresses in the packets to be the host NIC's physical address. The switch network will already know the correct MAC/port relationship for the host NIC's physical address, so loopback response packets will be delivered as needed. Code in _eth_write and _eth_callback provide the special handling to perform the described loopback packet adjustments, and code in eth_filter_hash makes sure that the loopback response packets are received. */ /* build a loopback forward request packet */ memset (&send, 0, sizeof(ETH_PACK)); send.len = ETH_MIN_PACKET; /* minimum packet size */ for (i=0; i<send.len; i++) send.msg[i] = _eth_rand_byte(); memcpy(&send.msg[0], mac, sizeof(ETH_MAC)); /* target address */ memcpy(&send.msg[6], mac, sizeof(ETH_MAC)); /* source address */ send.msg[12] = 0x90; /* loopback packet type */ send.msg[13] = 0; send.msg[14] = 0; /* Offset */ send.msg[15] = 0; send.msg[16] = 2; /* Forward */ send.msg[17] = 0; memcpy(&send.msg[18], mac, sizeof(ETH_MAC)); /* Forward Destination */ send.msg[24] = 1; /* Reply */ send.msg[25] = 0; eth_filter(dev, 1, (ETH_MAC *)mac, 0, 0); /* send the packet */ status = _eth_write (dev, &send, NULL); if (status != SCPE_OK) { const char *msg; msg = (dev->eth_api == ETH_API_PCAP) ? "Eth: Error Transmitting packet: %s\r\n" "You may need to run as root, or install a libpcap version\r\n" "which is at least 0.9 from your OS vendor or www.tcpdump.org\r\n" : "Eth: Error Transmitting packet: %s\r\n" "You may need to run as root.\r\n"; sim_printf(msg, strerror(errno)); return status; } sim_os_ms_sleep (300); /* time for a conflicting host to respond */ eth_packet_trace_detail (dev, send.msg, send.len, "Sent-Address-Check"); /* empty the read queue and count the responses */ do { memset (&recv, 0, sizeof(ETH_PACK)); status = eth_read (dev, &recv, NULL); eth_packet_trace_detail (dev, recv.msg, recv.len, "Recv-Address-Check"); offset = 16 + (recv.msg[14] | (recv.msg[15] << 8)); function = 0; if ((offset+2) < recv.len) function = recv.msg[offset] | (recv.msg[offset+1] << 8); if (((0 == memcmp(send.msg+12, recv.msg+12, 2)) && /* Protocol Match */ (function == 1) && /* Function is Reply */ (0 == memcmp(&send.msg[offset], &recv.msg[offset], send.len-offset))) || /* Content Match */ (0 == memcmp(send.msg, recv.msg, send.len))) /* Packet Match (Reflection) */ responses++; } while (recv.len > 0); sim_debug(dev->dbit, dev->dptr, "Address Conflict = %d\n", responses); return responses; } t_stat eth_reflect(ETH_DEV* dev) { /* Test with an address no NIC should have. */ /* We do this to avoid reflections from the wire, */ /* in the event that a simulated NIC has a MAC address conflict. */ static ETH_MAC mac = {0xfe,0xff,0xff,0xff,0xff,0xfe}; sim_debug(dev->dbit, dev->dptr, "Determining Reflections...\n"); dev->reflections = 0; dev->reflections = eth_check_address_conflict (dev, &mac); sim_debug(dev->dbit, dev->dptr, "Reflections = %d\n", dev->reflections); return dev->reflections; } static void _eth_error(ETH_DEV* dev, const char* where) { char msg[64]; const char *netname = ""; time_t now; time(&now); sim_printf ("%s", asctime(localtime(&now))); switch (dev->eth_api) { case ETH_API_PCAP: netname = "pcap"; break; case ETH_API_TAP: netname = "tap"; break; case ETH_API_VDE: netname = "vde"; break; case ETH_API_UDP: netname = "udp"; break; case ETH_API_NAT: netname = "nat"; break; } sprintf(msg, "%s(%s): ", where, netname); switch (dev->eth_api) { #if defined(HAVE_PCAP_NETWORK) case ETH_API_PCAP: sim_printf ("%s%s\n", msg, pcap_geterr ((pcap_t*)dev->handle)); break; #endif default: sim_err_sock (INVALID_SOCKET, msg); break; } #ifdef USE_READER_THREAD pthread_mutex_lock (&dev->lock); ++dev->error_waiting_threads; if (!dev->error_needs_reset) dev->error_needs_reset = (((dev->transmit_packet_errors + dev->receive_packet_errors)%ETH_ERROR_REOPEN_THRESHOLD) == 0); pthread_mutex_unlock (&dev->lock); #else dev->error_needs_reset = (((dev->transmit_packet_errors + dev->receive_packet_errors)%ETH_ERROR_REOPEN_THRESHOLD) == 0); #endif /* Limit errors to 1 per second (per invoking thread (reader and writer)) */ sim_os_sleep (1); /* When all of the threads which can reference this ETH_DEV object are simultaneously waiting in this routine, we have the potential to close and reopen the network connection. We do this after ETH_ERROR_REOPEN_THRESHOLD total errors have occurred. In practice could be as frequently as once every ETH_ERROR_REOPEN_THRESHOLD/2 seconds, but normally would be about once every 1.5*ETH_ERROR_REOPEN_THRESHOLD seconds (ONLY when the error condition exists). */ #ifdef USE_READER_THREAD pthread_mutex_lock (&dev->lock); if ((dev->error_waiting_threads == 2) && (dev->error_needs_reset)) { #else if (dev->error_needs_reset) { #endif char errbuf[PCAP_ERRBUF_SIZE]; t_stat r; _eth_close_port(dev->eth_api, (pcap_t *)dev->handle, dev->fd_handle); sim_os_sleep (ETH_ERROR_REOPEN_PAUSE); r = _eth_open_port(dev->name, &dev->eth_api, &dev->handle, &dev->fd_handle, errbuf, dev->bpf_filter, (void *)dev, dev->dptr, dev->dbit); dev->error_needs_reset = FALSE; if (r == SCPE_OK) sim_printf ("%s ReOpened: %s \n", msg, dev->name); else sim_printf ("%s ReOpen Attempt Failed: %s - %s\n", msg, dev->name, errbuf); ++dev->error_reopen_count; } #ifdef USE_READER_THREAD --dev->error_waiting_threads; pthread_mutex_unlock (&dev->lock); #endif } static t_stat _eth_write(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) { int status = 1; /* default to failure */ /* make sure device exists */ if ((!dev) || (dev->eth_api == ETH_API_NONE)) return SCPE_UNATT; /* make sure packet exists */ if (!packet) return SCPE_ARG; /* make sure packet is acceptable length */ if ((packet->len >= ETH_MIN_PACKET) && (packet->len <= ETH_MAX_PACKET)) { int loopback_self_frame = LOOPBACK_SELF_FRAME(packet->msg, packet->msg); int loopback_physical_response = LOOPBACK_PHYSICAL_RESPONSE(dev, packet->msg); eth_packet_trace (dev, packet->msg, packet->len, "writing"); /* record sending of loopback packet (done before actual send to avoid race conditions with receiver) */ if (loopback_self_frame || loopback_physical_response) { /* Direct loopback responses to the host physical address since our physical address may not have been learned yet. */ if (loopback_self_frame && dev->have_host_nic_phy_addr) { memcpy(&packet->msg[6], dev->host_nic_phy_hw_addr, sizeof(ETH_MAC)); memcpy(&packet->msg[18], dev->host_nic_phy_hw_addr, sizeof(ETH_MAC)); eth_packet_trace (dev, packet->msg, packet->len, "writing-fixed"); } #ifdef USE_READER_THREAD pthread_mutex_lock (&dev->self_lock); #endif dev->loopback_self_sent += dev->reflections; dev->loopback_self_sent_total++; #ifdef USE_READER_THREAD pthread_mutex_unlock (&dev->self_lock); #endif } /* dispatch write request (synchronous; no need to save write info to dev) */ switch (dev->eth_api) { #ifdef HAVE_PCAP_NETWORK case ETH_API_PCAP: status = pcap_sendpacket((pcap_t*)dev->handle, (u_char*)packet->msg, packet->len); break; #endif #ifdef HAVE_TAP_NETWORK case ETH_API_TAP: status = (((int)packet->len == write(dev->fd_handle, (void *)packet->msg, packet->len)) ? 0 : -1); break; #endif #ifdef HAVE_VDE_NETWORK case ETH_API_VDE: status = vde_send((VDECONN*)dev->handle, (void *)packet->msg, packet->len, 0); if ((status == (int)packet->len) || (status == 0)) status = 0; else if ((status == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) status = 0; else status = 1; break; #endif #ifdef HAVE_SLIRP_NETWORK case ETH_API_NAT: status = sim_slirp_send((SLIRP*)dev->handle, (char *)packet->msg, (size_t)packet->len, 0); if ((status == (int)packet->len) || (status == 0)) status = 0; else status = 1; break; #endif case ETH_API_UDP: status = (((int32)packet->len == sim_write_sock (dev->fd_handle, (char *)packet->msg, (int32)packet->len)) ? 0 : -1); break; } ++dev->packets_sent; /* basic bookkeeping */ /* On error, correct loopback bookkeeping */ if ((status != 0) && loopback_self_frame) { #ifdef USE_READER_THREAD pthread_mutex_lock (&dev->self_lock); #endif dev->loopback_self_sent -= dev->reflections; dev->loopback_self_sent_total--; #ifdef USE_READER_THREAD pthread_mutex_unlock (&dev->self_lock); #endif } if (status != 0) { ++dev->transmit_packet_errors; _eth_error (dev, "_eth_write"); } } /* if packet->len */ /* call optional write callback function */ if (routine) (routine)(status); return ((status == 0) ? SCPE_OK : SCPE_IOERR); } t_stat eth_write(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) { #ifdef USE_READER_THREAD ETH_WRITE_REQUEST *request; int write_queue_size = 1; /* make sure device exists */ if ((!dev) || (dev->eth_api == ETH_API_NONE)) return SCPE_UNATT; /* Get a buffer */ pthread_mutex_lock (&dev->writer_lock); if (NULL != (request = dev->write_buffers)) dev->write_buffers = request->next; pthread_mutex_unlock (&dev->writer_lock); if (NULL == request) request = (ETH_WRITE_REQUEST *)malloc(sizeof(*request)); /* Copy buffer contents */ request->packet.len = packet->len; request->packet.used = packet->used; request->packet.status = packet->status; request->packet.crc_len = packet->crc_len; memcpy(request->packet.msg, packet->msg, packet->len); /* Insert buffer at the end of the write list (to make sure that */ /* packets make it to the wire in the order they were presented here) */ pthread_mutex_lock (&dev->writer_lock); request->next = NULL; if (dev->write_requests) { ETH_WRITE_REQUEST *last_request = dev->write_requests; ++write_queue_size; while (last_request->next) { last_request = last_request->next; ++write_queue_size; } last_request->next = request; } else dev->write_requests = request; if (write_queue_size > dev->write_queue_peak) dev->write_queue_peak = write_queue_size; pthread_mutex_unlock (&dev->writer_lock); /* Awaken writer thread to perform actual write */ pthread_cond_signal (&dev->writer_cond); /* Return with a status from some prior write */ if (routine) (routine)(dev->write_status); return dev->write_status; #else return _eth_write(dev, packet, routine); #endif } static int _eth_hash_lookup(ETH_MULTIHASH hash, const u_char* data) { int key = 0x3f & (eth_crc32(0, data, 6) >> 26); key ^= 0x3f; return (hash[key>>3] & (1 << (key&0x7))); } #if 0 static int _eth_hash_validate(ETH_MAC *MultiCastList, int count, ETH_MULTIHASH hash) { ETH_MULTIHASH lhash; int i; memset(lhash, 0, sizeof(lhash)); for (i=0; i<count; ++i) { int key = 0x3f & (eth_crc32(0, MultiCastList[i], 6) >> 26); key ^= 0x3F; printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X Key: %X, Byte: %X, Val: %X\n", MultiCastList[i][0], MultiCastList[i][1], MultiCastList[i][2], MultiCastList[i][3], MultiCastList[i][4], MultiCastList[i][5], key, key>>3, (1 << (key&0x7))); lhash[key>>3] |= (1 << (key&0x7)); } if (memcmp(hash, lhash, sizeof(lhash))) { printf("Inconsistent Computed Hash:\n"); printf("Should be: %02X %02X %02X %02X %02X %02X %02X %02X\n", hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7]); printf("Was: %02X %02X %02X %02X %02X %02X %02X %02X\n", lhash[0], lhash[1], lhash[2], lhash[3], lhash[4], lhash[5], lhash[6], lhash[7]); } else { printf("Should be: %02X %02X %02X %02X %02X %02X %02X %02X\n", hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7]); printf("Was: %02X %02X %02X %02X %02X %02X %02X %02X\n", lhash[0], lhash[1], lhash[2], lhash[3], lhash[4], lhash[5], lhash[6], lhash[7]); } return 0; } static void _eth_test_multicast_hash() { ETH_MAC tMacs[] = { {0xAB, 0x00, 0x04, 0x01, 0xAC, 0x10}, {0xAB, 0x00, 0x00, 0x04, 0x00, 0x00}, {0x09, 0x00, 0x2B, 0x00, 0x00, 0x0F}, {0x09, 0x00, 0x2B, 0x02, 0x01, 0x04}, {0x09, 0x00, 0x2B, 0x02, 0x01, 0x07}, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x01, 0x00, 0x5E, 0x00, 0x00, 0x01}}; ETH_MULTIHASH thash = {0x01, 0x40, 0x00, 0x00, 0x48, 0x88, 0x40, 0x00}; _eth_hash_validate(tMacs, sizeof(tMacs)/sizeof(tMacs[0]), thash); } #endif /* The IP header */ struct IPHeader { uint8 verhlen; /* Version & Header Length in dwords */ #define IP_HLEN(IP) (((IP)->verhlen&0xF)<<2) /* Header Length in Bytes */ #define IP_VERSION(IP) ((((IP)->verhlen)>>4)&0xF) /* IP Version */ uint8 tos; /* Type of service */ uint16 total_len; /* Length of the packet in dwords */ uint16 ident; /* unique identifier */ uint16 flags; /* Fragmentation Flags */ #define IP_DF_FLAG (0x4000) #define IP_MF_FLAG (0x2000) #define IP_OFFSET_MASK (0x1FFF) #define IP_FRAG_DF(IP) (ntohs(((IP)->flags))&IP_DF_FLAG) #define IP_FRAG_MF(IP) (ntohs(((IP)->flags))&IP_MF_FLAG) #define IP_FRAG_OFFSET(IP) (ntohs(((IP)->flags))&IP_OFFSET_MASK) uint8 ttl; /* Time to live */ uint8 proto; /* Protocol number (TCP, UDP etc) */ uint16 checksum; /* IP checksum */ uint32 source_ip; /* Source Address */ uint32 dest_ip; /* Destination Address */ }; /* ICMP header */ struct ICMPHeader { uint8 type; /* ICMP packet type */ uint8 code; /* Type sub code */ uint16 checksum; /* ICMP Checksum */ uint32 otherstuff[1];/* optional data */ }; struct UDPHeader { uint16 source_port; uint16 dest_port; uint16 length; /* The length of the entire UDP datagram, including both header and Data fields. */ uint16 checksum; }; struct TCPHeader { uint16 source_port; uint16 dest_port; uint32 sequence_number; uint32 acknowledgement_number; uint16 data_offset_and_flags; #define TCP_DATA_OFFSET(TCP) ((ntohs((TCP)->data_offset_and_flags)>>12)<<2) #define TCP_CWR_FLAG (0x80) #define TCP_ECR_FLAG (0x40) #define TCP_URG_FLAG (0x20) #define TCP_ACK_FLAG (0x10) #define TCP_PSH_FLAG (0x08) #define TCP_RST_FLAG (0x04) #define TCP_SYN_FLAG (0x02) #define TCP_FIN_FLAG (0x01) #define TCP_FLAGS_MASK (0xFFF) uint16 window; uint16 checksum; uint16 urgent; uint16 otherstuff[1]; /* The rest of the packet */ }; #ifndef IPPROTO_TCP #define IPPROTO_TCP 6 /* tcp */ #endif #ifndef IPPROTO_UDP #define IPPROTO_UDP 17 /* user datagram protocol */ #endif #ifndef IPPROTO_ICMP #define IPPROTO_ICMP 1 /* control message protocol */ #endif static uint16 ip_checksum(uint16 *buffer, int size) { unsigned long cksum = 0; /* Sum all the words together, adding the final byte if size is odd */ while (size > 1) { cksum += *buffer++; size -= sizeof(*buffer); } if (size) { uint16 endword; uint8 *endbytes = (uint8 *)&endword; endbytes[0] = *((uint8 *)buffer); endbytes[1] = 0; cksum += endword; } /* Do a little shuffling */ cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); /* Return the bitwise complement of the resulting mishmash */ return (uint16)(~cksum); } static uint16 pseudo_checksum(uint16 len, uint16 proto, uint16 *src_addr, uint16 *dest_addr, uint8 *buff) { uint32 sum; /* Sum the data first */ sum = 0xffff&(~ip_checksum((uint16 *)buff, len)); /* add the pseudo header which contains the IP source and destinationn addresses */ sum += src_addr[0]; sum += src_addr[1]; sum += dest_addr[0]; sum += dest_addr[1]; /* and the protocol number and the length of the UDP packet */ sum = sum + htons(proto) + htons(len); /* Do a little shuffling */ sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); /* Return the bitwise complement of the resulting mishmash */ return (uint16)(~sum); } static void _eth_fix_ip_jumbo_offload(ETH_DEV* dev, u_char* msg, int len) { const unsigned short* proto = (const unsigned short*) &msg[12]; struct IPHeader *IP; struct TCPHeader *TCP = NULL; struct UDPHeader *UDP; struct ICMPHeader *ICMP; uint16 orig_checksum; uint16 payload_len; uint16 mtu_payload; uint16 ip_flags; uint16 frag_offset; struct pcap_pkthdr header; uint16 orig_tcp_flags; /* Only interested in IP frames */ if (ntohs(*proto) != 0x0800) { ++dev->jumbo_dropped; /* Non IP Frames are dropped */ return; } IP = (struct IPHeader *)&msg[14]; if (IP_VERSION(IP) != 4) { ++dev->jumbo_dropped; /* Non IPv4 jumbo frames are dropped */ return; } if ((IP_HLEN(IP) > len) || (ntohs(IP->total_len) > len)) { ++dev->jumbo_dropped; /* Bogus header length frames are dropped */ return; } if (IP_FRAG_OFFSET(IP) || IP_FRAG_MF(IP)) { ++dev->jumbo_dropped; /* Previously fragmented, but currently jumbo sized frames are dropped */ return; } switch (IP->proto) { case IPPROTO_UDP: UDP = (struct UDPHeader *)(((char *)IP)+IP_HLEN(IP)); if (ntohs(UDP->length) > (len-IP_HLEN(IP))) { ++dev->jumbo_dropped; /* Bogus UDP packet length (packet contained length exceeds packet size) frames are dropped */ return; } if (UDP->checksum == 0) break; /* UDP Checksums are disabled */ orig_checksum = UDP->checksum; UDP->checksum = 0; UDP->checksum = pseudo_checksum(ntohs(UDP->length), IPPROTO_UDP, (uint16 *)(&IP->source_ip), (uint16 *)(&IP->dest_ip), (uint8 *)UDP); if (orig_checksum != UDP->checksum) eth_packet_trace (dev, msg, len, "reading jumbo UDP header Checksum Fixed"); break; case IPPROTO_ICMP: ICMP = (struct ICMPHeader *)(((char *)IP)+IP_HLEN(IP)); orig_checksum = ICMP->checksum; ICMP->checksum = 0; ICMP->checksum = ip_checksum((uint16 *)ICMP, ntohs(IP->total_len)-IP_HLEN(IP)); if (orig_checksum != ICMP->checksum) eth_packet_trace (dev, msg, len, "reading jumbo ICMP header Checksum Fixed"); break; case IPPROTO_TCP: TCP = (struct TCPHeader *)(((char *)IP)+IP_HLEN(IP)); if ((TCP_DATA_OFFSET(TCP) > (len-IP_HLEN(IP))) || (TCP_DATA_OFFSET(TCP) < 20)) { ++dev->jumbo_dropped; /* Bogus TCP packet header length (packet contained length exceeds packet size) frames are dropped */ return; } /* We don't do anything with the TCP checksum since we're going to resegment the TCP data below */ break; default: ++dev->jumbo_dropped; /* We onlt handle UDP, ICMP and TCP jumbo frames others are dropped */ return; } /* Reasonable Checksums are now in the jumbo packet, but we've got to actually */ /* deliver ONLY standard sized ethernet frames. Our job here is to now act as */ /* a router might have to and fragment these IPv4 frames as they are delivered */ /* into the virtual NIC. We do this by walking down the packet and dispatching */ /* a chunk at a time recomputing an appropriate header for each chunk. For */ /* datagram oriented protocols (UDP and ICMP) this is done by simple packet */ /* fragmentation. For TCP this is done by breaking large packets into separate */ /* TCP packets. */ memset(&header, 0, sizeof(header)); switch (IP->proto) { case IPPROTO_UDP: case IPPROTO_ICMP: ++dev->jumbo_fragmented; /* When we're performing LSO (Large Send Offload), we're given a 'template' header which may not include a value being populated in the IP header length (which is only 16 bits). We process as payload everything which isn't known header data. */ payload_len = (uint16)(len - (14 + IP_HLEN(IP))); mtu_payload = ETH_MIN_JUMBO_FRAME - (14 + IP_HLEN(IP)); frag_offset = 0; while (payload_len > 0) { ip_flags = frag_offset; if (payload_len > mtu_payload) { ip_flags |= IP_MF_FLAG; IP->total_len = htons(((mtu_payload>>3)<<3) + IP_HLEN(IP)); } else { IP->total_len = htons(payload_len + IP_HLEN(IP)); } IP->flags = htons(ip_flags); IP->checksum = 0; IP->checksum = ip_checksum((uint16 *)IP, IP_HLEN(IP)); header.caplen = header.len = 14 + ntohs(IP->total_len); eth_packet_trace (dev, ((u_char *)IP)-14, header.len, "reading Datagram fragment"); #if ETH_MIN_JUMBO_FRAME < ETH_MAX_PACKET if (1) { /* Debugging is easier if we read packets directly with pcap (i.e. we can use Wireshark to verify packet contents) we don't want to do this all the time for 2 reasons: 1) sending through pcap involves kernel transitions and 2) if the current system reflects sent packets, the recieving side will receive and process 2 copies of any packets sent this way. */ ETH_PACK pkt; memset(&pkt, 0, sizeof(pkt)); memcpy(pkt.msg, ((u_char *)IP)-14, header.len); pkt.len = header.len; _eth_write(dev, &pkt, NULL); } #else _eth_callback((u_char *)dev, &header, ((u_char *)IP)-14); #endif payload_len -= (ntohs(IP->total_len) - IP_HLEN(IP)); frag_offset += (ntohs(IP->total_len) - IP_HLEN(IP))>>3; if (payload_len > 0) { /* Move the MAC and IP headers down to just prior to the next payload segment */ memcpy(((u_char *)IP) + ntohs(IP->total_len) - (14 + IP_HLEN(IP)), ((u_char *)IP) - 14, 14 + IP_HLEN(IP)); IP = (struct IPHeader *)(((u_char *)IP) + ntohs(IP->total_len) - IP_HLEN(IP)); } } break; case IPPROTO_TCP: ++dev->jumbo_fragmented; eth_packet_trace_ex (dev, ((u_char *)IP)-14, len, "Fragmenting Jumbo TCP segment", 1, dev->dbit); TCP = (struct TCPHeader *)(((char *)IP)+IP_HLEN(IP)); orig_tcp_flags = ntohs(TCP->data_offset_and_flags); /* When we're performing LSO (Large Send Offload), we're given a 'template' header which may not include a value being populated in the IP header length (which is only 16 bits). We process as payload everything which isn't known header data. */ payload_len = (uint16)(len - (14 + IP_HLEN(IP) + TCP_DATA_OFFSET(TCP))); mtu_payload = ETH_MIN_JUMBO_FRAME - (14 + IP_HLEN(IP) + TCP_DATA_OFFSET(TCP)); while (payload_len > 0) { if (payload_len > mtu_payload) { TCP->data_offset_and_flags = htons(orig_tcp_flags&~(TCP_PSH_FLAG|TCP_FIN_FLAG|TCP_RST_FLAG)); IP->total_len = htons(mtu_payload + IP_HLEN(IP) + TCP_DATA_OFFSET(TCP)); } else { TCP->data_offset_and_flags = htons(orig_tcp_flags); IP->total_len = htons(payload_len + IP_HLEN(IP) + TCP_DATA_OFFSET(TCP)); } IP->checksum = 0; IP->checksum = ip_checksum((uint16 *)IP, IP_HLEN(IP)); TCP->checksum = 0; TCP->checksum = pseudo_checksum(ntohs(IP->total_len)-IP_HLEN(IP), IPPROTO_TCP, (uint16 *)(&IP->source_ip), (uint16 *)(&IP->dest_ip), (uint8 *)TCP); header.caplen = header.len = 14 + ntohs(IP->total_len); eth_packet_trace_ex (dev, ((u_char *)IP)-14, header.len, "reading TCP segment", 1, dev->dbit); #if ETH_MIN_JUMBO_FRAME < ETH_MAX_PACKET if (1) { /* Debugging is easier if we read packets directly with pcap (i.e. we can use Wireshark to verify packet contents) we don't want to do this all the time for 2 reasons: 1) sending through pcap involves kernel transitions and 2) if the current system reflects sent packets, the recieving side will receive and process 2 copies of any packets sent this way. */ ETH_PACK pkt; memset(&pkt, 0, sizeof(pkt)); memcpy(pkt.msg, ((u_char *)IP)-14, header.len); pkt.len = header.len; _eth_write(dev, &pkt, NULL); } #else _eth_callback((u_char *)dev, &header, ((u_char *)IP)-14); #endif payload_len -= (ntohs(IP->total_len) - (IP_HLEN(IP) + TCP_DATA_OFFSET(TCP))); if (payload_len > 0) { /* Move the MAC, IP and TCP headers down to just prior to the next payload segment */ memcpy(((u_char *)IP) + ntohs(IP->total_len) - (14 + IP_HLEN(IP) + TCP_DATA_OFFSET(TCP)), ((u_char *)IP) - 14, 14 + IP_HLEN(IP) + TCP_DATA_OFFSET(TCP)); IP = (struct IPHeader *)(((u_char *)IP) + ntohs(IP->total_len) - (IP_HLEN(IP) + TCP_DATA_OFFSET(TCP))); TCP = (struct TCPHeader *)(((char *)IP)+IP_HLEN(IP)); TCP->sequence_number = htonl(mtu_payload + ntohl(TCP->sequence_number)); } } break; } } static void _eth_fix_ip_xsum_offload(ETH_DEV* dev, const u_char* msg, int len) { const unsigned short* proto = (const unsigned short*) &msg[12]; struct IPHeader *IP; struct TCPHeader *TCP; struct UDPHeader *UDP; struct ICMPHeader *ICMP; uint16 orig_checksum; /* Only need to process locally originated packets */ if ((!dev->have_host_nic_phy_addr) || (memcmp(msg+6, dev->host_nic_phy_hw_addr, 6))) return; /* Only interested in IP frames */ if (ntohs(*proto) != 0x0800) return; IP = (struct IPHeader *)&msg[14]; if (IP_VERSION(IP) != 4) return; /* Only interested in IPv4 frames */ if ((IP_HLEN(IP) > len) || (ntohs(IP->total_len) > len)) return; /* Bogus header length */ orig_checksum = IP->checksum; IP->checksum = 0; IP->checksum = ip_checksum((uint16 *)IP, IP_HLEN(IP)); if (orig_checksum != IP->checksum) eth_packet_trace (dev, msg, len, "reading IP header Checksum Fixed"); if (IP_FRAG_OFFSET(IP) || IP_FRAG_MF(IP)) return; /* Insufficient data to compute payload checksum */ switch (IP->proto) { case IPPROTO_UDP: UDP = (struct UDPHeader *)(((char *)IP)+IP_HLEN(IP)); if (ntohs(UDP->length) > (len-IP_HLEN(IP))) return; /* packet contained length exceeds packet size */ if (UDP->checksum == 0) return; /* UDP Checksums are disabled */ orig_checksum = UDP->checksum; UDP->checksum = 0; UDP->checksum = pseudo_checksum(ntohs(UDP->length), IPPROTO_UDP, (uint16 *)(&IP->source_ip), (uint16 *)(&IP->dest_ip), (uint8 *)UDP); if (orig_checksum != UDP->checksum) eth_packet_trace (dev, msg, len, "reading UDP header Checksum Fixed"); break; case IPPROTO_TCP: TCP = (struct TCPHeader *)(((char *)IP)+IP_HLEN(IP)); orig_checksum = TCP->checksum; TCP->checksum = 0; TCP->checksum = pseudo_checksum(ntohs(IP->total_len)-IP_HLEN(IP), IPPROTO_TCP, (uint16 *)(&IP->source_ip), (uint16 *)(&IP->dest_ip), (uint8 *)TCP); if (orig_checksum != TCP->checksum) eth_packet_trace (dev, msg, len, "reading TCP header Checksum Fixed"); break; case IPPROTO_ICMP: ICMP = (struct ICMPHeader *)(((char *)IP)+IP_HLEN(IP)); orig_checksum = ICMP->checksum; ICMP->checksum = 0; ICMP->checksum = ip_checksum((uint16 *)ICMP, ntohs(IP->total_len)-IP_HLEN(IP)); if (orig_checksum != ICMP->checksum) eth_packet_trace (dev, msg, len, "reading ICMP header Checksum Fixed"); break; } } static int _eth_process_loopback (ETH_DEV* dev, const u_char* data, uint32 len) { int protocol = data[12] | (data[13] << 8); ETH_PACK response; uint32 offset, function; if (protocol != 0x0090) /* !ethernet loopback */ return 0; if (LOOPBACK_REFLECTION_TEST_PACKET(dev, data)) return 0; /* Ignore reflection check packet */ offset = 16 + (data[14] | (data[15] << 8)); if (offset >= len) return 0; function = data[offset] | (data[offset+1] << 8); if (function != 2) /*forward*/ return 0; /* The only packets we should be responding to are ones which we received due to them being directed to our physical MAC address, OR the Broadcast address OR to a Multicast address we're listening to (we may receive others if we're in promiscuous mode, but shouldn't respond to them) */ if ((0 == (data[0]&1)) && /* Multicast or Broadcast */ (0 != memcmp(dev->filter_address[0], data, sizeof(ETH_MAC)))) return 0; /* Attempts to forward to multicast or broadcast addresses are explicitly ignored by consuming the packet and doing nothing else */ if (data[offset+2]&1) return 1; eth_packet_trace (dev, data, len, "rcvd"); sim_debug(dev->dbit, dev->dptr, "_eth_process_loopback()\n"); /* create forward response packet */ memset(&response, 0, sizeof(response)); response.len = len; memcpy(response.msg, data, len); memcpy(&response.msg[0], &response.msg[offset+2], sizeof(ETH_MAC)); memcpy(&response.msg[6], dev->filter_address[0], sizeof(ETH_MAC)); offset += 8 - 16; /* Account for the Ethernet Header and Offset value in this number */ response.msg[14] = offset & 0xFF; response.msg[15] = (offset >> 8) & 0xFF; /* send response packet */ eth_write(dev, &response, NULL); eth_packet_trace(dev, response.msg, response.len, ((function == 1) ? "loopbackreply" : "loopbackforward")); ++dev->loopback_packets_processed; return 1; } static void _eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* data) { ETH_DEV* dev = (ETH_DEV*) info; int to_me; int from_me = 0; int i; int bpf_used; if (LOOPBACK_PHYSICAL_RESPONSE(dev, data)) { u_char *datacopy = (u_char *)malloc(header->len); /* Since we changed the outgoing loopback packet to have the physical MAC address of the host's interface instead of the programmatically set physical address of this pseudo device, we restore parts of the modified packet back as needed */ memcpy(datacopy, data, header->len); memcpy(datacopy, dev->physical_addr, sizeof(ETH_MAC)); memcpy(datacopy+18, dev->physical_addr, sizeof(ETH_MAC)); _eth_callback(info, header, datacopy); free(datacopy); return; } switch (dev->eth_api) { case ETH_API_PCAP: #ifdef USE_BPF bpf_used = 1; to_me = 1; /* AUTODIN II hash mode? */ if ((dev->hash_filter) && (data[0] & 0x01) && (!dev->promiscuous) && (!dev->all_multicast)) to_me = _eth_hash_lookup(dev->hash, data); break; #endif /* USE_BPF */ case ETH_API_TAP: case ETH_API_VDE: case ETH_API_UDP: case ETH_API_NAT: bpf_used = 0; to_me = 0; eth_packet_trace (dev, data, header->len, "received"); for (i = 0; i < dev->addr_count; i++) { if (memcmp(data, dev->filter_address[i], 6) == 0) to_me = 1; if (memcmp(&data[6], dev->filter_address[i], 6) == 0) from_me = 1; } /* all multicast mode? */ if (dev->all_multicast && (data[0] & 0x01)) to_me = 1; /* promiscuous mode? */ if (dev->promiscuous) to_me = 1; /* AUTODIN II hash mode? */ if ((dev->hash_filter) && (!to_me) && (data[0] & 0x01)) to_me = _eth_hash_lookup(dev->hash, data); break; default: bpf_used = to_me = 0; /* Should NEVER happen */ abort(); break; } /* detect reception of loopback packet to our physical address */ if ((LOOPBACK_SELF_FRAME(dev->physical_addr, data)) || (LOOPBACK_PHYSICAL_REFLECTION(dev, data))) { #ifdef USE_READER_THREAD pthread_mutex_lock (&dev->self_lock); #endif dev->loopback_self_rcvd_total++; /* lower reflection count - if already zero, pass it on */ if (dev->loopback_self_sent > 0) { eth_packet_trace (dev, data, header->len, "ignored"); dev->loopback_self_sent--; to_me = 0; } else if (!bpf_used) from_me = 0; #ifdef USE_READER_THREAD pthread_mutex_unlock (&dev->self_lock); #endif } if (bpf_used ? to_me : (to_me && !from_me)) { if (header->len > ETH_MIN_JUMBO_FRAME) { if (header->len <= header->caplen) {/* Whole Frame captured? */ u_char *datacopy = (u_char *)malloc(header->len); memcpy(datacopy, data, header->len); _eth_fix_ip_jumbo_offload(dev, datacopy, header->len); free(datacopy); } else ++dev->jumbo_truncated; return; } if (_eth_process_loopback(dev, data, header->len)) return; #if defined (USE_READER_THREAD) if (1) { int crc_len = 0; uint8 crc_data[4]; uint32 len = header->len; u_char *moved_data = NULL; if (header->len < ETH_MIN_PACKET) { /* Pad runt packets before CRC append */ moved_data = (u_char *)malloc(ETH_MIN_PACKET); memcpy(moved_data, data, len); memset(moved_data + len, 0, ETH_MIN_PACKET-len); len = ETH_MIN_PACKET; data = moved_data; } /* If necessary, fix IP header checksums for packets originated locally */ /* but were presumed to be traversing a NIC which was going to handle that task */ /* This must be done before any needed CRC calculation */ _eth_fix_ip_xsum_offload(dev, (const u_char*)data, len); if (dev->need_crc) crc_len = eth_get_packet_crc32_data(data, len, crc_data); eth_packet_trace (dev, data, len, "rcvqd"); pthread_mutex_lock (&dev->lock); ethq_insert_data(&dev->read_queue, ETH_ITM_NORMAL, data, 0, len, crc_len, crc_data, 0); ++dev->packets_received; pthread_mutex_unlock (&dev->lock); free(moved_data); } #else /* !USE_READER_THREAD */ /* set data in passed read packet */ dev->read_packet->len = header->len; memcpy(dev->read_packet->msg, data, header->len); /* Handle runt case and pad with zeros. */ /* The real NIC won't hand us runts from the wire, BUT we may be getting */ /* some packets looped back before they actually traverse the wire */ /* (by an internal bridge device for instance) */ if (header->len < ETH_MIN_PACKET) { memset(&dev->read_packet->msg[header->len], 0, ETH_MIN_PACKET-header->len); dev->read_packet->len = ETH_MIN_PACKET; } /* If necessary, fix IP header checksums for packets originated by the local host */ /* but were presumed to be traversing a NIC which was going to handle that task */ /* This must be done before any needed CRC calculation */ _eth_fix_ip_xsum_offload(dev, dev->read_packet->msg, dev->read_packet->len); if (dev->need_crc) dev->read_packet->crc_len = eth_add_packet_crc32(dev->read_packet->msg, dev->read_packet->len); else dev->read_packet->crc_len = 0; eth_packet_trace (dev, dev->read_packet->msg, dev->read_packet->len, "reading"); ++dev->packets_received; /* call optional read callback function */ if (dev->read_callback) (dev->read_callback)(0); #endif } } int eth_read(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) { int status; /* make sure device exists */ if ((!dev) || (dev->eth_api == ETH_API_NONE)) return 0; /* make sure packet exists */ if (!packet) return 0; packet->len = 0; #if !defined (USE_READER_THREAD) /* set read packet */ dev->read_packet = packet; /* set optional callback routine */ dev->read_callback = routine; /* dispatch read request to either receive a filtered packet or timeout */ do { switch (dev->eth_api) { #ifdef HAVE_PCAP_NETWORK case ETH_API_PCAP: status = pcap_dispatch((pcap_t*)dev->handle, 1, &_eth_callback, (u_char*)dev); break; #endif #ifdef HAVE_TAP_NETWORK case ETH_API_TAP: if (1) { struct pcap_pkthdr header; int len; u_char buf[ETH_MAX_JUMBO_FRAME]; memset(&header, 0, sizeof(header)); len = read(dev->fd_handle, buf, sizeof(buf)); if (len > 0) { status = 1; header.caplen = header.len = len; _eth_callback((u_char *)dev, &header, buf); } else { if (len < 0) status = -1; else status = 0; } } break; #endif /* HAVE_TAP_NETWORK */ #ifdef HAVE_VDE_NETWORK case ETH_API_VDE: if (1) { struct pcap_pkthdr header; int len; u_char buf[ETH_MAX_JUMBO_FRAME]; memset(&header, 0, sizeof(header)); len = vde_recv((VDECONN*)dev->handle, buf, sizeof(buf), 0); if (len > 0) { status = 1; header.caplen = header.len = len; _eth_callback((u_char *)dev, &header, buf); } else { if (len < 0) status = -1; else status = 0; } } break; #endif /* HAVE_VDE_NETWORK */ case ETH_API_UDP: if (1) { struct pcap_pkthdr header; int len; u_char buf[ETH_MAX_JUMBO_FRAME]; memset(&header, 0, sizeof(header)); len = (int)sim_read_sock (dev->fd_handle, (char *)buf, (int32)sizeof(buf)); if (len > 0) { status = 1; header.caplen = header.len = len; _eth_callback((u_char *)dev, &header, buf); } else { if (len < 0) status = -1; else status = 0; } } break; } } while ((status > 0) && (0 == packet->len)); if (status < 0) { ++dev->receive_packet_errors; _eth_error (dev, "eth_reader"); } #else /* USE_READER_THREAD */ status = 0; pthread_mutex_lock (&dev->lock); if (dev->read_queue.count > 0) { ETH_ITEM* item = &dev->read_queue.item[dev->read_queue.head]; packet->len = item->packet.len; packet->crc_len = item->packet.crc_len; memcpy(packet->msg, item->packet.msg, ((packet->len > packet->crc_len) ? packet->len : packet->crc_len)); status = 1; ethq_remove(&dev->read_queue); } pthread_mutex_unlock (&dev->lock); if ((status) && (routine)) routine(0); #endif return status; } t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses, ETH_BOOL all_multicast, ETH_BOOL promiscuous) { return eth_filter_hash(dev, addr_count, addresses, all_multicast, promiscuous, NULL); } t_stat eth_filter_hash(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses, ETH_BOOL all_multicast, ETH_BOOL promiscuous, ETH_MULTIHASH* const hash) { int i; char buf[116+66*ETH_FILTER_MAX]; char errbuf[PCAP_ERRBUF_SIZE]; char mac[20]; char* buf2; t_stat status; #ifdef USE_BPF struct bpf_program bpf; #endif /* make sure device exists */ if (!dev) return SCPE_UNATT; /* filter count OK? */ if ((addr_count < 0) || (addr_count > ETH_FILTER_MAX)) return SCPE_ARG; else if (!addresses) return SCPE_ARG; /* test reflections. This is done early in this routine since eth_reflect */ /* calls eth_filter recursively and thus changes the state of the device. */ if (dev->reflections == -1) status = eth_reflect(dev); /* set new filter addresses */ for (i = 0; i < addr_count; i++) memcpy(dev->filter_address[i], addresses[i], sizeof(ETH_MAC)); dev->addr_count = addr_count; /* store other flags */ dev->all_multicast = all_multicast; dev->promiscuous = promiscuous; /* store multicast hash data */ dev->hash_filter = (hash != NULL); if (hash) { memcpy(dev->hash, hash, sizeof(*hash)); sim_debug(dev->dbit, dev->dptr, "Multicast Hash: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n", dev->hash[0], dev->hash[1], dev->hash[2], dev->hash[3], dev->hash[4], dev->hash[5], dev->hash[6], dev->hash[7]); } /* print out filter information if debugging */ if (dev->dptr->dctrl & dev->dbit) { sim_debug(dev->dbit, dev->dptr, "Filter Set\n"); for (i = 0; i < addr_count; i++) { char mac[20]; eth_mac_fmt(&dev->filter_address[i], mac); sim_debug(dev->dbit, dev->dptr, " Addr[%d]: %s\n", i, mac); } if (dev->all_multicast) { sim_debug(dev->dbit, dev->dptr, "All Multicast\n"); } if (dev->promiscuous) { sim_debug(dev->dbit, dev->dptr, "Promiscuous\n"); } } /* setup BPF filters and other fields to minimize packet delivery */ strcpy(buf, ""); /* construct destination filters - since the real ethernet interface was set into promiscuous mode by eth_open(), we need to filter out the packets that our simulated interface doesn't want. */ if (!dev->promiscuous) { for (i = 0; i < addr_count; i++) { eth_mac_fmt(&dev->filter_address[i], mac); if (!strstr(buf, mac)) /* eliminate duplicates */ sprintf(&buf[strlen(buf)], "%s(ether dst %s)", (*buf) ? " or " : "((", mac); } if (dev->all_multicast || dev->hash_filter) sprintf(&buf[strlen(buf)], "%s(ether multicast)", (*buf) ? " or " : "(("); if (strlen(buf) > 0) sprintf(&buf[strlen(buf)], ")"); } /* construct source filters - this prevents packets from being reflected back by systems where WinPcap and libpcap cause packet reflections. Note that some systems do not reflect packets at all. This *assumes* that the simulated NIC will not send out packets with multicast source fields. */ if ((addr_count > 0) && (dev->reflections > 0)) { if (strlen(buf) > 0) sprintf(&buf[strlen(buf)], " and "); sprintf (&buf[strlen(buf)], "not ("); buf2 = &buf[strlen(buf)]; for (i = 0; i < addr_count; i++) { if (dev->filter_address[i][0] & 0x01) continue; /* skip multicast addresses */ eth_mac_fmt(&dev->filter_address[i], mac); if (!strstr(buf2, mac)) /* eliminate duplicates */ sprintf(&buf2[strlen(buf2)], "%s(ether src %s)", (*buf2) ? " or " : "", mac); } sprintf (&buf[strlen(buf)], ")"); if (1 == strlen(buf2)) { /* all addresses were multicast? */ buf[strlen(buf)-6] = '\0'; /* Remove "not ()" */ if (strlen(buf) > 0) buf[strlen(buf)-5] = '\0'; /* remove " and " */ } } if (strlen(buf) > 0) sprintf(&buf[strlen(buf)], ")"); /* When changing the Physical Address on a LAN interface, VMS sends out a loopback packet with the source and destination addresses set to the same value as the Physical Address which is being setup. This packet is designed to find and help diagnose MAC address conflicts (which also include DECnet address conflicts). Normally, this packet would not be seen by the sender, only by the other machine that has the same Physical Address (or possibly DECnet address). If the ethernet subsystem is reflecting packets, the network startup will fail to start if it sees the reflected packet, since it thinks another system is using this Physical Address (or DECnet address). We have to let these packets through, so that if another machine has the same Physical Address (or DECnet address) that we can detect it. Both eth_write() and _eth_callback() help by checking the reflection count - eth_write() adds the reflection count to dev->loopback_self_sent, and _eth_callback() check the value - if the dev->loopback_self_sent count is zero, then the packet has come from another machine with the same address, and needs to be passed on to the simulated machine. */ memset(dev->physical_addr, 0, sizeof(ETH_MAC)); dev->loopback_self_sent = 0; /* check for physical address in filters */ if ((addr_count) && (dev->reflections > 0)) { for (i = 0; i < addr_count; i++) { if (dev->filter_address[i][0]&1) continue; /* skip all multicast addresses */ eth_mac_fmt(&dev->filter_address[i], mac); if (strcmp(mac, "00:00:00:00:00:00") != 0) { memcpy(dev->physical_addr, &dev->filter_address[i], sizeof(ETH_MAC)); /* let packets through where dst and src are the same as our physical address */ sprintf (&buf[strlen(buf)], " or ((ether dst %s) and (ether src %s))", mac, mac); if (dev->have_host_nic_phy_addr) { eth_mac_fmt(&dev->host_nic_phy_hw_addr, mac); sprintf(&buf[strlen(buf)], " or ((ether dst %s) and (ether proto 0x9000))", mac); } break; } } } if ((0 == strlen(buf)) && (!dev->promiscuous)) /* Empty filter means match nothing */ strcpy(buf, "ether host fe:ff:ff:ff:ff:ff"); /* this should be a good match nothing filter */ sim_debug(dev->dbit, dev->dptr, "BPF string is: |%s|\n", buf); /* get netmask, which is a required argument for compiling. The value, in our case isn't actually interesting since the filters we generate aren't referencing IP fields, networks or values */ #ifdef USE_BPF if (dev->eth_api == ETH_API_PCAP) { bpf_u_int32 bpf_subnet, bpf_netmask; if (pcap_lookupnet(dev->name, &bpf_subnet, &bpf_netmask, errbuf)<0) bpf_netmask = 0; /* compile filter string */ if ((status = pcap_compile((pcap_t*)dev->handle, &bpf, buf, 1, bpf_netmask)) < 0) { sprintf(errbuf, "%s", pcap_geterr((pcap_t*)dev->handle)); sim_printf("Eth: pcap_compile error: %s\r\n", errbuf); /* show erroneous BPF string */ sim_printf ("Eth: BPF string is: |%s|\r\n", buf); } else { /* apply compiled filter string */ if ((status = pcap_setfilter((pcap_t*)dev->handle, &bpf)) < 0) { sprintf(errbuf, "%s", pcap_geterr((pcap_t*)dev->handle)); sim_printf("Eth: pcap_setfilter error: %s\r\n", errbuf); } else { /* Save BPF filter string */ dev->bpf_filter = (char *)realloc(dev->bpf_filter, 1 + strlen(buf)); strcpy (dev->bpf_filter, buf); #ifdef USE_SETNONBLOCK /* set file non-blocking */ status = pcap_setnonblock (dev->handle, 1, errbuf); #endif /* USE_SETNONBLOCK */ } pcap_freecode(&bpf); } #ifdef USE_READER_THREAD pthread_mutex_lock (&dev->lock); ethq_clear (&dev->read_queue); /* Empty FIFO Queue when filter list changes */ pthread_mutex_unlock (&dev->lock); #endif } #endif /* USE_BPF */ return SCPE_OK; } /* The libpcap provided API pcap_findalldevs() on most platforms, will leverage the getifaddrs() API if it is available in preference to alternate platform specific methods of determining the interface list. A limitation of getifaddrs() is that it returns only interfaces which have associated addresses. This may not include all of the interesting interfaces that we are interested in since a host may have dedicated interfaces for a simulator, which is otherwise unused by the host. One could hand craft the the build of libpcap to specifically use alternate methods to implement pcap_findalldevs(). However, this can get tricky, and would then result in a sort of deviant libpcap. This routine exists to allow platform specific code to validate and/or extend the set of available interfaces to include any that are not returned by pcap_findalldevs. */ int eth_host_devices(int used, int max, ETH_LIST* list) { pcap_t* conn = NULL; int i, j, datalink = 0; char errbuf[PCAP_ERRBUF_SIZE]; for (i=0; i<used; ++i) { /* Cull any non-ethernet interface types */ #if defined(HAVE_PCAP_NETWORK) conn = pcap_open_live(list[i].name, ETH_MAX_PACKET, ETH_PROMISC, PCAP_READ_TIMEOUT, errbuf); if (NULL != conn) datalink = pcap_datalink(conn), pcap_close(conn); list[i].eth_api = ETH_API_PCAP; #endif if ((NULL == conn) || (datalink != DLT_EN10MB)) { for (j=i; j<used-1; ++j) list[j] = list[j+1]; --used; --i; } } /* for */ #if defined(_WIN32) /* replace device description with user-defined adapter name (if defined) */ for (i=0; i<used; i++) { char regkey[2048]; unsigned char regval[2048]; LONG status; DWORD reglen, regtype; HKEY reghnd; /* These registry keys don't seem to exist for all devices, so we simply ignore errors. */ /* Windows XP x64 registry uses wide characters by default, so we force use of narrow characters by using the 'A'(ANSI) version of RegOpenKeyEx. This could cause some problems later, if this code is internationalized. Ideally, the pcap lookup will return wide characters, and we should use them to build a wide registry key, rather than hardcoding the string as we do here. */ if (list[i].name[strlen( "\\Device\\NPF_" )] == '{') { sprintf( regkey, "SYSTEM\\CurrentControlSet\\Control\\Network\\" "{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", list[i].name+ strlen( "\\Device\\NPF_" ) ); if ((status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, regkey, 0, KEY_QUERY_VALUE, ®hnd)) != ERROR_SUCCESS) continue; reglen = sizeof(regval); /* look for user-defined adapter name, bail if not found */ /* same comment about Windows XP x64 (above) using RegQueryValueEx */ if ((status = RegQueryValueExA (reghnd, "Name", NULL, ®type, regval, ®len)) != ERROR_SUCCESS) { RegCloseKey (reghnd); continue; } /* make sure value is the right type, bail if not acceptable */ if ((regtype != REG_SZ) || (reglen > sizeof(regval))) { RegCloseKey (reghnd); continue; } /* registry value seems OK, finish up and replace description */ RegCloseKey (reghnd ); sprintf (list[i].desc, "%s", regval); } } /* for */ #endif #ifdef HAVE_TAP_NETWORK if (used < max) { #if defined(__OpenBSD__) sprintf(list[used].name, "%s", "tap:tunN"); #else sprintf(list[used].name, "%s", "tap:tapN"); #endif sprintf(list[used].desc, "%s", "Integrated Tun/Tap support"); list[used].eth_api = ETH_API_TAP; ++used; } #endif #ifdef HAVE_VDE_NETWORK if (used < max) { sprintf(list[used].name, "%s", "vde:device"); sprintf(list[used].desc, "%s", "Integrated VDE support"); list[used].eth_api = ETH_API_VDE; ++used; } #endif #ifdef HAVE_SLIRP_NETWORK if (used < max) { sprintf(list[used].name, "%s", "nat:{optional-nat-parameters}"); sprintf(list[used].desc, "%s", "Integrated NAT (SLiRP) support"); list[used].eth_api = ETH_API_NAT; ++used; } #endif if (used < max) { sprintf(list[used].name, "%s", "udp:sourceport:remotehost:remoteport"); sprintf(list[used].desc, "%s", "Integrated UDP bridge support"); list[used].eth_api = ETH_API_UDP; ++used; } return used; } int eth_devices(int max, ETH_LIST* list) { int i = 0; char errbuf[PCAP_ERRBUF_SIZE]; #ifndef DONT_USE_PCAP_FINDALLDEVS pcap_if_t* alldevs; pcap_if_t* dev; memset(list, 0, max*sizeof(*list)); errbuf[0] = '\0'; /* retrieve the device list */ if (pcap_findalldevs(&alldevs, errbuf) == -1) { sim_printf ("Eth: error in pcap_findalldevs: %s\r\n", errbuf); } else { /* copy device list into the passed structure */ for (i=0, dev=alldevs; dev && (i < max); dev=dev->next, ++i) { if ((dev->flags & PCAP_IF_LOOPBACK) || (!strcmp("any", dev->name))) continue; strncpy(list[i].name, dev->name, sizeof(list[i].name)-1); if (dev->description) strncpy(list[i].desc, dev->description, sizeof(list[i].desc)-1); else strncpy(list[i].desc, "No description available", sizeof(list[i].desc)-1); } /* free device list */ pcap_freealldevs(alldevs); } #endif /* Add any host specific devices and/or validate those already found */ i = eth_host_devices(i, max, list); /* If no devices were found and an error message was left in the buffer, display it */ if ((i == 0) && (errbuf[0])) { sim_printf ("Eth: pcap_findalldevs warning: %s\r\n", errbuf); } /* return device count */ return i; } void eth_show_dev (FILE *st, ETH_DEV* dev) { fprintf(st, "Ethernet Device:\n"); if (!dev) { fprintf(st, "-- Not Attached\n"); return; } fprintf(st, " Name: %s\n", dev->name); fprintf(st, " Reflections: %d\n", dev->reflections); fprintf(st, " Self Loopbacks Sent: %d\n", dev->loopback_self_sent_total); fprintf(st, " Self Loopbacks Rcvd: %d\n", dev->loopback_self_rcvd_total); if (dev->have_host_nic_phy_addr) { char hw_mac[20]; eth_mac_fmt(&dev->host_nic_phy_hw_addr, hw_mac); fprintf(st, " Host NIC Address: %s\n", hw_mac); } if (dev->jumbo_dropped) fprintf(st, " Jumbo Dropped: %d\n", dev->jumbo_dropped); if (dev->jumbo_fragmented) fprintf(st, " Jumbo Fragmented: %d\n", dev->jumbo_fragmented); if (dev->jumbo_truncated) fprintf(st, " Jumbo Truncated: %d\n", dev->jumbo_truncated); if (dev->packets_sent) fprintf(st, " Packets Sent: %d\n", dev->packets_sent); if (dev->transmit_packet_errors) fprintf(st, " Send Packet Errors: %d\n", dev->transmit_packet_errors); if (dev->packets_received) fprintf(st, " Packets Received: %d\n", dev->packets_received); if (dev->receive_packet_errors) fprintf(st, " Read Packet Errors: %d\n", dev->receive_packet_errors); if (dev->error_reopen_count) fprintf(st, " Error ReOpen Count: %d\n", dev->error_reopen_count); if (dev->loopback_packets_processed) fprintf(st, " Loopback Packets: %d\n", dev->loopback_packets_processed); #if defined(USE_READER_THREAD) fprintf(st, " Asynch Interrupts: %s\n", dev->asynch_io?"Enabled":"Disabled"); if (dev->asynch_io) fprintf(st, " Interrupt Latency: %d uSec\n", dev->asynch_io_latency); if (dev->throttle_count) fprintf(st, " Throttle Delays: %d\n", dev->throttle_count); fprintf(st, " Read Queue: Count: %d\n", dev->read_queue.count); fprintf(st, " Read Queue: High: %d\n", dev->read_queue.high); fprintf(st, " Read Queue: Loss: %d\n", dev->read_queue.loss); fprintf(st, " Peak Write Queue Size: %d\n", dev->write_queue_peak); #endif if (dev->bpf_filter) fprintf(st, " BPF Filter: %s\n", dev->bpf_filter); #if defined(HAVE_SLIRP_NETWORK) if (dev->eth_api == ETH_API_NAT) sim_slirp_show ((SLIRP *)dev->handle, st); #endif } #endif /* USE_NETWORK */ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | /* sim_ether.h: OS-dependent network information ------------------------------------------------------------------------------ Copyright (c) 2002-2005, David T. Hittner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the author shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. ------------------------------------------------------------------------------ Modification history: 01-Mar-12 AGN Cygwin doesn't have non-blocking pcap I/O pcap (it uses WinPcap) 17-Nov-11 MP Added dynamic loading of libpcap on *nix platforms 30-Oct-11 MP Added support for vde (Virtual Distributed Ethernet) networking 18-Apr-11 MP Fixed race condition with self loopback packets in multithreaded environments 09-Dec-10 MP Added support to determine if network address conflicts exist 07-Dec-10 MP Reworked DECnet self detection to the more general approach of loopback self when any Physical Address is being set. 04-Dec-10 MP Changed eth_write to do nonblocking writes when USE_READER_THREAD is defined. 07-Feb-08 MP Added eth_show_dev to display ethernet state 28-Jan-08 MP Added eth_set_async 23-Jan-08 MP Added eth_packet_trace_ex and ethq_destroy 30-Nov-05 DTH Added CRC length to packet and more field comments 04-Feb-04 DTH Added debugging information 14-Jan-04 MP Generalized BSD support issues 05-Jan-04 DTH Added eth_mac_scan 26-Dec-03 DTH Added ethernet show and queue functions from pdp11_xq 23-Dec-03 DTH Added status to packet 01-Dec-03 DTH Added reflections, tweaked decnet fix items 25-Nov-03 DTH Verified DECNET_FIX, reversed ifdef to mainstream code 14-Nov-03 DTH Added #ifdef DECNET_FIX for problematic duplicate detection code 07-Jun-03 MP Added WIN32 support for DECNET duplicate address detection. 05-Jun-03 DTH Added used to struct eth_packet 01-Feb-03 MP Changed some uint8 strings to char* to reflect usage 22-Oct-02 DTH Added all_multicast and promiscuous support 21-Oct-02 DTH Corrected copyright again 16-Oct-02 DTH Fixed copyright 08-Oct-02 DTH Integrated with 2.10-0p4, added variable vector and copyrights 03-Oct-02 DTH Beta version of xq/sim_ether released for SIMH 2.09-11 15-Aug-02 DTH Started XQ simulation ------------------------------------------------------------------------------ */ #ifndef SIM_ETHER_H #define SIM_ETHER_H #include "sim_defs.h" #include "sim_sock.h" #ifdef __cplusplus extern "C" { #endif /* make common BSD code a bit easier to read in this file */ /* OS/X seems to define and compile using one of these BSD types */ #if defined(__NetBSD__) || defined (__OpenBSD__) || defined (__FreeBSD__) #define xBSD 1 #endif #if !defined(__FreeBSD__) && !defined(_WIN32) && !defined(VMS) && !defined(__CYGWIN__) && !defined(__APPLE__) #define USE_SETNONBLOCK 1 #endif /* cygwin dowsn't have the right features to use the threaded network I/O */ #if defined(__CYGWIN__) || defined(__ZAURUS__) // psco added check for Zaurus platform #define DONT_USE_READER_THREAD #endif #if ((((defined(__sun) || defined(__sun__)) && defined(__i386__)) || defined(__linux)) && !defined(DONT_USE_READER_THREAD)) #define USE_READER_THREAD 1 #endif #if defined(DONT_USE_READER_THREAD) #undef USE_READER_THREAD #endif /* make common winpcap code a bit easier to read in this file */ #if defined(_WIN32) || defined(VMS) || defined(__CYGWIN__) #define PCAP_READ_TIMEOUT -1 #else #define PCAP_READ_TIMEOUT 1 #endif /* set related values to have correct relationships */ #if defined (USE_READER_THREAD) #if defined (USE_SETNONBLOCK) #undef USE_SETNONBLOCK #endif /* USE_SETNONBLOCK */ #undef PCAP_READ_TIMEOUT #define PCAP_READ_TIMEOUT 15 #if (!defined (xBSD) && !defined(_WIN32) && !defined(VMS) && !defined(__CYGWIN__)) || defined (HAVE_TAP_NETWORK) || defined (HAVE_VDE_NETWORK) #define MUST_DO_SELECT 1 #endif #endif /* USE_READER_THREAD */ /* give priority to USE_NETWORK over USE_SHARED */ #if defined(USE_NETWORK) && defined(USE_SHARED) #undef USE_SHARED #endif /* USE_SHARED only works on Windows or if HAVE_DLOPEN */ #if defined(USE_SHARED) && !defined(_WIN32) && !defined(HAVE_DLOPEN) #undef USE_SHARED #endif /* USE_SHARED implies shared pcap, so force HAVE_PCAP_NETWORK */ #if defined(USE_SHARED) && !defined(HAVE_PCAP_NETWORK) #define HAVE_PCAP_NETWORK 1 #endif /* USE_BPF is defined to let this code leverage the libpcap/OS kernel provided BPF packet filtering. This generally will enhance performance. It may not be available in some environments and/or it may not work correctly, so undefining this will still provide working code here. */ #if defined(HAVE_PCAP_NETWORK) #define USE_BPF 1 #if defined (_WIN32) && !defined (BPF_CONST_STRING) #define BPF_CONST_STRING 1 #endif #else #define DONT_USE_PCAP_FINDALLDEVS 1 #endif #if defined (USE_READER_THREAD) #include <pthread.h> #endif /* structure declarations */ #define ETH_PROMISC 1 /* promiscuous mode = true */ #define ETH_TIMEOUT -1 /* read timeout in milliseconds (immediate) */ #define ETH_FILTER_MAX 20 /* maximum address filters */ #define ETH_DEV_NAME_MAX 256 /* maximum device name size */ #define ETH_DEV_DESC_MAX 256 /* maximum device description size */ #define ETH_MIN_PACKET 60 /* minimum ethernet packet size */ #define ETH_MAX_PACKET 1514 /* maximum ethernet packet size */ #define ETH_MAX_JUMBO_FRAME 65536 /* maximum ethernet jumbo frame size (or Offload Segment Size) */ #define ETH_MAX_DEVICE 20 /* maximum ethernet devices */ #define ETH_CRC_SIZE 4 /* ethernet CRC size */ #define ETH_FRAME_SIZE (ETH_MAX_PACKET+ETH_CRC_SIZE) /* ethernet maximum frame size */ #define ETH_MIN_JUMBO_FRAME ETH_MAX_PACKET /* Threshold size for Jumbo Frame Processing */ #define LOOPBACK_SELF_FRAME(phy_mac, msg) \ (((msg)[12] == 0x90) && ((msg)[13] == 0x00) && /* Ethernet Loopback */ \ ((msg)[16] == 0x02) && ((msg)[17] == 0x00) && /* Forward Function */ \ ((msg)[24] == 0x01) && ((msg)[25] == 0x00) && /* Next Function - Reply */ \ (memcmp(phy_mac, (msg), 6) == 0) && /* Ethernet Destination */ \ (memcmp(phy_mac, (msg)+6, 6) == 0) && /* Ethernet Source */ \ (memcmp(phy_mac, (msg)+18, 6) == 0)) /* Forward Address */ #define LOOPBACK_PHYSICAL_RESPONSE(dev, msg) \ ((dev->have_host_nic_phy_addr) && \ ((msg)[12] == 0x90) && ((msg)[13] == 0x00) && /* Ethernet Loopback */ \ ((msg)[14] == 0x08) && ((msg)[15] == 0x00) && /* Skipcount - 8 */ \ ((msg)[16] == 0x02) && ((msg)[17] == 0x00) && /* Last Function - Forward */ \ ((msg)[24] == 0x01) && ((msg)[25] == 0x00) && /* Function - Reply */ \ (memcmp(dev->host_nic_phy_hw_addr, (msg)+18, 6) == 0) && /* Forward Address - Host MAC */\ (memcmp(dev->host_nic_phy_hw_addr, (msg), 6) == 0) && /* Ethernet Source - Host MAC */\ (memcmp(dev->physical_addr, (msg)+6, 6) == 0)) /* Ethernet Source */ #define LOOPBACK_PHYSICAL_REFLECTION(dev, msg) \ ((dev->have_host_nic_phy_addr) && \ ((msg)[12] == 0x90) && ((msg)[13] == 0x00) && /* Ethernet Loopback */ \ ((msg)[16] == 0x02) && ((msg)[17] == 0x00) && /* Forward Function */ \ ((msg)[24] == 0x01) && ((msg)[25] == 0x00) && /* Next Function - Reply */ \ (memcmp(dev->host_nic_phy_hw_addr, (msg)+6, 6) == 0) && /* Ethernet Source - Host MAC */\ (memcmp(dev->host_nic_phy_hw_addr, (msg)+18, 6) == 0)) /* Forward Address - Host MAC */ #define LOOPBACK_REFLECTION_TEST_PACKET(dev, msg) \ ((dev->have_host_nic_phy_addr) && \ ((msg)[12] == 0x90) && ((msg)[13] == 0x00) && /* Ethernet Loopback */ \ ((msg)[14] == 0x00) && ((msg)[15] == 0x00) && /* Skipcount - 0 */ \ ((msg)[16] == 0x02) && ((msg)[17] == 0x00) && /* Forward Function */ \ ((msg)[24] == 0x01) && ((msg)[25] == 0x00) && /* Next Function - Reply */ \ ((msg)[00] == 0xFE) && ((msg)[01] == 0xFF) && /* Ethernet Destination - Reflection Test MAC */\ ((msg)[02] == 0xFF) && ((msg)[03] == 0xFF) && \ ((msg)[04] == 0xFF) && ((msg)[05] == 0xFE) && \ (memcmp(dev->host_nic_phy_hw_addr, (msg)+6, 6) == 0)) /* Ethernet Source - Host MAC */ struct eth_packet { uint8 msg[ETH_FRAME_SIZE]; /* ethernet frame (message) */ uint8 *oversize; /* oversized frame (message) */ uint32 len; /* packet length without CRC */ uint32 used; /* bytes processed (used in packet chaining) */ int status; /* transmit/receive status */ uint32 crc_len; /* packet length with CRC */ }; struct eth_item { int type; /* receive (0=setup, 1=loopback, 2=normal) */ #define ETH_ITM_SETUP 0 #define ETH_ITM_LOOPBACK 1 #define ETH_ITM_NORMAL 2 struct eth_packet packet; }; struct eth_queue { int max; int count; int head; int tail; int loss; int high; struct eth_item* item; }; struct eth_list { char name[ETH_DEV_NAME_MAX]; char desc[ETH_DEV_DESC_MAX]; int eth_api; }; typedef int ETH_BOOL; typedef unsigned char ETH_MAC[6]; typedef unsigned char ETH_MULTIHASH[8]; typedef struct eth_packet ETH_PACK; typedef void (*ETH_PCALLBACK)(int status); typedef struct eth_list ETH_LIST; typedef struct eth_queue ETH_QUE; typedef struct eth_item ETH_ITEM; struct eth_write_request { struct eth_write_request *next; ETH_PACK packet; }; typedef struct eth_write_request ETH_WRITE_REQUEST; struct eth_device { char* name; /* name of ethernet device */ void* handle; /* handle of implementation-specific device */ SOCKET fd_handle; /* fd to kernel device (where needed) */ char* bpf_filter; /* bpf filter currently in effect */ int eth_api; /* Designator for which API is being used to move packets */ #define ETH_API_NONE 0 /* No API in use yet */ #define ETH_API_PCAP 1 /* Pcap API in use */ #define ETH_API_TAP 2 /* tun/tap API in use */ #define ETH_API_VDE 3 /* VDE API in use */ #define ETH_API_UDP 4 /* UDP API in use */ #define ETH_API_NAT 5 /* NAT (SLiRP) API in use */ ETH_PCALLBACK read_callback; /* read callback function */ ETH_PCALLBACK write_callback; /* write callback function */ ETH_PACK* read_packet; /* read packet */ ETH_MAC filter_address[ETH_FILTER_MAX]; /* filtering addresses */ int addr_count; /* count of filtering addresses */ ETH_BOOL promiscuous; /* promiscuous mode flag */ ETH_BOOL all_multicast; /* receive all multicast messages */ ETH_BOOL hash_filter; /* filter using AUTODIN II multicast hash */ ETH_MULTIHASH hash; /* AUTODIN II multicast hash */ int32 loopback_self_sent; /* loopback packets sent but not seen */ int32 loopback_self_sent_total; /* total loopback packets sent */ int32 loopback_self_rcvd_total; /* total loopback packets seen */ ETH_MAC physical_addr; /* physical address of interface */ int32 have_host_nic_phy_addr; /* flag indicating that the host_nic_phy_hw_addr is valid */ ETH_MAC host_nic_phy_hw_addr; /* MAC address of the attached NIC */ uint32 jumbo_fragmented; /* Giant IPv4 Frames Fragmented */ uint32 jumbo_dropped; /* Giant Frames Dropped */ uint32 jumbo_truncated; /* Giant Frames too big for capture buffer - Dropped */ uint32 packets_sent; /* Total Packets Sent */ uint32 packets_received; /* Total Packets Received */ uint32 loopback_packets_processed; /* Total Loopback Packets Processed */ uint32 transmit_packet_errors; /* Total Send Packet Errors */ uint32 receive_packet_errors; /* Total Read Packet Errors */ int32 error_waiting_threads; /* Count of threads currently waiting after an error */ ETH_BOOL error_needs_reset; /* Flag indicating to force reset */ #define ETH_ERROR_REOPEN_THRESHOLD 10 /* Attempt ReOpen after 20 send/receive errors */ #define ETH_ERROR_REOPEN_PAUSE 4 /* Seconds to pause between closing and reopening LAN */ uint32 error_reopen_count; /* Count of ReOpen Attempts */ DEVICE* dptr; /* device ethernet is attached to */ uint32 dbit; /* debugging bit */ int reflections; /* packet reflections on interface */ int need_crc; /* device needs CRC (Cyclic Redundancy Check) */ /* Throttling control parameters: */ uint32 throttle_time; /* ms burst time window */ #define ETH_THROT_DEFAULT_TIME 5 /* 5ms Default burst time window */ uint32 throttle_burst; /* packets passed with throttle_time which trigger throttling */ #define ETH_THROT_DEFAULT_BURST 4 /* 4 Packet burst in time window */ uint32 throttle_delay; /* ms to delay when throttling. 0 disables throttling */ #define ETH_THROT_DISABLED_DELAY 0 /* 0 Delay disables throttling */ #define ETH_THROT_DEFAULT_DELAY 10 /* 10ms Delay during burst */ /* Throttling state variables: */ uint32 throttle_mask; /* match test for threshold detection (1 << throttle_burst) - 1 */ uint32 throttle_events; /* keeps track of packet arrival values */ uint32 throttle_packet_time; /* time last packet was transmitted */ uint32 throttle_count; /* Total Throttle Delays */ #if defined (USE_READER_THREAD) int asynch_io; /* Asynchronous Interrupt scheduling enabled */ int asynch_io_latency; /* instructions to delay pending interrupt */ ETH_QUE read_queue; pthread_mutex_t lock; pthread_t reader_thread; /* Reader Thread Id */ pthread_t writer_thread; /* Writer Thread Id */ pthread_mutex_t writer_lock; pthread_mutex_t self_lock; pthread_cond_t writer_cond; ETH_WRITE_REQUEST *write_requests; int write_queue_peak; ETH_WRITE_REQUEST *write_buffers; t_stat write_status; #endif }; typedef struct eth_device ETH_DEV; /* prototype declarations*/ t_stat eth_open (ETH_DEV* dev, const char* name, /* open ethernet interface */ DEVICE* dptr, uint32 dbit); t_stat eth_close (ETH_DEV* dev); /* close ethernet interface */ t_stat eth_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet, /* write sychronous packet; */ ETH_PCALLBACK routine); /* callback when done */ int eth_read (ETH_DEV* dev, ETH_PACK* packet, /* read single packet; */ ETH_PCALLBACK routine); /* callback when done*/ t_stat eth_filter (ETH_DEV* dev, int addr_count, /* set filter on incoming packets */ ETH_MAC* const addresses, ETH_BOOL all_multicast, ETH_BOOL promiscuous); t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, /* set filter on incoming packets with AUTODIN II based hash */ ETH_MAC* const addresses, ETH_BOOL all_multicast, ETH_BOOL promiscuous, ETH_MULTIHASH* const hash); t_stat eth_check_address_conflict (ETH_DEV* dev, ETH_MAC* const address); int eth_devices (int max, ETH_LIST* dev); /* get ethernet devices on host */ void eth_setcrc (ETH_DEV* dev, int need_crc); /* enable/disable CRC mode */ t_stat eth_set_async (ETH_DEV* dev, int latency); /* set read behavior to be async */ t_stat eth_clr_async (ETH_DEV* dev); /* set read behavior to be not async */ t_stat eth_set_throttle (ETH_DEV* dev, uint32 time, uint32 burst, uint32 delay); /* set transmit throttle parameters */ uint32 eth_crc32(uint32 crc, const void* vbuf, size_t len); /* Compute Ethernet Autodin II CRC for buffer */ void eth_packet_trace (ETH_DEV* dev, const uint8 *msg, int len, const char* txt); /* trace ethernet packet header+crc */ void eth_packet_trace_ex (ETH_DEV* dev, const uint8 *msg, int len, const char* txt, int detail, uint32 reason); /* trace ethernet packet */ t_stat eth_show (FILE* st, UNIT* uptr, /* show ethernet devices */ int32 val, CONST void* desc); t_stat eth_show_devices (FILE* st, DEVICE *dptr, /* show ethernet devices */ UNIT* uptr, int32 val, CONST char* desc); void eth_show_dev (FILE*st, ETH_DEV* dev); /* show ethernet device state */ void eth_mac_fmt (ETH_MAC* const add, char* buffer); /* format ethernet mac address */ t_stat eth_mac_scan (ETH_MAC* mac, const char* strmac); /* scan string for mac, put in mac */ t_stat eth_mac_scan_ex (ETH_MAC* mac, /* scan string for mac, put in mac */ const char* strmac, UNIT *uptr);/* for specified unit */ t_stat ethq_init (ETH_QUE* que, int max); /* initialize FIFO queue */ void ethq_clear (ETH_QUE* que); /* clear FIFO queue */ void ethq_remove (ETH_QUE* que); /* remove item from FIFO queue */ void ethq_insert (ETH_QUE* que, int32 type, /* insert item into FIFO queue */ ETH_PACK* packet, int32 status); void ethq_insert_data(ETH_QUE* que, int32 type, /* insert item into FIFO queue */ const uint8 *data, int used, size_t len, size_t crc_len, const uint8 *crc_data, int32 status); t_stat ethq_destroy(ETH_QUE* que); /* release FIFO queue */ const char *eth_capabilities(void); #ifdef __cplusplus } #endif #endif /* _SIM_ETHER_H */ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | /* sim_fio.c: simulator file I/O library Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 03-Jun-11 MP Simplified VMS 64b support and made more portable 02-Feb-11 MP Added sim_fsize_ex and sim_fsize_name_ex returning t_addr Added export of sim_buf_copy_swapped and sim_buf_swap_data 28-Jun-07 RMS Added VMS IA64 support (from Norm Lastovica) 10-Jul-06 RMS Fixed linux conditionalization (from Chaskiel Grundman) 15-May-06 RMS Added sim_fsize_name 21-Apr-06 RMS Added FreeBSD large file support (from Mark Martinec) 19-Nov-05 RMS Added OS/X large file support (from Peter Schorn) 16-Aug-05 RMS Fixed C++ declaration and cast problems 17-Jul-04 RMS Fixed bug in optimized sim_fread (reported by Scott Bailey) 26-May-04 RMS Optimized sim_fread (suggested by John Dundas) 02-Jan-04 RMS Split out from SCP This library includes: sim_finit - initialize package sim_fopen - open file sim_fread - endian independent read (formerly fxread) sim_write - endian independent write (formerly fxwrite) sim_fseek - conditionally extended (>32b) seek ( sim_fseeko - extended seek (>32b if available) sim_fsize - get file size sim_fsize_name - get file size of named file sim_fsize_ex - get file size as a t_offset sim_fsize_name_ex - get file size as a t_offset of named file sim_buf_copy_swapped - copy data swapping elements along the way sim_buf_swap_data - swap data elements inplace in buffer sim_shmem_open create or attach to a shared memory region sim_shmem_close close a shared memory region sim_fopen and sim_fseek are OS-dependent. The other routines are not. sim_fsize is always a 32b routine (it is used only with small capacity random access devices like fixed head disks and DECtapes). */ #include "sim_defs.h" t_bool sim_end; /* TRUE = little endian, FALSE = big endian */ t_bool sim_taddr_64; /* t_addr is > 32b and Large File Support available */ t_bool sim_toffset_64; /* Large File (>2GB) file I/O Support available */ #if defined(fprintf) /* Make sure to only use the C rtl stream I/O routines */ #undef fprintf #undef fputs #undef fputc #endif /* OS-independent, endian independent binary I/O package For consistency, all binary data read and written by the simulator is stored in little endian data order. That is, in a multi-byte data item, the bytes are written out right to left, low order byte to high order byte. On a big endian host, data is read and written from high byte to low byte. Consequently, data written on a little endian system must be byte reversed to be usable on a big endian system, and vice versa. These routines are analogs of the standard C runtime routines fread and fwrite. If the host is little endian, or the data items are size char, then the calls are passed directly to fread or fwrite. Otherwise, these routines perform the necessary byte swaps. Sim_fread swaps in place, sim_fwrite uses an intermediate buffer. */ int32 sim_finit (void) { union {int32 i; char c[sizeof (int32)]; } end_test; end_test.i = 1; /* test endian-ness */ sim_end = (end_test.c[0] != 0); sim_toffset_64 = (sizeof(t_offset) > sizeof(int32)); /* Large File (>2GB) support */ sim_taddr_64 = sim_toffset_64 && (sizeof(t_addr) > sizeof(int32)); return sim_end; } void sim_buf_swap_data (void *bptr, size_t size, size_t count) { uint32 j; int32 k; unsigned char by, *sptr, *dptr; if (sim_end || (count == 0) || (size == sizeof (char))) return; for (j = 0, dptr = sptr = (unsigned char *) bptr; /* loop on items */ j < count; j++) { for (k = (int32)(size - 1); k >= (((int32) size + 1) / 2); k--) { by = *sptr; /* swap end-for-end */ *sptr++ = *(dptr + k); *(dptr + k) = by; } sptr = dptr = dptr + size; /* next item */ } } size_t sim_fread (void *bptr, size_t size, size_t count, FILE *fptr) { size_t c; if ((size == 0) || (count == 0)) /* check arguments */ return 0; c = fread (bptr, size, count, fptr); /* read buffer */ if (sim_end || (size == sizeof (char)) || (c == 0)) /* le, byte, or err? */ return c; /* done */ sim_buf_swap_data (bptr, size, count); return c; } void sim_buf_copy_swapped (void *dbuf, const void *sbuf, size_t size, size_t count) { size_t j; int32 k; const unsigned char *sptr = (const unsigned char *)sbuf; unsigned char *dptr = (unsigned char *)dbuf; if (sim_end || (size == sizeof (char))) { memcpy (dptr, sptr, size * count); return; } for (j = 0; j < count; j++) { /* loop on items */ for (k = (int32)(size - 1); k >= 0; k--) *(dptr + k) = *sptr++; dptr = dptr + size; } } size_t sim_fwrite (const void *bptr, size_t size, size_t count, FILE *fptr) { size_t c, nelem, nbuf, lcnt, total; int32 i; const unsigned char *sptr; unsigned char *sim_flip; if ((size == 0) || (count == 0)) /* check arguments */ return 0; if (sim_end || (size == sizeof (char))) /* le or byte? */ return fwrite (bptr, size, count, fptr); /* done */ sim_flip = (unsigned char *)malloc(FLIP_SIZE); if (!sim_flip) return 0; nelem = FLIP_SIZE / size; /* elements in buffer */ nbuf = count / nelem; /* number buffers */ lcnt = count % nelem; /* count in last buf */ if (lcnt) nbuf = nbuf + 1; else lcnt = nelem; total = 0; sptr = (const unsigned char *) bptr; /* init input ptr */ for (i = (int32)nbuf; i > 0; i--) { /* loop on buffers */ c = (i == 1)? lcnt: nelem; sim_buf_copy_swapped (sim_flip, sptr, size, c); sptr = sptr + size * count; c = fwrite (sim_flip, size, c, fptr); if (c == 0) { free(sim_flip); return total; } total = total + c; } free(sim_flip); return total; } /* Forward Declaration */ t_offset sim_ftell (FILE *st); /* Get file size */ t_offset sim_fsize_ex (FILE *fp) { t_offset pos, sz; if (fp == NULL) return 0; pos = sim_ftell (fp); sim_fseek (fp, 0, SEEK_END); sz = sim_ftell (fp); sim_fseeko (fp, pos, SEEK_SET); return sz; } t_offset sim_fsize_name_ex (const char *fname) { FILE *fp; t_offset sz; if ((fp = sim_fopen (fname, "rb")) == NULL) return 0; sz = sim_fsize_ex (fp); fclose (fp); return sz; } uint32 sim_fsize_name (const char *fname) { return (uint32)(sim_fsize_name_ex (fname)); } uint32 sim_fsize (FILE *fp) { return (uint32)(sim_fsize_ex (fp)); } /* OS-dependent routines */ /* Optimized file open */ FILE *sim_fopen (const char *file, const char *mode) { #if defined (VMS) return fopen (file, mode, "ALQ=32", "DEQ=4096", "MBF=6", "MBC=127", "FOP=cbt,tef", "ROP=rah,wbh", "CTX=stm"); #elif (defined (__linux) || defined (__linux__) || defined (__hpux) || defined (_AIX)) && !defined (DONT_DO_LARGEFILE) return fopen64 (file, mode); #else return fopen (file, mode); #endif } #if !defined (DONT_DO_LARGEFILE) /* 64b VMS */ #if ((defined (__ALPHA) || defined (__ia64)) && defined (VMS) && (__DECC_VER >= 60590001)) || \ ((defined(__sun) || defined(__sun__)) && defined(_LARGEFILE_SOURCE)) #define S_SIM_IO_FSEEK_EXT_ 1 int sim_fseeko (FILE *st, t_offset offset, int whence) { return fseeko (st, (off_t)offset, whence); } t_offset sim_ftell (FILE *st) { return (t_offset)(ftello (st)); } #endif /* Alpha UNIX - natively 64b */ #if defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */ #define S_SIM_IO_FSEEK_EXT_ 1 int sim_fseeko (FILE *st, t_offset offset, int whence) { return fseek (st, offset, whence); } t_offset sim_ftell (FILE *st) { return (t_offset)(ftell (st)); } #endif /* Windows */ #if defined (_WIN32) #define S_SIM_IO_FSEEK_EXT_ 1 #include <sys/stat.h> int sim_fseeko (FILE *st, t_offset offset, int whence) { fpos_t fileaddr; struct _stati64 statb; switch (whence) { case SEEK_SET: fileaddr = (fpos_t)offset; break; case SEEK_END: if (_fstati64 (_fileno (st), &statb)) return (-1); fileaddr = statb.st_size + offset; break; case SEEK_CUR: if (fgetpos (st, &fileaddr)) return (-1); fileaddr = fileaddr + offset; break; default: errno = EINVAL; return (-1); } return fsetpos (st, &fileaddr); } t_offset sim_ftell (FILE *st) { fpos_t fileaddr; if (fgetpos (st, &fileaddr)) return (-1); return (t_offset)fileaddr; } #endif /* end Windows */ /* Linux */ #if defined (__linux) || defined (__linux__) || defined (__hpux) || defined (_AIX) #define S_SIM_IO_FSEEK_EXT_ 1 int sim_fseeko (FILE *st, t_offset xpos, int origin) { return fseeko64 (st, (off64_t)xpos, origin); } t_offset sim_ftell (FILE *st) { return (t_offset)(ftello64 (st)); } #endif /* end Linux with LFS */ /* Apple OS/X */ #if defined (__APPLE__) || defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined (__CYGWIN__) #define S_SIM_IO_FSEEK_EXT_ 1 int sim_fseeko (FILE *st, t_offset xpos, int origin) { return fseeko (st, (off_t)xpos, origin); } t_offset sim_ftell (FILE *st) { return (t_offset)(ftello (st)); } #endif /* end Apple OS/X */ #endif /* !DONT_DO_LARGEFILE */ /* Default: no OS-specific routine has been defined */ #if !defined (S_SIM_IO_FSEEK_EXT_) int sim_fseeko (FILE *st, t_offset xpos, int origin) { return fseek (st, (long) xpos, origin); } t_offset sim_ftell (FILE *st) { return (t_offset)(ftell (st)); } #endif int sim_fseek (FILE *st, t_addr offset, int whence) { return sim_fseeko (st, (t_offset)offset, whence); } #if defined(_WIN32) #include <io.h> int sim_set_fsize (FILE *fptr, t_addr size) { return _chsize(_fileno(fptr), (long)size); } int sim_set_fifo_nonblock (FILE *fptr) { return -1; } struct SHMEM { HANDLE hMapping; size_t shm_size; void *shm_base; }; t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr) { *shmem = (SHMEM *)calloc (1, sizeof(**shmem)); if (*shmem == NULL) return SCPE_MEM; (*shmem)->hMapping = INVALID_HANDLE_VALUE; (*shmem)->shm_size = size; (*shmem)->shm_base = NULL; (*shmem)->hMapping = CreateFileMappingA (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)size, name); if ((*shmem)->hMapping == INVALID_HANDLE_VALUE) { sim_shmem_close (*shmem); *shmem = NULL; return SCPE_OPENERR; } (*shmem)->shm_base = MapViewOfFile ((*shmem)->hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); if ((*shmem)->shm_base == NULL) { sim_shmem_close (*shmem); *shmem = NULL; return SCPE_OPENERR; } *addr = (*shmem)->shm_base; return SCPE_OK; } void sim_shmem_close (SHMEM *shmem) { if (shmem == NULL) return; if (shmem->shm_base != NULL) UnmapViewOfFile (shmem->shm_base); if (shmem->hMapping != INVALID_HANDLE_VALUE) CloseHandle (shmem->hMapping); free (shmem); } #else /* !defined(_WIN32) */ #include <unistd.h> int sim_set_fsize (FILE *fptr, t_addr size) { return ftruncate(fileno(fptr), (off_t)size); } #include <sys/stat.h> #include <fcntl.h> int sim_set_fifo_nonblock (FILE *fptr) { struct stat stbuf; if (!fptr || fstat (fileno(fptr), &stbuf)) return -1; #if defined(S_IFIFO) && defined(O_NONBLOCK) if ((stbuf.st_mode & S_IFIFO)) { int flags = fcntl(fileno(fptr), F_GETFL, 0); return fcntl(fileno(fptr), F_SETFL, flags | O_NONBLOCK); } #endif return -1; } #include <sys/mman.h> struct SHMEM { int shm_fd; size_t shm_size; void *shm_base; }; t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr) { #ifdef HAVE_SHM_OPEN *shmem = (SHMEM *)calloc (1, sizeof(**shmem)); *addr = NULL; if (*shmem == NULL) return SCPE_MEM; (*shmem)->shm_base = MAP_FAILED; (*shmem)->shm_size = size; (*shmem)->shm_fd = shm_open (name, O_RDWR, 0); if ((*shmem)->shm_fd == -1) { (*shmem)->shm_fd = shm_open (name, O_CREAT | O_RDWR, 0660); if ((*shmem)->shm_fd == -1) { sim_shmem_close (*shmem); *shmem = NULL; return SCPE_OPENERR; } if (ftruncate((*shmem)->shm_fd, size)) { sim_shmem_close (*shmem); *shmem = NULL; return SCPE_OPENERR; } } else { struct stat statb; if ((fstat ((*shmem)->shm_fd, &statb)) || (statb.st_size != (*shmem)->shm_size)) { sim_shmem_close (*shmem); *shmem = NULL; return SCPE_OPENERR; } } (*shmem)->shm_base = mmap(NULL, (*shmem)->shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, (*shmem)->shm_fd, 0); if ((*shmem)->shm_base == MAP_FAILED) { sim_shmem_close (*shmem); *shmem = NULL; return SCPE_OPENERR; } *addr = (*shmem)->shm_base; return SCPE_OK; #else return SCPE_NOFNC; #endif } void sim_shmem_close (SHMEM *shmem) { if (shmem == NULL) return; if (shmem->shm_base != MAP_FAILED) munmap (shmem->shm_base, shmem->shm_size); if (shmem->shm_fd != -1) close (shmem->shm_fd); free (shmem); } #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | /* sim_fio.h: simulator file I/O library headers Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 02-Feb-11 MP Added sim_fsize_ex and sim_fsize_name_ex returning t_addr Added export of sim_buf_copy_swapped and sim_buf_swap_data 15-May-06 RMS Added sim_fsize_name 16-Aug-05 RMS Fixed C++ declaration and cast problems 02-Jan-04 RMS Split out from SCP */ #ifndef SIM_FIO_H_ #define SIM_FIO_H_ 0 #ifdef __cplusplus extern "C" { #endif #define FLIP_SIZE (1 << 16) /* flip buf size */ #define fxread(a,b,c,d) sim_fread (a, b, c, d) #define fxwrite(a,b,c,d) sim_fwrite (a, b, c, d) int32 sim_finit (void); #if (defined (__linux) || defined (__linux__) || defined (__hpux) || defined (_AIX) || \ (defined (VMS) && (defined (__ALPHA) || defined (__ia64)) && (__DECC_VER >= 60590001)) || \ ((defined(__sun) || defined(__sun__)) && defined(_LARGEFILE_SOURCE)) || \ defined (_WIN32) || defined (__APPLE__) || defined (__CYGWIN__) || \ defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__)) && !defined (DONT_DO_LARGEFILE) typedef t_int64 t_offset; #else typedef int32 t_offset; #if !defined (DONT_DO_LARGEFILE) #define DONT_DO_LARGEFILE 1 #endif #endif FILE *sim_fopen (const char *file, const char *mode); int sim_fseek (FILE *st, t_addr offset, int whence); int sim_fseeko (FILE *st, t_offset offset, int whence); int sim_set_fsize (FILE *fptr, t_addr size); int sim_set_fifo_nonblock (FILE *fptr); size_t sim_fread (void *bptr, size_t size, size_t count, FILE *fptr); size_t sim_fwrite (const void *bptr, size_t size, size_t count, FILE *fptr); uint32 sim_fsize (FILE *fptr); uint32 sim_fsize_name (const char *fname); t_offset sim_ftell (FILE *st); t_offset sim_fsize_ex (FILE *fptr); t_offset sim_fsize_name_ex (const char *fname); void sim_buf_swap_data (void *bptr, size_t size, size_t count); void sim_buf_copy_swapped (void *dptr, const void *bptr, size_t size, size_t count); typedef struct SHMEM SHMEM; t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr); void sim_shmem_close (SHMEM *shmem); extern t_bool sim_taddr_64; /* t_addr is > 32b and Large File Support available */ extern t_bool sim_toffset_64; /* Large File (>2GB) file I/O support */ extern t_bool sim_end; /* TRUE = little endian, FALSE = big endian */ #ifdef __cplusplus } #endif #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 | /* sim_frontpanel.h: simulator frontpanel API definitions Copyright (c) 2015, Mark Pizzolato Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL MARK PIZZOLATO BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Mark Pizzolato shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Mark Pizzolato. 15-Jan-15 MP Initial implementation 01-Apr-15 MP Added register indirect, mem_examine and mem_deposit 03-Apr-15 MP Added logic to pass simulator startup messages in panel error text if the connection to the simulator shuts down while it is starting. 04-Apr-15 MP Added mount and dismount routines to connect and disconnect removable media This module defines interface between a front panel application and a simh simulator. Facilities provide ways to gather information from and to observe and control the state of a simulator. Any application which wants to use this API needs to: 1) include this file in the application code 2) compile sim_frontpanel.c and sim_sock.c from the top level directory of the simh source. 3) link the sim_frontpanel and sim_sock object modules and libpthreads into the application. 4) Use a simh simulator built from the same version of simh that the sim_frontpanel and sim_sock modules came from. */ #ifndef SIM_FRONTPANEL_H_ #define SIM_FRONTPANEL_H_ 0 #ifdef __cplusplus extern "C" { #endif #include <stdlib.h> #if !defined(__VAX) /* Unsupported platform */ #define SIM_FRONTPANEL_VERSION 4 /** sim_panel_start_simulator A starts a simulator with a particular configuration sim_path the path to the simulator binary sim_config the configuration to run the simulator with device_panel_count the number of sub panels for connected devices Note 1: - The path specified must be either a fully specified path or it could be merey the simulator name if the simulator binary is located in the current PATH. - The simulator binary must be built from the same version simh source code that the frontpanel API was acquired fron (the API and the simh framework must speak the same language) Note 2: - Configuration file specified should contain device setup statements (enable, disable, CPU types and attach commands). It should not start a simulator running. */ typedef struct PANEL PANEL; PANEL * sim_panel_start_simulator (const char *sim_path, const char *sim_config, size_t device_panel_count); PANEL * sim_panel_start_simulator_debug (const char *sim_path, const char *sim_config, size_t device_panel_count, const char *debug_file); /** sim_panel_add_device_panel - creates a sub panel associated with a specific simulator panel simulator_panel the simulator panel to connect to device_name the simulator's name for the device */ PANEL * sim_panel_add_device_panel (PANEL *simulator_panel, const char *device_name); /** sim_panel_destroy to shutdown a panel or sub panel. Note: destroying a simulator panel will also destroy any related sub panels */ int sim_panel_destroy (PANEL *panel); /** The frontpanel API exposes the state of a simulator via access to simh register variables that the simulator and its devices define. These registers certainly include any architecturally described registers (PC, PSL, SP, etc.), but also include anything else the simulator uses as internal state to implement the running simulator. The registers that a particular frontpanel application mught need access to are specified by the application when it calls: sim_panel_add_register sim_panel_add_register_bits sim_panel_add_register_array and sim_panel_add_register_indirect sim_panel_add_register_indirect_bits name the name the simulator knows this register by device_name the device this register is part of. Defaults to the device of the panel (in a device panel) or the default device in the simulator (usually the CPU). element_count number of elements in the register array size the size (in local storage) of the buffer which will receive the data in the simulator's register addr a pointer to the location of the buffer which will be loaded with the data in the simulator's register bit_width the number of values to populate in the bits array bits an array of integers which is bit_width long that will receive each bit's current accumulated value. The accumulated value will range from 0 thru the the sample_depth specified when calling sim_panel_set_sampling_parameters(). */ int sim_panel_add_register (PANEL *panel, const char *name, const char *device_name, size_t size, void *addr); int sim_panel_add_register_bits (PANEL *panel, const char *name, const char *device_name, size_t bit_width, int *bits); int sim_panel_add_register_array (PANEL *panel, const char *name, const char *device_name, size_t element_count, size_t size, void *addr); int sim_panel_add_register_indirect (PANEL *panel, const char *name, const char *device_name, size_t size, void *addr); int sim_panel_add_register_indirect_bits (PANEL *panel, const char *name, const char *device_name, size_t bit_width, int *bits); /** A panel application has a choice of two different methods of getting the values contained in the set of registers it has declared interest in via the sim_panel_add_register APIs. 1) The values can be polled (when ever it is desired) by calling sim_panel_get_registers(). 2) The panel can call sim_panel_set_display_callback_interval() to specify a callback routine and a periodic rate that the callback routine should be called. The panel API will make a best effort to deliver the current register state at the desired rate. Note 1: The buffers described in a panel's register set will be dynamically revised as soon as data is available from the simulator. The callback routine merely serves as a notification that a complete register set has arrived. Note 2: The callback routine should, in general, not run for a long time or frontpanel interactions with the simulator may be disrupted. Setting a flag, signaling an event or posting a message are reasonable activities to perform in a callback routine. */ int sim_panel_get_registers (PANEL *panel, unsigned long long *simulation_time); typedef void (*PANEL_DISPLAY_PCALLBACK)(PANEL *panel, unsigned long long simulation_time, void *context); int sim_panel_set_display_callback_interval (PANEL *panel, PANEL_DISPLAY_PCALLBACK callback, void *context, int usecs_between_callbacks); /** When a front panel application wants to get averaged bit sample values, it must first declare the sampling parameters that will be used while collecting the bit values. sim_panel_set_sampling_parameters sample_frequency cycles/instructions between sample captures sample_depth how many samples to accumulate in the rolling average for each bit sample. Returned bit sample values will range from 0 thru this value. */ int sim_panel_set_sampling_parameters (PANEL *panel, unsigned int sample_frequency, unsigned int sample_depth); /** When a front panel application needs to change the running state of a simulator one of the following routines should be called: sim_panel_exec_halt - Stop instruction execution sim_panel_exec_boot - Boot a simulator from a specific device sim_panel_exec_run - Start/Resume a simulator running instructions sim_panel_exec_step - Have a simulator execute a single step */ int sim_panel_exec_halt (PANEL *panel); int sim_panel_exec_boot (PANEL *panel, const char *device); int sim_panel_exec_run (PANEL *panel); int sim_panel_exec_step (PANEL *panel); /** When a front panel application wants to describe conditions that should stop instruction execution an execution or an output breakpoint should be used. To established or clear a breakpoint, one of the following routines should be called: sim_panel_break_set - Establish a simulation breakpoint sim_panel_break_clear - Cancel/Delete a previously defined breakpoint sim_panel_break_output_set - Establish a simulator output breakpoint sim_panel_break_output_clear - Cancel/Delete a previously defined output breakpoint Note: Any breakpoint switches/flags must be located at the beginning of the condition string */ int sim_panel_break_set (PANEL *panel, const char *condition); int sim_panel_break_clear (PANEL *panel, const char *condition); int sim_panel_break_output_set (PANEL *panel, const char *condition); int sim_panel_break_output_clear (PANEL *panel, const char *condition); /** When a front panel application needs to change or access memory or a register one of the following routines should be called: sim_panel_gen_examine - Examine register or memory sim_panel_gen_deposit - Deposit to register or memory sim_panel_mem_examine - Examine memory location sim_panel_mem_deposit - Deposit to memory location sim_panel_set_register_value - Deposit to a register or memory location */ /** sim_panel_gen_examine name_or_addr the name the simulator knows this register by size the size (in local storage) of the buffer which will receive the data returned when examining the simulator value a pointer to the buffer which will be loaded with the data returned when examining the simulator */ int sim_panel_gen_examine (PANEL *panel, const char *name_or_addr, size_t size, void *value); /** sim_panel_gen_deposit name_or_addr the name the simulator knows this register by size the size (in local storage) of the buffer which contains the data to be deposited into the simulator value a pointer to the buffer which contains the data to be deposited into the simulator */ int sim_panel_gen_deposit (PANEL *panel, const char *name_or_addr, size_t size, const void *value); /** sim_panel_mem_examine addr_size the size (in local storage) of the buffer which contains the memory address of the data to be examined in the simulator addr a pointer to the buffer containing the memory address of the data to be examined in the simulator value_size the size (in local storage) of the buffer which will receive the data returned when examining the simulator value a pointer to the buffer which will be loaded with the data returned when examining the simulator */ int sim_panel_mem_examine (PANEL *panel, size_t addr_size, const void *addr, size_t value_size, void *value); /** sim_panel_mem_deposit addr_size the size (in local storage) of the buffer which contains the memory address of the data to be deposited into the simulator addr a pointer to the buffer containing the memory address of the data to be deposited into the simulator value_size the size (in local storage) of the buffer which will contains the data to be deposited into the simulator value a pointer to the buffer which contains the data to be deposited into the simulator */ int sim_panel_mem_deposit (PANEL *panel, size_t addr_size, const void *addr, size_t value_size, const void *value); /** sim_panel_set_register_value name the name of a simulator register or a memory address which is to receive a new value value the new value in character string form. The string must be in the native/natural radix that the simulator uses when referencing that register */ int sim_panel_set_register_value (PANEL *panel, const char *name, const char *value); /** When a front panel application needs to change the media in a simulated removable media device one of the following routines should be called: sim_panel_mount - mounts the indicated media file on a device sim_panel_dismount - dismounts the currently mounted media file from a device */ /** sim_panel_mount device the name of a simulator device/unit switches any switches appropriate for the desire attach path the path on the local system to be attached */ int sim_panel_mount (PANEL *panel, const char *device, const char *switches, const char *path); /** sim_panel_dismount device the name of a simulator device/unit */ int sim_panel_dismount (PANEL *panel, const char *device); typedef enum { Halt, /* Simulation is halted (instructions not being executed) */ Run, /* Simulation is executing instructions */ Error /* Panel simulator is in an error state and should be */ /* closed (destroyed). sim_panel_get_error might help */ /* explain why */ } OperationalState; OperationalState sim_panel_get_state (PANEL *panel); /** All APIs routines which return an int return 0 for success and -1 for an error. An API which returns an error (-1), will not change the panel state. sim_panel_get_error - the details of the most recent error sim_panel_clear_error - clears the error buffer */ const char *sim_panel_get_error (void); void sim_panel_clear_error (void); /** The panek<->simulator wire protocol can be traced if protocol problems arise. sim_panel_set_debug_file - Specifies the log file to record debug traffic sim_panel_set_debug_mode - Specifies the debug detail to be recorded sim_panel_flush_debug - Flushes debug output to disk */ void sim_panel_set_debug_file (PANEL *panel, const char *debug_file); #define DBG_XMT 1 /* Transmit Data */ #define DBG_RCV 2 /* Receive Data */ #define DBG_REQ 4 /* Request Data */ #define DBG_RSP 8 /* Response Data */ void sim_panel_set_debug_mode (PANEL *panel, int debug_bits); void sim_panel_flush_debug (PANEL *panel); #endif /* !defined(__VAX) */ #ifdef __cplusplus } #endif #endif /* SIM_FRONTPANEL_H_ */ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 | /* sim_rev.h: simulator revisions and current rev level Copyright (c) 1993-2012, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. */ #ifndef SIM_REV_H_ #define SIM_REV_H_ 0 #ifndef SIM_MAJOR #define SIM_MAJOR 4 #endif #ifndef SIM_MINOR #define SIM_MINOR 0 #endif #ifndef SIM_PATCH #define SIM_PATCH 0 #endif #ifndef SIM_DELTA #define SIM_DELTA 0 #endif #ifndef SIM_VERSION_MODE #define SIM_VERSION_MODE "Beta" #endif #if defined(SIM_NEED_GIT_COMMIT_ID) #include ".git-commit-id.h" #endif #if !defined(SIM_GIT_COMMIT_ID) #define SIM_GIT_COMMIT_ID $Format:%H$ #endif /* The comment section below reflects the manual editing process which was in place prior to the use of the git source control system on at https://gihub.com/simh/simh Details about all future fixes will be visible in the source control system's history. */ /* V3.9 revision history patch date module(s) and fix(es) 0 01-May-2012 scp.c: - added *nix READLINE support (Mark Pizzolato) - fixed handling of DO with no arguments (Dave Bryan) - fixed "SHOW DEVICE" with only one enabled unit (Dave Bryan) - clarified some help messages (Mark Pizzolato) - added "SHOW SHOW" and "SHOW <dev> SHOW" commands (Mark Pizzolato) - fixed bug in deposit stride for numeric input (John Dundas) sim_console.c - added support for BREAK key on Windows (Mark Pizzolato) sim_ether.c - major revision (Dave Hittner and Mark Pizzolato) - fixed array overrun which caused SEGFAULT on hosts with many devices which libpcap can access. - fixed duplicate MAC address detection to work reliably on switch connected LANs sim_tmxr.c: - made telnet option negotiation more reliable, VAX simulator now works with PuTTY as console (Mark Pizzolato) h316_cpu.c: - fixed bugs in MPY, DIV introduced in 3.8-1 (from Theo Engel) - fixed bugs in double precision, normalization, SC (from Adrian Wise) - fixed XR behavior (from Adrian Wise) hp2100 all peripherals (Dave Bryan): - Changed I/O signal handlers for newly revised signal model - Deprecated DEVNO modifier in favor of SC hp2100_cpu.c (Dave Bryan): - Minor speedup in "is_mapped" - Added casts to cpu_mod, dmasio, dmapio, cpu_reset, dma_reset - Fixed I/O return status bug for DMA cycles - Failed I/O cycles now stop on failing instruction - Revised DMA for new multi-card paradigm - Consolidated DMA reset routines - DMA channels renamed from 0,1 to 1,2 to match documentation - Changed I/O instructions, handlers, and DMA for revised signal model - Changed I/O dispatch table to use DIB pointers - Removed DMA latency counter - Fixed DMA requests to enable stealing every cycle - Fixed DMA priority for channel 1 over channel 2 - Corrected comments for "cpu_set_idle" hp2100_cpu.h: - Changed declarations for VMS compiler hp2100_cpu0.c (Dave Bryan): - Removed DS note regarding PIF card (is now implemented) hp2100_cpu4.c (Dave Bryan): - Added OPSIZE casts to fp_accum calls in .FPWR/.TPWR hp2100_cpu5.c (Dave Bryan): - Added sign extension for dim count in "cpu_ema_resolve" - Eliminated unused variable in "cpu_ema_vset" hp2100_cpu6.c (Dave Bryan): - DMA channels renamed from 0,1 to 1,2 to match documentation hp2100_cpu7.c (Dave Bryan): - Corrected "opsize" parameter type in vis_abs hp2100_defs.h (Dave Bryan): - Added hp_setsc, hp_showsc functions to support SC modifier - DMA channels renamed from 0,1 to 1,2 to match documentation - Revised I/O signal enum values for concurrent signals - Revised I/O macros for new signal handling - Added DA and DC device select code assignments hp2100_di.c, hp2100_di.h (Dave Bryan): - Implemented 12821A HP-IB Disc Interface hp2100_di_da.c (Dave Bryan): - Implemented 7906H/20H/25H ICD disc drives hp2100_dp.c (Dave Bryan): - Added CNTLR_TYPE cast to dp_settype hp2100_ds.c (Dave Bryan): - Rewritten to use the MAC/ICD disc controller library - ioIOO now notifies controller service of parameter output - Corrected SRQ generation and FIFO under/overrun detection - Corrected Clear command to conform to the hardware - Fixed Request Status to return Unit Unavailable if illegal - Seek and Cold Load Read now Seek Check if seek in progress - Remodeled command wait for seek completion - Corrected status returns for disabled drive, auto-seek beyond drive limits, Request Sector Address and Wakeup with invalid or offline unit - Address verification reenabled if auto-seek during Read Without Verify hp2100_fp1.c (Dave Bryan): - Added missing precision on constant "one" in fp_trun - Completed the comments for divide; no code changes hp2100_ipl.c (Dave Bryan): - Added CARD_INDEX casts to dib.card_index - A failed STC may now be retried - Consolidated reporting of consecutive CRS signals - Revised for new multi-card paradigm hp2100_lps.c (Dave Bryan): - Revised detection of CLC at last DMA cycle - Corrected 12566B (DIAG mode) jumper settings hp2100_ms.c (Dave Bryan): - Added CNTLR_TYPE cast to ms_settype hp2100_mt.c (Dave Bryan): - Removed redundant MTAB_VUN from "format" MTAB entry - Fixed command scanning error in mtcio ioIOO handler hp2100_stddev.c (Dave Bryan): - Add TBG as a logical name for the CLK device hp2100_sys.c (Dave Bryan): - Deprecated DEVNO in favor of SC - Added hp_setsc, hp_showsc functions to support SC modifier - Added DA and dummy DC devices - DMA channels renamed from 0,1 to 1,2 to match documentation - Changed DIB access for revised signal model hp_disclib.c, hp_disclib.h (Dave Bryan) - Created MAC/ICD disc controller library i1401_cd.c: - fixed read stacker operation in column binary mode - fixed punch stacker operation (Van Snyder) id_pas.c: - fixed TT_GET_MODE test to use TTUF_MODE_x (Michael Bloom) - revised to use clock coscheduling id_tt.c, id_ttc.p: - revised to use clock coscheduling id_uvc.c: - added clock coscheduling routine 1401_cpu.c: - reverted multiple tape indicator implementation - fixed EOT indicator test not to clear indicator (Van Snyder) - fixed divide not to clear word marks in quotient (Van Snyder) - revised divide algorithm (Van Snyder) i1401_mt.c: - reverted multiple tape indicator implementation - fixed END indicator test not to clear indicator (Van Snyder) - fixed backspace over tapemark not to set EOR (Van Snyder) - added no rewind option (Van Snyder) i1401_sys.c: - fixed misuse of & instead of && in decode (Peter Schorn) pdp1_cpu.c: - fixed misuse of & instead of && in Ea_ch (Michael Bloom) pdp1_stddev.c: - fixed unitialized variable in tty output service (Michael Bloom) pdp10_fe.c: - revised to use clock coscheduling pdp11_defs.h: - fixed priority of PIRQ vs IO; added INT_INTERNALn pdp11_io.c: - fixed Qbus interrupts to treat all IO devices (except clock) as BR4 - fixed order of int_internal (Jordi Guillaumes i Pons) ppd11_rf.c - fixed bug in updating mem addr extension (Peter Schorn) pdp11_rk.c: - fixed bug in read header (Walter F Mueller) pdp11_rl.c: - added debug support pdp11_rq.c: - added RD32 support pdp11_tq.c: (Mark Pizzolato) - set UNIT_SXC flag when a tape mark is encountered during forward motion read operations - fixed logic which clears UNIT_SXC to check command modifier - added CMF_WR flag to tq_cmf entry for OP_WTM - made non-immediate rewind positioning operations take 2 seconds - added UNIT_IDLE flag to tq units. - fixed debug output of tape file positions when they are 64b - added more debug output after positioning operations - added textual display of the command being performed - fixed comments about register addresses pdp11_ts.c: - fixed t_addr printouts for 64b big-endian systems (Mark Pizzolato) pdp11_tu.c: - fixed t_addr printouts for 64b big-endian systems (Mark Pizzolato) pdp11_vh.c: (Mark Pizzolato) - fixed SET VH LINES=n to correctly adjust the number of lines available to be 8, 16, 24, or 32. - fixed performance issue avoiding redundant polling pdp11_xq.c: (Mark Pizzolato) - Fixed missing information from save/restore which caused operations to not complete correctly after a restore until the OS reset the controller. - Added address conflict check during attach. - Fixed loopback processing to correctly handle forward packets. - Fixed interrupt dispatch issue which caused delivered packets (in and out) to sometimes not interrupt the CPU after processing. - Fixed the SCP visibile SA registers to always display the ROM mac address, even after it is changed by SET XQ MAC=. - Added changes so that the Console DELQA diagnostic (>>>TEST 82) will succeed. - Added DELQA-T (aka DELQA Plus) device emulation support. - Added dropped frame statistics to record when the receiver discards received packets due to the receiver being disabled, or due to the XQ device's packet receive queue being full. - Fixed bug in receive processing when we're not polling. This could cause receive processing to never be activated again if we don't read all available packets via eth_read each time we get the opportunity. - Added the ability to Coalesce received packet interrupts. This is enabled by SET XQ POLL=DELAY=nnn where nnn is a number of microseconds to delay the triggering of an interrupt when a packet is received. - Added SET XQ POLL=DISABLE (aka SET XQ POLL=0) to operate without polling for packet read completion. - Changed the sanity and id timer mechanisms to use a separate timer unit so that transmit and recieve activities can be dealt with by the normal xq_svc routine. Dynamically determine the timer polling rate based on the calibrated tmr_poll and clk_tps values of the simulator. - Enabled the SET XQ POLL to be meaningful if the simulator currently doesn't support idling. - Changed xq_debug_setup to use sim_debug instead of printf so that all debug output goes to the same place. - Restored the call to xq_svc after all successful calls to eth_write to allow receive processing to happen before the next event service time. This must have been inadvertently commented out while other things were being tested. pdp11_xu.c: (Mark Pizzolato) - Added SHOW XU FILTERS modifier (Dave Hittner) - Corrected SELFTEST command, enabling use by VMS 3.7, VMS 4.7, and Ultrix 1.1 (Dave Hittner) - Added address conflict check during attach. - Added loopback processing support - Fixed the fact that no broadcast packets were received by the DEUNA - Fixed transmitted packets to have the correct source MAC address. - Fixed incorrect address filter setting calling eth_filter(). pdp18b_stddev.c: - added clock coscheduling - revised TTI to use clock coscheduling and to fix perpetual CAF bug pdp18b_ttx.c: - revised to use clock coscheduling pdp8_clk.c: - added clock coscheduling pdp8_fpp.c: (Rick Murphy) - many bug fixes; now functional pdp8_tt.c: - revised to use clock coscheduling and to fix perpetual CAF bug pdp8_ttx.c: - revised to use clock cosheduling pdp8_sys.c: - added link to FPP pdp8_td.c: - fixed SDLC to clear AC (Dave Gesswein) sds_mt.c: - fixed bug in scan function decode (Peter Schorn) vax_cpu.c: - revised idle design (Mark Pizzolato) - fixed bug in SET CPU IDLE - fixed failure to clear PSL<tp> in BPT, XFC vax_cpu1.c: - revised idle design Mark Pizzolato) - added VEC_QMODE test in interrupt handler vax_fpa.c: - fixed integer overflow bug in EMODx (Camiel Vanderhoeven) - fixed POLYx normalizing before add mask bug (Camiel Vanderhoeven) - fixed missing arguments in 32b floating add (Mark Pizzolato) vax_octa.c (Camiel Vanderhoeven) - fixed integer overflow bug in EMODH - fixed POLYH normalizing before add mask bug vax_stddev.c: - revised to use clock coscheduling vax_syscm.c: - fixed t_addr printouts for 64b big-endian systems (Mark Pizzolato) vax_sysdev.c: - added power clear call to boot routine (Mark Pizzolato) vax780_sbi.c: - added AUTORESTART switch support (Mark Pizzolato) vax780_stddev.c - added REBOOT support (Mark Pizzolato) - revised to use clock coscheduling vaxmod_def.h - moved all Qbus devices to BR4; deleted RP definitions V3.8 revision history 1 08-Feb-09 scp.c: - revised RESTORE unit logic for consistency - "detach_all" ignores error status returns if shutting down (Dave Bryan) - DO cmd missing params now default to null string (Dave Bryan) - DO cmd sub_args now allows "\\" to specify literal backslash (Dave Bryan) - decommitted MTAB_VAL - fixed implementation of MTAB_NC - fixed warnings in help printouts - fixed "SHOW DEVICE" with only one enabled unit (Dave Bryan) sim_tape.c: - fixed signed/unsigned warning in sim_tape_set_fmt (Dave Bryan) sim_tmxr.c, sim_tmxr.h: - added line connection order to tmxr_poll_conn, added tmxr_set_lnorder and tmxr_show_lnorder (Dave Bryan) - print device and line to which connection was made (Dave Bryan) - added three new standardized SHOW routines all terminal multiplexers: - revised for new common SHOW routines in TMXR library - rewrote set size routines not to use MTAB_VAL hp2100_cpu.c (Dave Bryan): - VIS and IOP are now mutually exclusive on 1000-F - Removed A/B shadow register variables - Moved hp_setdev, hp_showdev to hp2100_sys.c - Moved non-existent memory checks to WritePW - Fixed mp_dms_jmp to accept lower bound, check write protection - Corrected DMS violation register set conditions - Refefined ABORT to pass address, moved def to hp2100_cpu.h - Combined dms and dms_io routines - JSB to 0/1 with W5 out and fence = 0 erroneously causes MP abort - Unified I/O slot dispatch by adding DIBs for CPU, MP, and DMA - Rewrote device I/O to model backplane signals - EDT no longer passes DMA channel - Added SET CPU IDLE/NOIDLE, idle detection for DOS/RTE - Breakpoints on interrupt trap cells now work hp2100_cpu0.c (Dave Bryan): - .FLUN and self-tests for VIS and SIGNAL are NOP if not present - Moved microcode function prototypes to hp2100_cpu1.h - Removed option-present tests (now in UIG dispatchers) - Added "user microcode" dispatcher for unclaimed instructions hp2100_cpu1.c (Dave Bryan): - Moved microcode function prototypes to hp2100_cpu1.h - Moved option-present tests to UIG dispatchers - Call "user microcode" dispatcher for unclaimed UIG instructions hp2100_cpu2.c (Dave Bryan): - Moved microcode function prototypes to hp2100_cpu1.h - Removed option-present tests (now in UIG dispatchers) - Updated mp_dms_jmp calling sequence - Fixed DJP, SJP, and UJP jump target validation - RVA/B conditionally updates dms_vr before returning value hp2100_cpu3.c (Dave Bryan): - Moved microcode function prototypes to hp2100_cpu1.h - Removed option-present tests (now in UIG dispatchers) - Updated mp_dms_jmp calling sequence hp2100_cpu4.c, hp2100_cpu7.c (Dave Bryan): - Moved microcode function prototypes to hp2100_cpu1.h - Removed option-present tests (now in UIG dispatchers) hp2100_cpu5.c (Dave Bryan): - Moved microcode function prototypes to hp2100_cpu1.h - Removed option-present tests (now in UIG dispatchers) - Redefined ABORT to pass address, moved def to hp2100_cpu.h - Rewrote device I/O to model backplane signals hp2100_cpu6.c (Dave Bryan): - Corrected .SIP debug formatting - Moved microcode function prototypes to hp2100_cpu1.h - Removed option-present tests (now in UIG dispatchers) - Rewrote device I/O to model backplane signals hp2100 all peripherals (Dave Bryan): - Rewrote device I/O to model backplane signals hp2100_baci.c (Dave Bryan): - Fixed STC,C losing interrupt request on BREAK - Changed Telnet poll to connect immediately after reset or attach - Added REG_FIT to register variables < 32-bit size - Moved fmt_char() function to hp2100_sys.c hp2100_dp.c, hp2100_dq.c (Dave Bryan): - Added REG_FIT to register variables < 32-bit size hp2100_dr.c (Dave Bryan): - Revised drc_boot to use ibl_copy hp2100_fp1.c (Dave Bryan): - Quieted bogus gcc warning in fp_exec hp2100_ipl.c (Dave Bryan): - Changed socket poll to connect immediately after reset or attach - Revised EDT handler to refine completion delay conditions - Revised ipl_boot to use ibl_copy hp2100_lpt.c (Dave Bryan): - Changed CTIME register width to match documentation hp2100_mpx.c (Dave Bryan): - Implemented 12792C eight-channel terminal multiplexer hp2100_ms.c (Dave Bryan): - Revised to use AR instead of saved_AR in boot hp2100_mt.c (Dave Bryan): - Fixed missing flag after CLR command - Moved write enable and format commands from MTD to MTC hp2100_mux.c (Dave Bryan): - SHOW MUX CONN/STAT with SET MUX DIAG is no longer disallowed - Changed Telnet poll to connect immediately after reset or attach - Added LINEORDER support - Added BREAK deferral to allow RTE break-mode to work hp2100_pif.c (Dave Bryan): - Implemented 12620A/12936A Privileged Interrupt Fences hp2100_sys.c (Dave Bryan): - Fixed IAK instruction dual-use mnemonic display - Moved hp_setdev, hp_showdev from hp2100_cpu.c - Changed sim_load to use WritePW instead of direct M[] access - Added PIF device - Moved fmt_char() function from hp2100_baci.c - Added MPX device hp2100_cpu.h (Dave Bryan): - Rearranged declarations with hp2100_cpu.c and hp2100_defs.h - Added mp_control to CPU state externals hp2100_cpu1.h (Dave Bryan): - Moved microcode function prototypes here hp2100_defs.h (Dave Bryan): - Added POLL_FIRST to indicate immediate connection attempt - Rearranged declarations with hp2100_cpu.h - Added PIF device - Declared fmt_char() function - Added MPX device i1401_cpu.c: - fixed bug in ZA and ZS (Bob Abeles) - fixed tape indicator implementation (Bob Abeles) - added missing magtape modifier A (Van Snyder) i1401_mt.c: - added -n (no rewind) option to BOOT (Van Snyder) - fixed bug to mask input to 6b on read (Bob Abeles) lgp_stddev.c: - changed encode character from # to !, due to overlap pdp11_cpu.c: - fixed failure to clear cpu_bme on RESET (Walter Mueller) pdp11_dz.c: - added MTAB_NC modifier on SET LOG command (Walter Mueller) pdp11_io.c, vax_io.c, vax780_uba.c: - revised to use PDP-11 I/O library pdp11_io_lib.c: - created common library for Unibus/Qbus support routines pdp11_cis.c, vax_cis.c: - fixed bug in ASHP left overflow calc (Word/NibbleLShift) - fixed bug in DIVx (LntDstr calculation) sds_lp.c: - fixed loss of carriage control position on space op vax_stddev.c, vax780_stddev.c - modified to resync TODR on any clock reset 0 15-Jun-08 scp.c: - fixed bug in local/global register search (Mark Pizzolato) - fixed bug in restore of RO units (Mark Pizzolato) - added SET/SHO/NO BR with default argument (Dave Bryan) sim_tmxr.c - worked around Telnet negotiation problem with QCTerm (Dave Bryan) gri_defs.h, gri_cpu.c, gri_sys.c: - added GRI-99 support hp2100_baci.c (Dave Bryan): - Implemented 12966A Buffered Asynchronous Communications Interface simulator hp2100_cpu.c (Dave Bryan): - Memory ex/dep and bkpt type default to current map mode - Added SET CPU DEBUG and OS/VMA flags, enabled OS/VMA - Corrected MP W5 (JSB) jumper action, SET/SHOW reversal, mp_mevff clear on interrupt with I/O instruction in trap cell - Removed DBI support from 1000-M (was temporary for RTE-6/VM) - Enabled EMA and VIS, added EMA, VIS, and SIGNAL debug flags - Enabled SIGNAL instructions, SIG debug flag - Fixed single stepping through interrupts hp2100_cpu0.c (Dave Bryan and Holger Veit): - Removed and implemented "cpu_rte_vma" and "cpu_rte_os" - Removed and implemented "cpu_vis" and "cpu_signal" - Removed and implemented "cpu_rte_ema" hp2100_cpu1.c (Dave Bryan): - Added fprint_ops, fprint_regs for debug printouts - Enabled DIAG as NOP on 1000 F-Series - Fixed VIS and SIGNAL to depend on the FPP and HAVE_INT64 hp2100_cpu3.c (Dave Bryan): - Fixed unsigned divide bug in .DDI - Fixed unsigned multiply bug in .DMP - Added implementation of DBI self-test hp2100_cpu4.c (Dave Bryan): - Fixed B register return bug in /CMRT hp2100_cpu5.c (Holger Veit): - Implemented RTE-6/VM Virtual Memory Area firmware - Implemented RTE-IV Extended Memory Area firmware hp2100_cpu6.c (Dave Bryan): - Implemented RTE-6/VM OS accelerator firmware hp2100_cpu7.c (Holger Veit): - Implemented Vector Instruction Set and SIGNAL/1000 firmware hp2100_ds.c (Dave Bryan): - Corrected and verified ioCRS action - Corrected DPTR register definition from FLDATA to DRDATA hp2100_fp.c (Mark Pizzolato) - Corrected fp_unpack mantissa high-word return hp2100_fp1.c (Dave Bryan): - Reworked "complement" to avoid inlining bug in gcc-4.x - Fixed uninitialized return in fp_accum when setting hp2100_mux.c (Dave Bryan): - Sync mux poll with console poll for idle compatibility hp2100_stddev.c (Dave Bryan): - Fixed PTR trailing null counter for tape re-read - Added IPTICK register to CLK to display CPU instr/tick - Corrected and verified ioCRS actions - Changed TTY console poll to 10 msec. real time - Synchronized CLK with TTY if set for 10 msec. - Added UNIT_IDLE to TTY and CLK - Removed redundant control char handling definitions - Changed TTY output wait from 100 to 200 for MSU BASIC hp2100_sys.c (Dave Bryan): - Added BACI device - Added RTE OS/VMA/EMA mnemonics - Changed fprint_sym to handle step with irq pending hp2100_cpu.h (Dave Bryan): - Added calc_defer() prototype - Added extern sim_deb, cpu_dev, DEB flags for debug printouts - Added extern intaddr, mp_viol, mp_mevff, calc_int, dev_ctl, ReadIO, WriteIO for RTE-6/VM microcode support hp2100_cpu1.h (Dave Bryan): - Corrected OP_AFF to OP_AAFF for SIGNAL/1000 - Removed unused operand patterns - Added fprint_ops, fprint_regs for debug printouts - Revised OP_KKKAKK operand profile to OP_CCCACC for $LOC hp2100_defs.h (Dave Bryan): - Added BACI device - Added 16/32-bit unsigned-to-signed conversions - Changed TMR_MUX to TMR_POLL for idle support - Added POLLMODE, sync_poll() declaration - Added I_MRG, I_ISZ, I_IOG, I_STF, and I_SFS instruction masks - Added I_MRG_I, I_JSB, I_JSB_I, and I_JMP instruction masks nova_defs.h (Bruce Ray): - added support for third-party 64KW memory nova_clk.c (Bruce Ray): - renamed to RTC, to match DG literature nova_cpu.c (Bruce Ray): - added support for third-party 64KW memory - added Nova 3 "secret" instructions - added CPU history support nova_dkp.c (Bruce Ray): - renamed to DKP, to match DG literature - fixed numerous bugs in both documented and undocumented behavior - changed bootstrap code to DG official sequence nova_dsk.c (Bruce Ray): - renamed to DSK, to match DG literature - added support for undocumented behavior - changed bootstrap code to DG official sequence nova_mta.c (Bruce Ray): - renamed to MTA, to match DG literature - changed bootstrap code to DG official sequence nova_plt.c, nova_pt.c (Bruce Ray): - added 7B/8B support nova_sys.c (Bruce Ray): - fixed mistaken instruction mnemonics pdp11_cpu.c, pdp11_io.c, pdp11_rh.c: - fixed DMA memory address limit test (John Dundas) - fixed MMR0 treatment in RESET (Walter Mueller) pdp11_cpumod.h, pdp11_cpumod.c: - fixed write behavior of 11/70 MBRK, LOSIZE, HISIZE (Walter Mueller) - added support to set default state of KDJ11B,E clock control register pdp11_dc.c: - added support for DC11 pdp11_defs.h: - added KE, KG, RC, DC support - renamed DL11 devices pdp11_dl.c: - renamed devices to DLI/DLO, to match DC11 - added modem control pdp11_io.c: - added autoconfigure support for DC11 pdp11_ke.c: - added support for KE11A pdp11_kg.c (John Dundas): - added support for KG11A pdp11_rc.c (John Dundas): - added support for RC11 pdp11_sys.c: - modified to allow -A, -B use with 8b devices - added KE, KG, RC, DC support - renamed DL11 devices vax_cmode.c, vax_io.c, vax780_uba.c: - fixed declarations (Mark Pizzolato) V3.7 revision history 3 02-Sep-07 scp.c: - fixed bug in SET THROTTLE command pdp10_cpu.c: - fixed non-portable usage in SHOW HISTORY routine pdp11_ta.c: - forward op at BOT skips initial file gap pdp8_ct.c: - forward op at BOT skips initial file gap - fixed handling of BEOT vax_cpu.c: - fixed bug in read access g-format indexed specifiers 2 12-Jul-07 sim_ether.c (Dave Hittner): - fixed non-ethernet device removal loop (Naoki Hamada) - added dynamic loading of wpcap.dll; - corrected exceed max index bug in ethX lookup - corrected failure to look up ethernet device names in the registry on Windows XP x64 sim_timer.c: - fixed idle timer event selection algorithm h316_lp.c: - fixed loss of last print line (Theo Engel) h316_mt.c: - fixed bug in write without stop (Theo Engel) h316_stddev.c: - fixed bug in clock increment (Theo Engel) i1401_cpu.c: - added recognition of overlapped operation modifiers - remove restriction on load-mode binary tape operations i1401_mt.c: - fixed read tape mark operation (Van Snyder) - remove restriction on load-mode binary tape operations pdp1_cpu.c: - fixed typo in SBS clear (Norm Lastovica) pdp11_rh.c, pdp11_rp.c, pdp11_tu.c: - CS1 DVA is in the device, not the MBA pdp8_ct.c: - fixed typo (Norm Lastovica) vax_cpu.c: - revised idle detector 1 14-May-07 scp.c: - modified sim_instr invocation to call sim_rtcn_init_all - fixed bug in get_sim_opt (reported by Don North) - fixed bug in RESTORE with changed memory size - added global 'RESTORE in progress' flag - fixed breakpoint actions in DO command file processing (Dave Bryan) all CPU's with clocks: - removed clock initialization (now done in SCP) hp2100_cpu.c (Dave Bryan): - EDT passes input flag and DMA channel in dat parameter hp2100_ipl.c (Dave Bryan): - IPLI EDT delays DMA completion interrupt for TSB hp2100_mux.c (Dave Bryan): - corrected "mux_sta" size from 16 to 21 elements - fixed "muxc_reset" to clear lines 16-20 - fixed control card OTx to set current channel number - fixed to set "muxl_ibuf" in response to a transmit interrupt - changed "mux_xbuf", "mux_rbuf" declarations from 8 to 16 bits - fixed to set "mux_rchp" when a line break is received - fixed incorrect "odd_par" table values - reversed test in "RCV_PAR" to return "LIL_PAR" on odd parity - rixed mux reset (ioCRS) to clear port parameters - fixed to use PUT_DCH instead of PUT_CCH for data channel status - added DIAG/TERM modifiers to implement diagnostic mode pdp11_cpumod.c: - changed memory size routine to work with RESTORE pdp11_hk.c: - NOP and DCLR (at least) do not check drive type - MR2 and MR3 only updated on NOP pdp10_tu.c, pdp11_tu.c: - TMK sets FCE only on read (Naoki Hamada) pdp11_xu.c: - added missing FC_RMAL command - cleared multicast on write vax_moddefs.h, vax_cpu1.c: - separated PxBR and SBR mbz checks vax780_defs.h - separated PxBR and SBR mbz checks - modified mbz checks to reflect 780 microcode patches (Naoki Hamada) vax_mmu.c: - added address masking to all SBR-based memory reads 0 30-Jan-07 scp.c: - implemented throttle commands - added -e to control error processing in DO command files (Dave Bryan) sim_console.c: - fixed handling of non-printable characters in KSR mode sim_tape.c: - fixed bug in reverse operations for P7B-format tapes - fixed bug in reverse operations across erase gaps sim_timer.c: - added throttle support - added idle support (based on work by Mark Pizzolato) gri_stddev.c, h316_stddev.c, pdp18b_tt1.c - fixed handling of non-printable characters in KSR mode hp2100_cpu.c, hp2100_cpu0.c, hp2100_cpu1.c, hp2100_cpu2.c, hp2100_cpu3.c, hp2100_cpu4.c (Dave Bryan): - reorganized CPU modules for easier addition of new instructions - added Double Integer instructions, 1000-F CPU, 2114 and 2115 CPUs, 12K and 24K memory sizes, 12607B and 12578A DMA controllers, and 21xx binary loader protection - fixed DMS self-test instruction execution on 1000-M - fixed indirect interrupt holdoff logic hp2100_ds.c: - fixed REQUEST STATUS to clear status-1 (Dave Bryan) hp2100_fp1.c: - Added Floating Point Processor (Dave Bryan) hp2100_lps.c: - fixed diag-mode CLC response i7094_cpu.c: - fixed new bug in halt IO wait loop - added IFT, EFT expanded core test instructions id16_cpu.c, id32_cpu.c: - removed separate multiplexor clock - added idle support id_pas.c: - synced multiplexor poll to real-time clock id_tt.c, id_ttp.c: - fixed handling of non-printable characters in KSR mode - synced keyboard poll to real-time clock id_uvc.c: - changed line-time clock to be free-running pdp1_cpu.c: - added 16-channel sequence break system (API) support - added PDP-1D support pdp1_clk.c: - first release pdp1_dcs.c: - first release pdp1_stddev.c: - separated TTI, TTO for API support pdp1_sys.c: - added PDP-1D, 16-channel SBS, clock, DCS support - fixed bugs in character input, block loader pdp10_cpu.c: - added idle support pdp10_defs.h, pdp10_sys.c: - added CR support pdp10_fe.c, pdp10_tim.c: - synced keyboard poll to real-time clock pdp11_cr.c: - revised for PDP-10 compatibility (CD11 only) pdp11_cpu.c: - added idle support - fixed bug in ASH -32 C value pdp11_rf.c: - fixed unit mask (John Dundas) pdp11_stddev.c, vax_stddev.c, vax780_stddev.c: - synced keyboard poll to real-time clock - added clock coscheduling support pdp11_ta.c: - first release pdp11_vh.c: - synced service poll to real-time clock - changed device to be off by default pdp11_dz.c, pdp11_xq.c, pdp11_xu.c: - synced service poll to real-time clock pdp11_sys.c: - fixed operand order in EIS instructions (W.F.J. Mueller) - added TA11 support pdp18b_cpu.c: - fixed incorrect value of PC on instruction fetch mem mmgt error - fixed PDP-15 handling of mem mmgt traps (sets API 3) - fixed PDP-15 handling of CAL API 4 (sets only if 0-3 inactive) - fixed PDP-15 CAF to clear memory management mode register - fixed boundary test in KT15/XVM (reported by Andrew Warkentin) - added XVM RDCLK instruction - added idle support and infinite loop detection pdp18b_rf.c: - fixed bug, DSCD does not clear function register pdp18b_stddev.c: - added PDP-15 program-selectable duplex handling instruction - fixed PDP-15 handling of reader out-of-tape - fixed handling of non-printable characters in KSR mode - added XVM RDCLK instruction - changed real-time clock to be free running - synced keyboard poll to real-time clock pdp18b_tt1.c - fixed handling of non-printable characters in KSR mode pdp18b_sys.c: - added XVM RDCLK instruction pdp8_cpu.c: - fixed SC value after DVI overflow (Don North) - added idle support and infinite loop detection pdp8_ct.c: - first release pdp8_clk.c: - changed real-time clock to be free running pdp8_sys.c: - added TA8E support - added ability to disambiguate overlapping IOT definitions pdp8_tt.c: - fixed handling of non-printable characters in KSR mode - synced keyboard poll to real-time clock vax_cpu.c, vax_cpu1.c: - added idle support vax_syscm.c: - fixed operand order in EIS instructions (W.F.J. Mueller) V3.6 revision history 1 25-Jul-06 sim_console.c: - implemented SET/SHOW PCHAR all DECtapes: - fixed conflict in ATTACH switches hp2100_ms.c (Dave Bryan): - added CAPACITY as alternate for REEL - fixed EOT test for unlimited reel size i1620_cd.c (Tom McBride): - fixed card reader fgets call - fixed card reader boot sequence i7094_cd.c: - fixed problem with 80 column full cards i7094_cpu.c: - fixed bug in halt IO wait loop i7094_sys.c: - added binary loader (courtesy of Dave Pitt) pdp1_cpu.c: - fixed bugs in MUS and DIV pdp11_cis.c: - added interrupt tests to character instructions - added 11/44 stack probe test to MOVCx (only) pdp11_dl.c: - first release pdp11_rf.c: - first release pdp11_stddev.c: - added UC support to TTI, TTO pdp18b_cpu.c: - fixed RESET to clear AC, L, and MQ pdp18b_dt.c: - fixed checksum calculation bug for Type 550 pdp18b_fpp.c: - fixed bugs in left shift, multiply pdp18b_stddev.c: - fixed Baudot letters/figures inversion for PDP-4 - fixed letters/figures tracking for PDP-4 - fixed PDP-4/PDP-7 default terminal to be local echo pdp18b_sys.c: - added Fiodec, Baudot display - generalized LOAD to handle HRI, RIM, and BIN files pdp8_ttx.c: - fixed bug in DETACH routine 0 15-May-06 scp.c: - revised save file format to save options, unit capacity sim_tape.c, sim_tape.h: - added support for finite reel size - fixed bug in P7B write record most magtapes: - added support for finite reel size h316_cpu.c: fixed bugs in LLL, LRL (Theo Engel) h316_lp.c: fixed bug in blanks backscanning (Theo Engel) h316_stddev.c: fixed bugs in punch state handling (Theo Engel) i1401_cpu.c: fixed bug in divide (reported by Van Snyder) i16_cpu.c: fixed bug in DH (Mark Hittinger) i32_cpu.c: - fixed bug in DH (Mark Hittinger) - added support for 8 register banks in 8/32 i7094: first release id_io.c: fixed bug, GO preserves EXA and SSTA (Davis Johnson) id_idc.c: - fixed WD/WH handling (Davis Johnson) - fixed bug, nop command should be ignored (Davis Johnson) nova_cpu.c: fixed bug in DIVS (Mark Hittinger) pdp11_cis.c: (all reported by John Dundas) - fixed bug in decode table - fixed bug in ASHP - fixed bug in write decimal string with mmgt enabled - fixed bug in 0-length strings in multiply/divide pdp11_cpu.c: fixed order of operand fetching in XOR for SDSD models pdp11_cr.c: added CR11/CD11 support pdp11_tc.c: - fixed READ to set extended data bits in TCST (Alan Frisbie) vax780_fload.c: added FLOAD command vax780_sbi.c: fixed writes to ACCS vax780_stddev.c: revised timer logic for EVKAE (reported by Tim Stark) vax_cis.c: (all reported by Tim Stark) - fixed MOVTC, MOVTUC to preserve cc's through page faults - fixed MOVTUC to stop on translated == escape - fixed CVTPL to set registers before destination reg write - fixed CVTPL to set correct cc bit on overflow - fixed EDITPC to preserve cc's through page faults - fixed EDITPC EO$BLANK_ZERO count, cc test - fixed EDITPC EO$INSERT to insert fill instead of blank - fixed EDITPC EO$LOAD_PLUS/MINUS to skip character vax_cpu.c: - added KESU capability to virtual examine - fixed bugs in virtual examine - rewrote CPU history function for improved usability (bugs below reported by Tim Stark) - fixed fault cleanup to clear PSL<tp> - fixed ADAWI r-mode to preserve dst<31:16> - fixed ACBD/G to test correct operand - fixed access checking on modify-class specifiers - fixed branch address calculation in CPU history - fixed bug in reported VA on faulting cross-page write vax_cpu1.c: (all reported by Tim Stark) - added access check on system PTE for 11/780 - added mbz check in LDPCTX for 11/780 vax_cmode.c: (all reported by Tim Stark) - fixed omission of SXT - fixed order of operand fetching in XOR vax_fpa.c: (all reported by Tim Stark) - fixed POLYD, POLYG to clear R4, R5 - fixed POLYD, POLYG to set R3 correctly - fixed POLYD, POLYG to not exit prematurely if arg = 0 - fixed POLYD, POLYG to do full 64b multiply - fixed POLYF, POLYD, POLYG to remove truncation on add - fixed POLYF, POLYD, POLYG to mask mul reslt to 31b/63b/63b - fixed fp add routine to test for zero via fraction to support "denormal" argument from POLYF, POLYD, POLYG - fixed bug in 32b floating multiply routine - fixed bug in 64b extended modulus routine vax_mmu.c: - added access check on system PTE for 11/780 vax_octa.c: (all reported by Tim Stark) - fixed MNEGH to test negated sign, clear C - fixed carry propagation in qp_inc, qp_neg, qp_add - fixed pack routines to test for zero via fraction - fixed ACBH to set cc's on result - fixed POLYH to set R3 correctly - fixed POLYH to not exit prematurely if arg = 0 - fixed POLYH to mask mul reslt to 127b - fixed fp add routine to test for zero via fraction to support "denormal" argument from POLYH - fixed EMODH to concatenate 15b of 16b extension - fixed bug in reported VA on faulting cross-page write V3.5 revision history patch date module(s) and fix(es) 2 07-Jan-06 scp.c: - added breakpoint spaces - added REG_FIT support sim_console.c: added ASCII character processing routines sim_tape.c, sim_tape.h: - added write support for P7B format - fixed bug in write forward (Dave Bryan) h316_stddev.c, hp2100_stddev.c, hp2100_mux.c, id_tt.c, id_ttp.c, id_pas.c, pdp8_tt.c, pdp8_ttx.c, pdp11_stddev.c, pdp11_dz.c, pdp18b_stddev.c, pdp18b_tt1.c, vax_stddev, gri_stddev.c: - revised to support new character handling routines pdp10_rp.c: fixed DCLR not to clear disk address pdp11_hk.c: fixed overlapped seek interaction with NOP, etc pdp11_rh.c: added enable/disable routine pdp11_rq.c, pdp11_tm.c, pdp11_tq.c, pdp11_ts.c - widened address display to 64b when USE_ADDR64 pdp11_rp.c: - fixed DCLR not to clear disk address - fixed device enable/disable logic to include Massbus adapter - widened address display to 64b when USE_ADDR64 pdp11_tu.c: - fixed device enable/disable logic to include Massbus adapter - widened address display to 64b when USE_ADDR64 - changed default adapter to TM03 (for VMS) pdp8_df.c, pdp8_dt.c, pdp8_rf.c: - fixed unaligned access bug (Doug Carman) pdp8_rl.c: fixed IOT 61 decoding bug (David Gesswein) vax_cpu.c: - fixed breakpoint detection when USE_ADDR64 option is active - fixed CVTfi to trap on integer overflow if PSW<iv> set 1 15-Oct-05 All CPU's, other sources: fixed declaration inconsistencies (Sterling Garwood) i1401_cpu.c: added control for old/new character encodings i1401_cd.c, i1401_lpt.c, i1401_tty.c: - changed character encodings to be consistent with 7094 - changed column binary format to be consistent with 7094 - added choice of business or Fortran set for output encoding i1401_sys.c: changed WM character to ` under new encodings i1620_cd.c, i1620_lpt.c, i1620_tty.c: - changed character encodings to be consistent with 7094 pdp10_cpu.c: changed MOVNI to eliminate gcc warning pdp11_io.c: fixed bug in autoconfiguration (missing XU) vax_io.c: fixed bug in autoconfiguration (missing XU) vax_fpa.c: fixed bug in 32b structure definitions (Jason Stevens) 0 1-Sep-05 Note: most source modules have been edited to improve readability and to fix declaration and cast problems in C++ all instruction histories: fixed reversed arguments to calloc scp.c: revised to trim trailing spaces on file inputs sim_sock.c: fixed SIGPIPE error on Unix sim_ether.c: added Windows user-defined adapter names (Timothe Litt) sim_tape.c: fixed misallocation of TPC map array sim_tmxr.c: added support for SET <unit> DISCONNECT hp2100_mux.c: added SET MUXLn DISCONNECT i1401_cpu.c: - fixed SSB-SSG clearing on RESET (reported by Ralph Reinke) - removed error stops in MCE i1401_cd.c: fixed read, punch to ignore modifier on 1, 4 char inst (reported by Van Snyder) id_pas.c: - fixed bug in SHOW CONN/STATS - added SET PASLn DISCONNECT pdp10_ksio.c: revised for new autoconfiguration interface pdp11_cpu.c: replaced WAIT clock queue check with API call pdp11_cpumod.c: added additional 11/60 registers pdp11_io.c: revised autoconfiguration algorithm and interface pdp11_dz.c: revised for new autoconfiguration interface pdp11_vh.c: - revised for new autoconfiguration interface - fixed bug in vector display routine pdp11_xu.c: fixed runt packet processing (Tim Chapman) pdp18b_cpu.c, pdp18b_sys.c: - removed spurious AAS instruction pdp18b_tt1.c: - fixed bug in SHOW CONN/STATS - fixed bug in SET LOG/NOLOG - added SET TTOXn DISCONNECT pdp8_ttx.c: - fixed bug in SHOW CONN/STATS - fixed bug in SET LOG/NOLOG - added SET TTOXn DISCONNECT sds_mux.c: - fixed bug in SHOW CONN/STATS - added SET MUXLn DISCONNECT vaxmod_defs.h: added QDSS support vax_io.c: revised autoconfiguration algorithm and interface V3.4 revision history 0 01-May-04 scp.c: - fixed ASSERT code - revised syntax for SET DEBUG (Dave Bryan) - revised interpretation of fprint_sym, fparse_sym returns - moved DETACH sanity tests into detach_unit sim_sock.h and sim_sock.c: - added test for WSAEINPROGRESS (Tim Riker) many: revised detach routines to test for attached state hp2100_cpu.c: reorganized CPU options (Dave Bryan) hp2100_cpu1.c: reorganized EIG routines (Dave Bryan) hp2100_fp1.c: added FFP support (Dave Bryan) id16_cpu.c: - fixed bug in show history routine (Mark Hittinger) - revised examine/deposit to do words rather than bytes id32_cpu.c: - fixed bug in initial memory allocation - fixed bug in show history routine (Mark Hittinger) - revised examine/deposit to do words rather than bytes id16_sys.c, id32_sys: - revised examine/deposit to do words rather than bytes pdp10_tu.c: - fixed bug, ERASE and WREOF should not clear done (reported by Rich Alderson) - fixed error reporting pdp11_tu.c: fixed error reporting V3.3 revision history 2 08-Mar-05 scp.c: added ASSERT command (Dave Bryan) h316_defs.h: fixed IORETURN macro h316_mt.c: fixed error reporting from OCP (Philipp Hachtmann) h316_stddev.c: fixed bug in OCP '0001 (Philipp Hachtmann) hp2100_cpu.c: split out EAU and MAC instructions hp2100_cpu1.c: (Dave Bryan) - fixed missing MPCK on JRS target - removed EXECUTE instruction (is NOP in actual microcode) hp2100_fp: (Dave Bryan) - fixed missing negative overflow renorm in StoreFP i1401_lp.c: fixed bug in write_line (reported by Van Snyder) id32_cpu.c: fixed branches to mask new PC (Greg Johnson) pdp11_cpu.c: fixed bugs in RESET for 11/70 (reported by Tim Chapman) pdp11_cpumod.c: - fixed bug in SHOW MODEL (Sergey Okhapkin) - made SYSID variable for 11/70 (Tim Chapman) - added MBRK write case for 11/70 (Tim Chapman) pdp11_rq: added RA60, RA71, RA81 disks pdp11_ry: fixed bug in boot code (reported by Graham Toal) vax_cpu.c: fixed initial state of cpu_extmem 1 05-Jan-05 h316_cpu.c: fixed bug in DIV h316_stddev.c: - fixed bug in SKS '104 (reported by Philipp Hachtmann) - fixed bug in SKS '504 - adder reader/punch ASCII file support - added Teletype reader/punch support h316_dp.c: fixed bug in skip on !seeking h316_mt.c: fixed bug in DMA/DMC support h316_lp.c: fixed bug in DMA/DMC support hp2100_cpu.c: - fixed DMA reset to clear alternate CTL flop (Dave Bryan) - fixed DMA reset to not clear control words (Dave Bryan) - fixed SBS, CBS, TBS to do virtual reads - separated A/B from M[0/1], for DMA IO (Dave Bryan) - added SET CPU 21MX-M, 21MX-E (Dave Brian) - disabled TIMER/EXECUTE/DIAG instructions for 21MX-M (Dave Bryan) - added post-processor to maintain T/M consistency (Dave Bryan) hp2100_ds.c: first release hp2100_lps.c (all changes from Dave Bryan) - added restart when set online, etc. - fixed col count for non-printing chars hp2100_lpt.c (all changes from Dave Bryan) - added restart when set online, etc. hp2100_sys.c (all changes from Dave Bryan): - added STOP_OFFLINE, STOP_PWROFF messages i1401_sys.c: added address argument support (Van Snyder) id_mt.c: added read-only file support lgp_cpu.c, lgp_sys.c: modified VM pointer setup pdp11_cpu.c: fixed WAIT to work in all modes (John Dundas) pdp11_tm.c, pdp11_ts.c: added read-only file support sds_mt.c: added read-only file support 0 23-Nov-04 scp.c: - added reset_all_p (powerup) - fixed comma-separated SET options (Dave Bryan) - changed ONLINE/OFFLINE to ENABLED/DISABLED (Dave Bryan) - modified to flush device buffers on stop (Dave Bryan) - changed HELP to suppress duplicate command displays sim_console.c: - moved SET/SHOW DEBUG under CONSOLE hierarchy hp2100_cpu.c: (all fixes by Dave Bryan) - moved MP into its own device; added MP option jumpers - modified DMA to allow disabling - modified SET CPU 2100/2116 to truncate memory > 32K - added -F switch to SET CPU to force memory truncation - fixed S-register behavior on 2116 - fixed LIx/MIx behavior for DMA on 2116 and 2100 - fixed LIx/MIx behavior for empty I/O card slots - modified WRU to be REG_HRO - added BRK and DEL to save console settings - fixed use of "unsigned int16" in cpu_reset hp2100_dp.c: (all fixes by Dave Bryan) - fixed enable/disable from either device - fixed ANY ERROR status for 12557A interface - fixed unattached drive status for 12557A interface - status cmd without prior STC DC now completes (12557A) - OTA/OTB CC on 13210A interface also does CLC CC - fixed RAR model - fixed seek check on 13210 if sector out of range hp2100_dq.c: (all fixes by Dave Bryan) - fixed enable/disable from either device - shortened xtime from 5 to 3 (drive avg 156KW/second) - fixed not ready/any error status - fixed RAR model hp2100_dr.c: (all fixes by Dave Bryan) - fixed enable/disable from either device - fixed sector return in status word - provided protected tracks and "Writing Enabled" status bit - fixed DMA last word write, incomplete sector fill value - added "parity error" status return on writes for 12606 - added track origin test for 12606 - added SCP test for 12606 - fixed 12610 SFC operation - added "Sector Flag" status bit - added "Read Inhibit" status bit for 12606 - fixed current-sector determination - added TRACKPROT modifier hp2100_ipl.c, hp2100_ms.c: (all fixes by Dave Bryan) - fixed enable/disable from either device hp2100_lps.c: (all fixes by Dave Bryan) - added SET OFFLINE/ONLINE, POWEROFF/POWERON - fixed status returns for error conditions - fixed handling of non-printing characters - fixed handling of characters after column 80 - improved timing model accuracy for RTE - added fast/realistic timing - added debug printouts hp2100_lpt.c: (all fixes by Dave Bryan) - added SET OFFLINE/ONLINE, POWEROFF/POWERON - fixed status returns for error conditions - fixed TOF handling so form remains on line 0 hp2100_stddev.c (all fixes by Dave Bryan) - added paper tape loop mode, DIAG/READER modifiers to PTR - added PV_LEFT to PTR TRLLIM register - modified CLK to permit disable hp2100_sys.c: (all fixes by Dave Bryan) - added memory protect device - fixed display of CCA/CCB/CCE instructions i1401_cpu.c: added =n to SHOW HISTORY id16_cpu.c: added instruction history id32_cpu.c: added =n to SHOW HISTORY pdp10_defs.h: revised Unibus DMA API's pdp10_ksio.c: revised Unibus DMA API's pdp10_lp20.c: revised Unibus DMA API's pdp10_rp.c: replicated register state per drive pdp10_tu.c: - fixed to set FCE on short record - fixed to return bit<15> in drive type - fixed format specification, 1:0 are don't cares - implemented write check - TMK is cleared by new motion command, not DCLR - DONE is set on data transfers, ATA on non data transfers pdp11_defs.h: - revised Unibus/Qbus DMA API's - added CPU type and options flags pdp11_cpumod.h, pdp11_cpumod.c: - new routines for setting CPU type and options pdp11_io.c: revised Unibus/Qbus DMA API's all PDP-11 DMA peripherals: - revised Unibus/Qbus DMA API's pdp11_hk.c: CS2 OR must be zero for M+ pdp11_rh.c, pdp11_rp.c, pdp11_tu.c: - split Massbus adapter from controllers - replicated RP register state per drive - added TM02/TM03 with TE16/TU45/TU77 drives pdp11_rq.c, pdp11_tq.c: - provided different default timing for PDP-11, VAX - revised to report CPU bus type in stage 1 - revised to report controller type reflecting bus type - added -L switch (LBNs) to RAUSER size specification pdp15_cpu.c: added =n to SHOW HISTORY pdp15_fpp.c: - fixed URFST to mask low 9b of fraction - fixed exception PC setting pdp8_cpu.c: added =n to SHOW HISTORY vax_defs.h: - added octaword, compatibility mode support vax_moddefs.h: - revised Unibus/Qbus DMA API's vax_cpu.c: - moved processor-specific code to vax_sysdev.c - added =n to SHOW HISTORY vax_cpu1.c: - moved processor-specific IPR's to vax_sysdev.c - moved emulation trap to vax_cis.c - added support for compatibility mode vax_cis.c: new full VAX CIS instruction emulator vax_octa.c: new full VAX octaword and h_floating instruction emulator vax_cmode.c: new full VAX compatibility mode instruction emulator vax_io.c: - revised Unibus/Qbus DMA API's vax_io.c, vax_stddev.c, vax_sysdev.c: - integrated powerup into RESET (with -p) vax_sys.c: - fixed bugs in parsing indirect displacement modes - fixed bugs in displaying and parsing character data vax_syscm.c: added display and parse for compatibility mode vax_syslist.c: - split from vax_sys.c - removed PTR, PTP V3.2 revision history 3 03-Sep-04 scp.c: - added ECHO command (Dave Bryan) - qualified RESTORE detach with SIM_SW_REST sim_console: added OS/2 EMX fixes (Holger Veit) sim_sock.h: added missing definition for OS/2 (Holger Veit) hp2100_cpu.c: changed error stops to report PC not PC + 1 (Dave Bryan) hp2100_dp.c: functional and timing fixes (Dave Bryan) - controller sets ATN for all commands except read status - controller resumes polling for ATN interrupts after read status - check status on unattached drive set busy and not ready - check status tests wrong unit for write protect status - drive on line sets ATN, will set FLG if polling hp2100_dr.c: fixed CLC to stop operation (Dave Bryan) hp2100_ms.c: functional and timing fixes (Dave Bryan) - fixed erroneous execution of rejected command - fixed erroneous execution of select-only command - fixed erroneous execution of clear command - fixed odd byte handling for read - fixed spurious odd byte status on 13183A EOF - modified handling of end of medium - added detailed timing, with fast and realistic modes - added reel sizes to simulate end of tape - added debug printouts hp2100_mt.c: modified handling of end of medium (Dave Bryan) hp2100_stddev.c: added tab to control char set (Dave Bryan) pdp11_rq.c: VAX controllers luns start at 0 (Andreas Cejna) vax_cpu.c: fixed bug in EMODD/G, second word of quad dst not probed 2 17-Jul-04 scp.c: fixed problem ATTACHing to read only files (John Dundas) sim_console.c: revised Windows console code (Dave Bryan) sim_fio.c: fixed problem in big-endian read (reported by Scott Bailey) gri_cpu.c: updated MSR, EAO functions hp_stddev.c: generalized handling of control char echoing (Dave Bryan) vax_sys.c: fixed bad block initialization routine 1 10-Jul-04 scp.c: added SET/SHOW CONSOLE subhierarchy hp2100_cpu.c: fixes and added features (Dave Bryan) - SBT increments B after store - DMS console map must check dms_enb - SFS x,C and SFC x,C work - MP violation clears automatically on interrupt - SFS/SFC 5 is not gated by protection enabled - DMS enable does not disable mem prot checks - DMS status inconsistent at simulator halt - Examine/deposit are checking wrong addresses - Physical addresses are 20b not 15b - Revised DMS to use memory rather than internal format - Added instruction printout to HALT message - Added M and T internal registers - Added N, S, and U breakpoints Revised IBL facility to conform to microcode Added DMA EDT I/O pseudo-opcode Separated DMA SRQ (service request) from FLG all HP2100 peripherals: - revised to make SFS x,C and SFC x,C work - revised to separate SRQ from FLG all HP2100 IBL bootable peripherals: - revised boot ROMs to use IBL facility - revised SR values to preserve SR<5:3> hp2100_lps.c, hp2100_lpt.c: fixed timing hp2100_dp.c: fixed interpretation of SR<0> hp2100_dr.c: revised boot code to use IBL algorithm hp2100_mt.c, hp2100_ms.c: fixed spurious timing error after CLC (Dave Bryan) hp2100_stddev.c: - fixed input behavior during typeout for RTE-IV - suppressed nulls on TTY output for RTE-IV hp2100_sys.c: added SFS x,C and SFC x,C to print/parse routines pdp10_fe.c, pdp11_stddev.c, pdp18b_stddev.c, pdp8_tt.c, vax_stddev.c: - removed SET TTI CTRL-C option pdp11_tq.c: - fixed bug in reporting write protect (reported by Lyle Bickley) - fixed TK70 model number and media ID (Robert Schaffrath) pdp11_vh.c: added DHQ11 support (John Dundas) pdp11_io.c, vax_io.c: fixed DHQ11 autoconfigure (John Dundas) pdp11_sys.c, vax_sys.c: added DHQ11 support (John Dundas) vax_cpu.c: fixed bug in DIVBx, DIVWx (reported by Peter Trimmel) 0 04-Apr-04 scp.c: - added sim_vm_parse_addr and sim_vm_fprint_addr - added REG_VMAD - moved console logging to SCP - changed sim_fsize to use descriptor rather than name - added global device/unit show modifiers - added device debug support (Dave Hittner) - moved device and unit flags, updated save format sim_ether.c: - further generalizations (Dave Hittner, Mark Pizzolato) sim_tmxr.h, sim_tmxr.c: - added tmxr_linemsg - changed TMXR definition to support variable number of lines sim_libraries: - new console library (sim_console.h, sim_console.c) - new file I/O library (sim_fio.h, sim_fio.c) - new timer library (sim_timer.h, sim_timer.c) all terminal multiplexors: revised for tmxr library changes all DECtapes: - added STOP_EOR to enable end-of-reel stop - revised for device debug support all variable-sized devices: revised for sim_fsize change eclipse_cpu.c, nova_cpu.c: fixed device enable/disable support (Bruce Ray) nova_defs.h, nova_sys.c, nova_qty.c: - added QTY and ALM support (Bruce Ray) id32_cpu.c, id_dp.c: revised for device debug support lgp: added LGP-30 [LGP-21] simulator pdp1_sys.c: fixed bug in LOAD (Mark Crispin) pdp10_mdfp.c: - fixed bug in floating unpack - fixed bug in FIXR (Philip Stone, fixed by Chris Smith) pdp11_dz.c: added per-line logging pdp11_rk.c: - added formatting support - added address increment inhibit support - added transfer overrun detection pdp11_hk.c, pdp11_rp.c: revised for device debug support pdp11_rq.c: fixed bug in interrupt control (Tom Evans) pdp11_ry.c: added VAX support pdp11_tm.c, pdp11_tq.c, pdp11_ts.c: revised for device debug support pdp11_xu.c: replaced stub with real implementation (Dave Hittner) pdp18b_cpu.c: - fixed bug in XVM g_mode implementation - fixed bug in PDP-15 indexed address calculation - fixed bug in PDP-15 autoindexed address calculation pdp18b_fpp.c: fixed bugs in instruction decode pdp18b_stddev.c: - fixed clock response to CAF - fixed bug in hardware read-in mode bootstrap pdp18b_sys.c: fixed XVM instruction decoding errors pdp18b_tt1.c: added support for 1-16 additional terminals vax_moddef.h, vax_cpu.c, vax_sysdev.c: - added extended physical memory support (Mark Pizzolato) - added RXV21 support vax_cpu1.c: - added PC read fault in EXTxV - fixed PC write fault in INSV V3.1 revision history 0 29-Dec-03 sim_defs.h, scp.c: added output stall status all console emulators: added output stall support sim_ether.c (Dave Hittner, Mark Pizzolato, Anders Ahgren): - added Alpha/VMS support - added FreeBSD, Mac OS/X support - added TUN/TAP support - added DECnet duplicate address detection all memory buffered devices (fixed head disks, floppy disks): - cleaned up buffer copy code all DECtapes: - fixed reverse checksum in read all - added DECtape off reel message - simplified timing eclipse_cpu.c (Charles Owen): - added floating point support - added programmable interval timer support - bug fixes h316_cpu.c: - added instruction history - added DMA/DMC support - added device ENABLE/DISABLE support - change default to HSA option included h316_dp.c: added moving head disk support h316_fhd.c: added fixed head disk support h316_mt.c: added magtape support h316_sys.c: added new device support nova_dkp.c (Charles Owen): - fixed bug in flag clear sequence - added diagnostic mode support for disk sizing ` nova_mt.c (Charles Owen): - fixed bug, space operations return record count - fixed bug, reset doesn't cancel rewind nova_sys.c: added floating point, timer support (Charles Owen) i1620_cpu.c: fixed bug in branch digit (Dave Babcock) pdp1_drm.c: - added parallel drum support - fixed bug in serial drum instructin decoding pdp1_sys.c: added parallel drum support, mnemonics pdp11_cpu.c: - added autoconfiguration controls - added support for 18b-only Qbus devices - cleaned up addressing/bus definitions pdp11_rk.c, pdp11_ry.c, pdp11_tm.c, pdp11_hk.c: - added Q18 attribute pdp11_io.c: - added autoconfiguration controls - fixed bug in I/O configuration (Dave Hittner) pdp11_rq.c: - revised MB->LBN conversion for greater accuracy - fixed bug with multiple RAUSER drives pdp11_tc.c: changed to be off by default (base config is Qbus) pdp11_xq.c (Dave Hittner, Mark Pizzolato): - fixed second controller interrupts - fixed bugs in multicast and promiscuous setup pdp18b_cpu.c: - added instruction history - fixed PDP-4,-7,-9 autoincrement bug - change PDP-7,-9 default to API option included pdp8_defs.h, pdp8_sys.c: - added DECtape off reel message - added support for TSC8-75 (ETOS) option - added support for TD8E controller pdp8_cpu.c: added instruction history pdp8_rx.c: - fixed bug in RX28 read status (Charles Dickman) - fixed double density write pdp8_td.c: added TD8E controller pdp8_tsc.c: added TSC8-75 option vax_cpu.c: - revised instruction history for dynamic sizing - added autoconfiguration controls vax_io.c: - added autoconfiguration controls - fixed bug in I/O configuration (Dave Hittner) id16_cpu.c: revised instruction decoding id32_cpu.c: - revised instruction decoding - added instruction history V3.0 revision history 2 15-Sep-03 scp.c: - fixed end-of-file problem in dep, idep - fixed error on trailing spaces in dep, idep pdp1_stddev.c - fixed system hang if continue after PTR error - added PTR start/stop functionality - added address switch functionality to PTR BOOT pdp1_sys.c: added multibank capability to LOAD pdp18b_cpu.c: - fixed priorities in PDP-15 API (PI between 3 and 4) - fixed sign handling in PDP-15 unsigned mul/div - fixed bug in CAF, must clear API subsystem i1401_mt.c: - fixed tape read end-of-record handling based on real 1401 - added diagnostic read (space forward) i1620_cpu.c - fixed bug in immediate index add (Michael Short) 1 27-Jul-03 pdp1_cpu.c: updated to detect indefinite I/O wait pdp1_drm.c: fixed incorrect logical, missing activate, break pdp1_lp.c: - fixed bugs in instruction decoding, overprinting - updated to detect indefinite I/O wait pdp1_stddev.c: - changed RIM loader to be "hardware" - updated to detect indefinite I/O wait pdp1_sys.c: added block loader format support to LOAD pdp10_rp.c: fixed bug in read header pdp11_rq: fixed bug in user disk size (Chaskiel M Grundman) pdp18b_cpu.c: - added FP15 support - added XVM support - added EAE support to the PDP-4 - added PDP-15 "re-entrancy ECO" - fixed memory protect/skip interaction - fixed CAF to only reset peripherals pdp18b_fpp.c: added FP15 pdp18b_lp.c: fixed bug in Type 62 overprinting pdp18b_rf.c: fixed bug in set size routine pdp18b_stddev.c: - increased PTP TIME for PDP-15 operating systems - added hardware RIM loader for PDP-7, PDP-9, PDP-15 pdp18b_sys.c: added FP15, KT15, XVM instructions pdp8b_df.c, pdp8_rf.c: fixed bug in set size routine hp2100_dr.c: - fixed drum sizes - fixed variable capacity interaction with SAVE/RESTORE i1401_cpu.c: revised fetch to model hardware more closely ibm1130: fixed bugs found by APL 1130 nova_dsk.c: fixed bug in set size routine altairz80: fixed bug in real-time clock on Windows host 0 15-Jun-03 scp.c: - added ASSIGN/DEASSIGN - changed RESTORE to detach files - added u5, u6 unit fields - added USE_ADDR64 support - changed some structure fields to unsigned scp_tty.c: added extended file seek sim_sock.c: fixed calling sequence in stubs sim_tape.c: - added E11 and TPC format support - added extended file support sim_tmxr.c: fixed bug in SHOW CONNECTIONS all magtapes: - added multiformat support - added extended file support i1401_cpu.c: - fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS - fixed MCE bug, BS off by 1 if zero suppress - fixed chaining bug, D lost if return to SCP - fixed H branch, branch occurs after continue - added check for invalid 8 character MCW, LCA i1401_mt.c: fixed load-mode end of record response nova_dsk.c: fixed variable size interaction with restore pdp1_dt.c: fixed variable size interaction with restore pdp10_rp.c: fixed ordering bug in attach pdp11_cpu.c: - fixed bug in MMR1 update (Tim Stark) - fixed bug in memory size table pdp11_lp.c, pdp11_rq.c: added extended file support pdp11_rl.c, pdp11_rp.c, pdp11_ry.c: fixed ordering bug in attach pdp11_tc.c: fixed variable size interaction with restore pdp11_xq.c: - corrected interrupts on IE state transition (code by Tom Evans) - added interrupt clear on soft reset (first noted by Bob Supnik) - removed interrupt when setting XL or RL (multiple people) - added SET/SHOW XQ STATS - added SHOW XQ FILTERS - added ability to split received packet into multiple buffers - added explicit runt & giant packet processing vax_fpa.c: - fixed integer overflow bug in CVTfi - fixed multiple bugs in EMODf vax_io.c: optimized byte and word DMA routines vax_sysdev.c: - added calibrated delay to ROM reads (Mark Pizzolato) - fixed calibration problems in interval timer (Mark Pizzolato) pdp1_dt.c: fixed variable size interaction with restore pdp18b_dt.c: fixed variable size interaction with restore pdp18b_mt.c: fixed bug in MTTR pdp18b_rf.c: fixed variable size interaction with restore pdp8_df.c, pdp8_rf.c: fixed variable size interaction with restore pdp8_dt.c: fixed variable size interaction with restore pdp8_mt.c: fixed bug in SKTR hp2100_dp.c,hp2100_dq.c: - fixed bug in read status (13210A controller) - fixed bug in seek completion id_pt.c: fixed type declaration (Mark Pizzolato) gri_cpu.c: fixed bug in SC queue pointer management V2.10 revision history 4 03-Mar-03 scp.c - added .ini startup file capability - added multiple breakpoint actions - added multiple switch evaluation points - fixed bug in multiword deposits to file sim_tape.c: magtape simulation library h316_stddev.c: added set line frequency command hp2100_mt.c, hp2100_ms.c: revised to use magtape library i1401_mt.c: revised to use magtape library id_dp.c, id_idc.c: fixed cylinder overflow on writes id_mt.c: - fixed error handling to stop selector channel - revised to use magtape library id16_sys.c, id32_sys.c: added relative addressing support id_uvc.c: - added set frequency command to line frequency clock - improved calibration algorithm for precision clock nova_clk.c: added set line frequency command nova_dsk.c: fixed autosizing algorithm nova_mt.c: revised to use magtape library pdp10_tu.c: revised to use magtape library pdp11_cpu.c: fixed bug in MMR1 update (Tim Stark) pdp11_stddev.c - added set line frequency command - added set ctrl-c command pdp11_rq.c: - fixed ordering problem in queue process - fixed bug in vector calculation for VAXen - added user defined drive support pdp11_ry.c: fixed autosizing algorithm pdp11_tm.c, pdp11_ts.c: revised to use magtape library pdp11_tq.c: - fixed ordering problem in queue process - fixed overly restrictive test for bad modifiers - fixed bug in vector calculation for VAXen - added variable controller, user defined drive support - revised to use magtape library pdp18b_cpu.c: fixed three EAE bugs (Hans Pufal) pdp18b_mt.c: - fixed bugs in BOT error handling, interrupt handling - revised to use magtape library pdp18b_rf.c: - removed 22nd bit from disk address - fixed autosizing algorithm pdp18b_stddev.c: - added set line frequency command - added set ctrl-c command pdp18b_sys.c: fixed FMTASC printouts (Hans Pufal) pdp8_clk.c: added set line frequency command pdp8_df.c, pdp8_rf.c, pdp8_rx.c: fixed autosizing algorithm pdp8_mt.c: - fixed bug in BOT error handling - revised to use magtape library pdp8_tt.c: added set ctrl-c command sds_cpu.c: added set line frequency command sds_mt.c: revised to use magtape library vax_stddev.c: added set ctrl-c command 3 06-Feb-03 scp.c: - added dynamic extension of the breakpoint table - added breakpoint actions hp2100_cpu.c: fixed last cycle bug in DMA output (found by Mike Gemeny) hp2100_ipl.c: individual links are full duplex (found by Mike Gemeny) pdp11_cpu.c: changed R, SP to track PSW<rs,cm> respectively pdp18b_defs.h, pdp18b_sys.c: added RB09 fixed head disk, LP09 printer pdp18b_rf.c: - fixed IOT decoding (Hans Pufal) - fixed address overrun logic - added variable number of platters and autosizing pdp18b_rf.c: - fixed IOT decoding - fixed bug in command initiation pdp18b_rb.c: new RB09 fixed head disk pdp18b_lp.c: new LP09 line printer pdp8_df.c: added variable number of platters and autosizing pdp8_rf.c: added variable number of platters and autosizing nova_dsk.c: added variable number of platters and autosizing id16_cpu.c: fixed bug in SETM, SETMR (Mark Pizzolato) 2 15-Jan-03 scp.c: - added dynamic memory size flag and RESTORE support - added EValuate command - added get_ipaddr routine - added ! (OS command) feature (Mark Pizzolato) - added BREAK support to sim_poll_kbd (Mark Pizzolato) sim_tmxr.c: - fixed bugs in IAC+IAC handling (Mark Pizzolato) - added IAC+BRK handling (Mark Pizzolato) sim_sock.c: - added use count for Windows start/stop - added sim_connect_sock pdp1_defs.h, pdp1_cpu.c, pdp1_sys.c, pdp1_drm.c: added Type 24 serial drum pdp18_defs.h: added PDP-4 drum support hp2100_cpu.c: added 21MX IOP support hp2100_ipl.c: added HP interprocessor link support pdp11_tq.c: fixed bug in transfer end packet length pdp11_xq.c: - added VMScluster support (thanks to Mark Pizzolato) - added major performance enhancements (thanks to Mark Pizzolato) - added local packet processing - added system id broadcast pdp11_stddev.c: changed default to 7b (for early UNIX) vax_cpu.c, vax_io.c, vax_stddev.c, vax_sysdev.c: added console halt capability (Mark Pizzolato) all terminals and multiplexors: added BREAK support 1 21-Nov-02 pdp1_stddev.c: changed typewriter to half duplex (Derek Peschel) pdp10_tu.c: - fixed bug in bootstrap (reported by Michael Thompson) - fixed bug in read (reported by Harris Newman) 0 15-Nov-02 SCP and libraries scp.c: - added Telnet console support - removed VT emulation support - added support for statically buffered devices - added HELP <command> - fixed bugs in set_logon, ssh_break (David Hittner) - added VMS file optimization (Robert Alan Byer) - added quiet mode, DO with parameters, GUI interface, extensible commands (Brian Knittel) - added DEVICE context and flags - added central device enable/disable support - modified SAVE/GET to save and restore flags - modified boot routine calling sequence scp_tty.c: - removed VT emulation support - added sim_os_sleep, renamed sim_poll_kbd, sim_putchar sim_tmxr.c: - modified for Telnet console support - fixed bug in binary (8b) support sim_sock.c: modified for Telnet console support sim_ether.c: new library for Ethernet (David Hittner) all magtapes: - added support for end of medium - cleaned up BOT handling all DECtapes: added support for RT11 image file format most terminals and multiplexors: - added support for 7b vs 8b character processing PDP-1 pdp1_cpu.c, pdp1_sys.c, pdp1_dt.c: added PDP-1 DECtape support PDP-8 pdp8_cpu.c, all peripherals: - added variable device number support - added new device enabled/disable support pdp8_rx.c: added RX28/RX02 support PDP-11 pdp11_defs.h, pdp11_io.c, pdp11_sys.c, all peripherals: - added variable vector support - added new device enable/disable support - added autoconfiguration support all bootstraps: modified to support variable addresses dec_mscp.h, pdp11_tq.c: added TK50 support pdp11_rq.c: - added multicontroller support - fixed bug in HBE error log packet - fixed bug in ATP processing pdp11_ry.c: added RX211/RX02 support pdp11_hk.c: added RK611/RK06/RK07 support pdp11_tq.c: added TMSCP support pdp11_xq.c: added DEQNA/DELQA support (David Hittner) pdp11_pclk.c: added KW11P support pdp11_ts.c: - fixed bug in CTL decoding - fixed bug in extended status XS0_MOT pdp11_stddev.c: removed paper tape to its own module PDP-18b pdp18b_cpu.c, all peripherals: - added variable device number support - added new device enabled/disabled support VAX dec_dz.h: fixed bug in number of boards calculation vax_moddefs.h, vax_io.c, vax_sys.c, all peripherals: - added variable vector support - added new device enable/disable support - added autoconfiguration support vax_sys.c: - generalized examine/deposit - added TMSCP, multiple RQDX3, DEQNA/DELQA support vax_stddev.c: removed paper tape, now uses PDP-11 version vax_sysdev.c: - allowed NVR to be attached to file - removed unused variables (David Hittner) PDP-10 pdp10_defs.h, pdp10_ksio.c, all peripherals: - added variable vector support - added new device enable/disable support pdp10_defs.h, pdp10_ksio.c: added support for standard PDP-11 peripherals, added RX211 support pdp10_pt.c: rewritten to reference common implementation Nova, Eclipse: nova_cpu.c, eclipse_cpu.c, all peripherals: - added new device enable/disable support HP2100 hp2100_cpu: - fixed bugs in the EAU, 21MX, DMS, and IOP instructions - fixed bugs in the memory protect and DMS functions - created new options to enable/disable EAU, MPR, DMS - added new device enable/disable support hp2100_fp.c: - recoded to conform to 21MX microcode algorithms hp2100_stddev.c: - fixed bugs in TTY reset, OTA, time base generator - revised BOOT support to conform to RBL loader - added clock calibration hp2100_dp.c: - changed default to 13210A - added BOOT support hp2100_dq.c: - finished incomplete functions, fixed head switching - added BOOT support hp2100_ms.c: - fixed bugs found by diagnostics - added 13183 support - added BOOT support hp2100_mt.c: - fixed bugs found by diagnostics - disabled by default hp2100_lpt.c: implemented 12845A controller hp2100_lps.c: - renamed 12653A controller - added diagnostic mode for MPR, DCPC diagnostics - disabled by default IBM 1620: first release V2.9 revision history 11 20-Jul-02 i1401_mt.c: on read, end of record stores group mark without word mark (Van Snyder) i1401_dp.c: reworked address generation and checking vax_cpu.c: added infinite loop detection and halt to boot ROM option (Mark Pizzolato) vax_fpa.c: changed function names to prevent conflict with C math library pdp11_cpu.c: fixed bug in MMR0 update logic (from John Dundas) pdp18b_stddev.c: added "ASCII mode" for reader and punch (Hans Pufal) gri_*.c: added GRI-909 simulator scp.c: added DO echo, DO exit (Brian Knittel) scp_tty.c: added Windows priority hacking (from Mark Pizzolato) 10 15-Jun-02 scp.c: fixed error checking on calls to fxread/fxwrite (Norm Lastovic) scp_tty.c, sim_vt.h, sim_vt.c: added VTxxx emulation support for Windows (Fischer Franz) sim_sock.c: added OS/2 support (Holger Veit) pdp11_cpu.c: fixed bugs (John Dundas) - added special case for PS<15:12> = 1111 to MFPI - removed special case from MTPI - added masking of relocation adds i1401_cpu.c: - added multiply/divide - fixed bugs (Van Snyder) o 5 and 7 character H, 7 character doesn't branch o 8 character NOP o 1401-like memory dump i1401_dp.c: added 1311 disk 9 04-May-02 pdp11_rq: fixed bug in polling routine 8 03-May-02 scp.c: - changed LOG/NOLOG to SET LOG/NOLOG - added SHOW LOG - added SET VT/NOVT and SHOW VT for VT emulation sim_sock.h: changed VMS stropt.h include to ioctl.h vax_cpu.c - added TODR powerup routine to set date, time on boot - fixed exception flows to clear trap request - fixed register logging in autoincrement indexed vax_stddev.c: added TODR powerup routine vax_cpu1.c: fixed exception flows to clear trap request 7 30-Apr-02 scp.c: fixed bug in clock calibration when (real) clock jumps forward due too far (Jonathan Engdahl) pdp11_cpu.c: fixed bugs, added features (John Dundas and Wolfgang Helbig) - added HTRAP and BPOK to maintenance register - added trap on kernel HALT if MAINT<HTRAP> set - fixed red zone trap, clear odd address and nxm traps - fixed RTS SP, don't increment restored SP - fixed TSTSET, write dst | 1 rather than prev R0 | 1 - fixed DIV, set N=0,Z=1 on div by zero (J11, 11/70) - fixed DIV, set set N=Z=0 on overfow (J11, 11/70) - fixed ASH, ASHC, count = -32 used implementation- dependent 32 bit right shift - fixed illegal instruction test to detect 000010 - fixed write-only page test pdp11_rp.c: fixed SHOW ADDRESS command vaxmod_defs.h: fixed DZ vector base and number of lines dec_dz.h: - fixed interrupt acknowledge routines - fixed SHOW ADDRESS command all magtape routines: added test for badly formed record length (suggested by Jonathan Engdahl) 6 18-Apr-02 vax_cpu.c: fixed CASEL condition codes vax_cpu1.c: fixed vfield pos > 31 test to be unsigned vax_fpu.c: fixed EDIV overflow test for 0 quotient 5 14-Apr-02 vax_cpu1.c: - fixed interrupt, prv_mode set to 0 (Tim Stark) - fixed PROBEx to mask mode to 2b (Kevin Handy) 4 1-Apr-02 pdp11_rq.c: fixed bug, reset cleared write protect status pdp11_ts.c: fixed bug in residual frame count after space 3 15-Mar-02 pdp11_defs.h: changed default model to KDJ11A (11/73) pdp11_rq.c: adjusted delays for M+ timing bugs hp2100_cpu.c, pdp10_cpu.c, pdp11_cpu.c: tweaked abort code for ANSI setjmp/longjmp compliance hp2100_cpu.c, hp2100_fp.c, hp2100_stddev.c, hp2100_sys.c: revised to allocate memory dynamically 2 01-Mar-02 pdp11_cpu.c: - fixed bugs in CPU registers - fixed double operand evaluation order for M+ pdp11_rq.c: added delays to initialization for RSX11M+ prior to V4.5 1 20-Feb-02 scp.c: fixed bug in clock calibration when (real) time runs backwards pdp11_rq.c: fixed bug in host timeout logic pdp11_ts.c: fixed bug in message header logic pdp18b_defs.h, pdp18b_dt.c, pdp18b_sys.c: added PDP-7 DECtape support hp2100_cpu.c: - added floating point and DMS - fixed bugs in DIV, ASL, ASR, LBT, SBT, CBT, CMW hp2100_sys.c: added floating point, DMS hp2100_fp.c: added floating point ibm1130: added Brian Knittel's IBM 1130 simulator 0 30-Jan-02 scp.c: - generalized timer package for multiple timers - added circular register arrays - fixed bugs, line spacing in modifier display - added -e switch to attach - moved device enable/disable to simulators scp_tty.c: VAX specific fix (Robert Alan Byer) sim_tmxr.c, sim_tmxr.h: - added tmxr_fstats, tmxr_dscln - renamed tmxr_fstatus to tmxr_fconns sim_sock.c, sim_sock.h: added VMS support (from Robert Alan Byer) pdp_dz.h, pdp18b_tt1.c, nova_tt1.c: - added SET DISCONNECT - added SHOW STATISTICS pdp8_defs.h: fixed bug in interrupt enable initialization pdp8_ttx.c: rewrote as unified multiplexor pdp11_cpu.c: fixed calc_MMR1 macro (Robert Alan Byer) pdp11_stddev.c: fixed bugs in KW11L (John Dundas) pdp11_rp.c: fixed bug in 18b mode boot pdp11 bootable I/O devices: fixed register setup at boot exit (Doug Carman) hp2100_cpu.c: - fixed DMA register tables (Bill McDermith) - fixed SZx,SLx,RSS bug (Bill McDermith) - fixed flop restore logic (Bill McDermith) hp2100_mt.c: fixed bug on write of last character hp2100_dq,dr,ms,mux.c: added new disk, magtape, and terminal multiplexor controllers i1401_cd.c, i1401_mt.c: new zero footprint bootstraps (Van Snyder) i1401_sys.c: fixed symbolic display of H, NOP with no trailing word mark (Van Snyder) most CPUs: - replaced OLDPC with PC queue - implemented device enable/disable locally V2.8 revision history 5 25-Dec-01 scp.c: fixed bug in DO command (John Dundas) pdp10_cpu.c: - moved trap-in-progress to separate variable - cleaned up declarations - cleaned up volatile state for GNU C longjmp pdp11_cpu.c: cleaned up declarations pdp11_rq.c: added RA-class disks 4 17-Dec-01 pdp11_rq.c: added delayed processing of packets 3 16-Dec-01 pdp8_cpu.c: - mode A EAE instructions didn't clear GTF - ASR shift count > 24 mis-set GTF - effective shift count == 32 didn't work 2 07-Dec-01 scp.c: added breakpoint package all CPU's: revised to use new breakpoint package 1 05-Dec-01 scp.c: fixed bug in universal register name logic 0 30-Nov-01 Reorganized simh source and documentation tree scp: Added DO command, universal registers, extended SET/SHOW logic pdp11: overhauled PDP-11 for DMA map support, shared sources with VAX, dynamic buffer allocation 18b pdp: overhauled interrupt structure pdp8: added RL8A pdp10: fixed two ITS-related bugs (Dave Conroy) V2.7 revision history patch date module(s) and fix(es) 15 23-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: fixed bugs error interrupt handling pdp10_defs.h, pdp10_ksio.c, pdp10_fe.c, pdp10_fe.c, pdp10_rp.c, pdp10_tu.c: reworked I/O page interface to use symbolic base addresses and lengths 14 20-Oct-01 dec_dz.h, sim_tmxr_h, sim_tmxr.c: fixed bug in Telnet state handling (Thord Nilson), removed tmxr_getchar, added tmxr_rqln and tmxr_tqln 13 18-Oct-01 pdp11_tm.c: added stub diagnostic register clock for RSTS/E (Thord Nilson) 12 15-Oct-01 pdp11_defs.h, pdp11_cpu.c, pdp11_tc.c, pdp11_ts.c, pdp11_rp.c: added operations logging 11 8-Oct-01 scp.c: added sim_rev.h include and version print pdp11_cpu.c: fixed bug in interrupt acknowledge, multiple outstanding interrupts caused the lowest rather than the highest to be acknowledged 10 7-Oct-01 pdp11_stddev.c: added monitor bits (CSR<7>) for full KW11L compatibility, needed for RSTS/E autoconfiguration 9 6-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: rewrote interrupt logic from RH11/RH70 schematics, to mimic hardware quirks dec_dz.c: fixed bug in carrier detect logic, carrier detect was being cleared on next modem poll 8 4-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: undid edit of 28-Sep-01; real problem was level-sensitive nature of CS1_SC, but CS1_SC can only trigger an interrupt if DONE is set 7 2-Oct-01 pdp11_rp.c, pdp10_rp.c: CS1_SC is evaluated as a level- sensitive, rather than an edge-sensitive, input to interrupt request 6 30-Sep-01 pdp11_rp.c, pdp10_rp.c: separated out CS1<5:0> to per- drive registers pdp10_tu.c: based on above, cleaned up handling of non-existent formatters, fixed non-data transfer commands clearing DONE 5 28-Sep-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: controller should interrupt if ATA or SC sets when IE is set, was interrupting only if DON = 1 as well 4 27-Sep-01 pdp11_ts.c: - NXM errors should return TC4 or TC5; were returning TC3 - extended features is part of XS2; was returned in XS3 - extended characteristics (fifth) word needed for RSTS/E pdp11_tc.c: stop, stop all do cause an interrupt dec_dz.h: scanner should find a ready output line, even if there are no connections; needed for RSTS/E autoconfigure scp.c: - added routine sim_qcount for 1130 - added "simulator exit" detach routine for 1130 sim_defs.h: added header for sim_qcount 3 20-Sep-01 pdp11_ts.c: boot code binary was incorrect 2 19-Sep-01 pdp18b_cpu.c: EAE should interpret initial count of 00 as 100 scp.c: modified Macintosh support 1 17-Sep-01 pdp8_ttx.c: new module for PDP-8 multi-terminal support pdp18b_tt1.c: modified to use sim_tmxr library nova_tt1.c: modified to use sim_tmxr library dec_dz.h: added autodisconnect support scp.c: removed old multiconsole support sim_tmxr.c: modified calling sequence for sim_putchar_ln sim_sock.c: added Macintosh sockets support */ #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 | /* sim_serial.c: OS-dependent serial port routines Copyright (c) 2008, J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the author shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. The author gratefully acknowledges the assistance of Holger Veit with the UNIX-specific code and testing. 07-Oct-08 JDB [serial] Created file This module provides OS-dependent routines to access serial ports on the host machine. The terminal multiplexer library uses these routines to provide serial connections to simulated terminal interfaces. Currently, the module supports Windows and UNIX. Use on other systems returns error codes indicating that the functions failed, inhibiting serial port support in SIMH. The following routines are provided: sim_open_serial open a serial port sim_config_serial change baud rate and character framing configuration sim_control_serial manipulate and/or return the modem bits on a serial port sim_read_serial read from a serial port sim_write_serial write to a serial port sim_close_serial close a serial port sim_show_serial shows the available host serial ports The calling sequences are as follows: SERHANDLE sim_open_serial (char *name) -------------------------------------- The serial port referenced by the OS-dependent "name" is opened. If the open is successful, and "name" refers to a serial port on the host system, then a handle to the port is returned. If not, then the value INVALID_HANDLE is returned. t_stat sim_config_serial (SERHANDLE port, const char *config) ------------------------------------------------------------- The baud rate and framing parameters (character size, parity, and number of stop bits) of the serial port associated with "port" are set. If any "config" field value is unsupported by the host system, or if the combination of values (e.g., baud rate and number of stop bits) is unsupported, SCPE_ARG is returned. If the configuration is successful, SCPE_OK is returned. sim_control_serial (SERHANDLE port, int32 bits_to_set, int32 bits_to_clear, int32 *incoming_bits) ------------------------------------------------------------------------------------------------- The DTR and RTS line of the serial port is set or cleared as indicated in the respective bits_to_set or bits_to_clear parameters. If the incoming_bits parameter is not NULL, then the modem status bits DCD, RNG, DSR and CTS are returned. If unreasonable or nonsense bits_to_set or bits_to_clear bits are specified, then the return status is SCPE_ARG; If an error occurs, SCPE_IOERR is returned. int32 sim_read_serial (SERHANDLE port, char *buffer, int32 count, char *brk) ---------------------------------------------------------------------------- A non-blocking read is issued for the serial port indicated by "port" to get at most "count" bytes into the string "buffer". If a serial line break was detected during the read, the variable pointed to by "brk" is set to 1. If the read is successful, the actual number of characters read is returned. If no characters were available, then the value 0 is returned. If an error occurs, then the value -1 is returned. int32 sim_write_serial (SERHANDLE port, char *buffer, int32 count) ------------------------------------------------------------------ A write is issued to the serial port indicated by "port" to put "count" characters from "buffer". If the write is successful, the actual number of characters written is returned. If an error occurs, then the value -1 is returned. void sim_close_serial (SERHANDLE port) -------------------------------------- The serial port indicated by "port" is closed. int sim_serial_devices (int max, SERIAL_LIST* list) --------------------------------------------------- enumerates the available host serial ports t_stat sim_show_serial (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, const void* desc) --------------------------------- displays the available host serial ports */ #include "sim_defs.h" #include "sim_serial.h" #include "sim_tmxr.h" #include <ctype.h> #define SER_DEV_NAME_MAX 256 /* maximum device name size */ #define SER_DEV_DESC_MAX 256 /* maximum device description size */ #define SER_DEV_CONFIG_MAX 64 /* maximum device config size */ #define SER_MAX_DEVICE 64 /* maximum serial devices */ typedef struct serial_list { char name[SER_DEV_NAME_MAX]; char desc[SER_DEV_DESC_MAX]; } SERIAL_LIST; typedef struct serial_config { /* serial port configuration */ uint32 baudrate; /* baud rate */ uint32 charsize; /* character size in bits */ char parity; /* parity (N/O/E/M/S) */ uint32 stopbits; /* 0/1/2 stop bits (0 implies 1.5) */ } SERCONFIG; static int sim_serial_os_devices (int max, SERIAL_LIST* list); static SERHANDLE sim_open_os_serial (char *name); static void sim_close_os_serial (SERHANDLE port); static t_stat sim_config_os_serial (SERHANDLE port, SERCONFIG config); static struct open_serial_device { SERHANDLE port; TMLN *line; char name[SER_DEV_NAME_MAX]; char config[SER_DEV_CONFIG_MAX]; } *serial_open_devices = NULL; static int serial_open_device_count = 0; static struct open_serial_device *_get_open_device (SERHANDLE port) { int i; for (i=0; i<serial_open_device_count; ++i) if (serial_open_devices[i].port == port) return &serial_open_devices[i]; return NULL; } static struct open_serial_device *_get_open_device_byname (const char *name) { int i; for (i=0; i<serial_open_device_count; ++i) if (0 == strcmp(name, serial_open_devices[i].name)) return &serial_open_devices[i]; return NULL; } static struct open_serial_device *_serial_add_to_open_list (SERHANDLE port, TMLN *line, const char *name, const char *config) { serial_open_devices = (struct open_serial_device *)realloc(serial_open_devices, (++serial_open_device_count)*sizeof(*serial_open_devices)); memset(&serial_open_devices[serial_open_device_count-1], 0, sizeof(serial_open_devices[serial_open_device_count-1])); serial_open_devices[serial_open_device_count-1].port = port; serial_open_devices[serial_open_device_count-1].line = line; strncpy(serial_open_devices[serial_open_device_count-1].name, name, sizeof(serial_open_devices[serial_open_device_count-1].name)-1); if (config) strncpy(serial_open_devices[serial_open_device_count-1].config, config, sizeof(serial_open_devices[serial_open_device_count-1].config)-1); return &serial_open_devices[serial_open_device_count-1]; } static void _serial_remove_from_open_list (SERHANDLE port) { int i, j; for (i=0; i<serial_open_device_count; ++i) if (serial_open_devices[i].port == port) { for (j=i+1; j<serial_open_device_count; ++j) serial_open_devices[j-1] = serial_open_devices[j]; --serial_open_device_count; break; } } /* Generic error message handler. This routine should be called for unexpected errors. Some error returns may be expected, e.g., a "file not found" error from an "open" routine. These should return appropriate status codes to the caller, allowing SCP to print an error message if desired, rather than printing this generic error message. */ static void sim_error_serial (const char *routine, int error) { sim_printf ("Serial: %s fails with error %d\n", routine, error); return; } /* Used when sorting a list of serial port names */ static int _serial_name_compare (const void *pa, const void *pb) { const SERIAL_LIST *a = (const SERIAL_LIST *)pa; const SERIAL_LIST *b = (const SERIAL_LIST *)pb; return strcmp(a->name, b->name); } static int sim_serial_devices (int max, SERIAL_LIST *list) { int i, j, ports = sim_serial_os_devices(max, list); /* Open ports may not show up in the list returned by sim_serial_os_devices so we add the open ports to the list removing duplicates before sorting the resulting list */ for (i=0; i<serial_open_device_count; ++i) { for (j=0; j<ports; ++j) if (0 == strcmp(serial_open_devices[i].name, list[j].name)) break; if (j<ports) continue; if (ports >= max) break; strcpy(list[ports].name, serial_open_devices[i].name); strcpy(list[ports].desc, serial_open_devices[i].config); ++ports; } if (ports) /* Order the list returned alphabetically by the port name */ qsort (list, ports, sizeof(list[0]), _serial_name_compare); return ports; } static char* sim_serial_getname (int number, char* name) { SERIAL_LIST list[SER_MAX_DEVICE]; int count = sim_serial_devices(SER_MAX_DEVICE, list); if (count <= number) return NULL; strcpy(name, list[number].name); return name; } static char* sim_serial_getname_bydesc (char* desc, char* name) { SERIAL_LIST list[SER_MAX_DEVICE]; int count = sim_serial_devices(SER_MAX_DEVICE, list); int i; size_t j=strlen(desc); for (i=0; i<count; i++) { int found = 1; size_t k = strlen(list[i].desc); if (j != k) continue; for (k=0; k<j; k++) if (tolower(list[i].desc[k]) != tolower(desc[k])) found = 0; if (found == 0) continue; /* found a case-insensitive description match */ strcpy(name, list[i].name); return name; } /* not found */ return NULL; } static char* sim_serial_getname_byname (char* name, char* temp) { SERIAL_LIST list[SER_MAX_DEVICE]; int count = sim_serial_devices(SER_MAX_DEVICE, list); size_t n; int i, found; found = 0; n = strlen(name); for (i=0; i<count && !found; i++) { if ((n == strlen(list[i].name)) && (sim_strncasecmp(name, list[i].name, n) == 0)) { found = 1; strcpy(temp, list[i].name); /* only case might be different */ } } return (found ? temp : NULL); } char* sim_serial_getdesc_byname (char* name, char* temp) { SERIAL_LIST list[SER_MAX_DEVICE]; int count = sim_serial_devices(SER_MAX_DEVICE, list); size_t n; int i, found; found = 0; n = strlen(name); for (i=0; i<count && !found; i++) { if ((n == strlen(list[i].name)) && (sim_strncasecmp(name, list[i].name, n) == 0)) { found = 1; strcpy(temp, list[i].desc); } } return (found ? temp : NULL); } t_stat sim_show_serial (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc) { SERIAL_LIST list[SER_MAX_DEVICE]; int number = sim_serial_devices(SER_MAX_DEVICE, list); fprintf(st, "Serial devices:\n"); if (number == -1) fprintf(st, " serial support not available in simulator\n"); else if (number == 0) fprintf(st, " no serial devices are available\n"); else { size_t min, len; int i; for (i=0, min=0; i<number; i++) if ((len = strlen(list[i].name)) > min) min = len; for (i=0; i<number; i++) fprintf(st," ser%d\t%-*s%s%s%s\n", i, (int)min, list[i].name, list[i].desc[0] ? " (" : "", list[i].desc, list[i].desc[0] ? ")" : ""); } if (serial_open_device_count) { int i; char desc[SER_DEV_DESC_MAX], *d; fprintf(st,"Open Serial Devices:\n"); for (i=0; i<serial_open_device_count; i++) { d = sim_serial_getdesc_byname(serial_open_devices[i].name, desc); fprintf(st, " %s\tLn%02d %s%s%s%s\tConfig: %s\n", serial_open_devices[i].line->mp->dptr->name, (int)(serial_open_devices[i].line->mp->ldsc-serial_open_devices[i].line), serial_open_devices[i].line->destination, d ? " {" : "", d ? d : "", d ? ")" : "", serial_open_devices[i].line->serconfig); } } return SCPE_OK; } SERHANDLE sim_open_serial (char *name, TMLN *lp, t_stat *stat) { char temp1[1024], devname [1024]; char *savname = name; SERHANDLE port = INVALID_HANDLE; CONST char *config; t_stat status; config = get_glyph_nc (name, devname, ';'); /* separate port name from optional config params */ if ((config == NULL) || (*config == '\0')) config = "9600-8N1"; if (stat) *stat = SCPE_OK; /* translate name of type "serX" to real device name */ if ((strlen(devname) <= 5) && (tolower(devname[0]) == 's') && (tolower(devname[1]) == 'e') && (tolower(devname[2]) == 'r') && (isdigit(devname[3])) && (isdigit(devname[4]) || (devname[4] == '\0')) ) { int num = atoi(&devname[3]); savname = sim_serial_getname(num, temp1); if (savname == NULL) { /* didn't translate */ if (stat) *stat = SCPE_OPENERR; return INVALID_HANDLE; } } else { /* are they trying to use device description? */ savname = sim_serial_getname_bydesc(devname, temp1); if (savname == NULL) { /* didn't translate */ /* probably is not serX and has no description */ savname = sim_serial_getname_byname(devname, temp1); if (savname == NULL) /* didn't translate */ savname = devname; } } if (_get_open_device_byname (savname)) { if (stat) *stat = SCPE_OPENERR; return INVALID_HANDLE; } port = sim_open_os_serial (savname); if (port == INVALID_HANDLE) { if (stat) *stat = SCPE_OPENERR; return port; } status = sim_config_serial (port, config); /* set serial configuration */ if (status != SCPE_OK) { /* port configuration error? */ sim_close_serial (port); /* close the port */ if (stat) *stat = status; port = INVALID_HANDLE; /* report error */ } if ((port != INVALID_HANDLE) && (*config) && (lp)) { lp->serconfig = (char *)realloc (lp->serconfig, 1 + strlen (config)); strcpy (lp->serconfig, config); } if (port != INVALID_HANDLE) _serial_add_to_open_list (port, lp, savname, config); return port; } void sim_close_serial (SERHANDLE port) { sim_close_os_serial (port); _serial_remove_from_open_list (port); } t_stat sim_config_serial (SERHANDLE port, CONST char *sconfig) { CONST char *pptr; CONST char *sptr, *tptr; SERCONFIG config = { 0 }; t_bool arg_error = FALSE; t_stat r; struct open_serial_device *dev; if ((sconfig == NULL) || (*sconfig == '\0')) sconfig = "9600-8N1"; /* default settings */ pptr = sconfig; config.baudrate = (uint32)strtotv (pptr, &sptr, 10); /* parse baud rate */ arg_error = (pptr == sptr); /* check for bad argument */ if (*sptr) /* separator present? */ sptr++; /* skip it */ config.charsize = (uint32)strtotv (sptr, &tptr, 10); /* parse character size */ arg_error = arg_error || (sptr == tptr); /* check for bad argument */ if (*tptr) /* parity character present? */ config.parity = (char)toupper (*tptr++); /* save parity character */ config.stopbits = (uint32)strtotv (tptr, &sptr, 10); /* parse number of stop bits */ arg_error = arg_error || (tptr == sptr); /* check for bad argument */ if (arg_error) /* bad conversions? */ return SCPE_ARG; /* report argument error */ if (strcmp (sptr, ".5") == 0) /* 1.5 stop bits requested? */ config.stopbits = 0; /* code request */ r = sim_config_os_serial (port, config); dev = _get_open_device (port); if (dev) { dev->line->serconfig = (char *)realloc (dev->line->serconfig, 1 + strlen (sconfig)); strcpy (dev->line->serconfig, sconfig); } return r; } #if defined (_WIN32) /* Windows serial implementation */ /* Enumerate the available serial ports. The serial port names are extracted from the appropriate place in the windows registry (HKLM\HARDWARE\DEVICEMAP\SERIALCOMM\). The resulting list is sorted alphabetically by device name (COMn). The device description is set to the OS internal name for the COM device. */ struct SERPORT { HANDLE hPort; DWORD dwEvtMask; OVERLAPPED oReadSync; OVERLAPPED oWriteReady; OVERLAPPED oWriteSync; }; static int sim_serial_os_devices (int max, SERIAL_LIST* list) { int ports = 0; HKEY hSERIALCOMM; memset(list, 0, max*sizeof(*list)); if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hSERIALCOMM) == ERROR_SUCCESS) { DWORD dwIndex = 0; DWORD dwType; DWORD dwValueNameSize = sizeof(list[ports].desc); DWORD dwDataSize = sizeof(list[ports].name); /* Enumerate all the values underneath HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM */ while (RegEnumValueA(hSERIALCOMM, dwIndex, list[ports].desc, &dwValueNameSize, NULL, &dwType, (BYTE *)list[ports].name, &dwDataSize) == ERROR_SUCCESS) { /* String values with non-zero size are the interesting ones */ if ((dwType == REG_SZ) && (dwDataSize > 0)) { if (ports < max) ++ports; else break; } /* Besure to clear the working entry before trying again */ memset(list[ports].name, 0, sizeof(list[ports].name)); memset(list[ports].desc, 0, sizeof(list[ports].desc)); dwValueNameSize = sizeof(list[ports].desc); dwDataSize = sizeof(list[ports].name); ++dwIndex; } RegCloseKey(hSERIALCOMM); } return ports; } /* Open a serial port. The serial port designated by "name" is opened, and the handle to the port is returned. If an error occurs, INVALID_HANDLE is returned instead. After opening, the port is configured with the default communication parameters established by the system, and the timeouts are set for immediate return on a read request to enable polling. Implementation notes: 1. We call "GetDefaultCommConfig" to obtain the default communication parameters for the specified port. If the name does not refer to a communications port (serial or parallel), the function fails. 2. There is no way to limit "CreateFile" just to serial ports, so we must check after the port is opened. The "GetCommState" routine will return an error if the handle does not refer to a serial port. 3. Calling "GetDefaultCommConfig" for a serial port returns a structure containing a DCB. This contains the default parameters. However, some of the DCB fields are not set correctly, so we cannot use this directly in a call to "SetCommState". Instead, we must copy the fields of interest to a DCB retrieved from a call to "GetCommState". */ static SERHANDLE sim_open_os_serial (char *name) { HANDLE hPort; SERHANDLE port; DCB dcb; COMMCONFIG commdefault; DWORD error; DWORD commsize = sizeof (commdefault); COMMTIMEOUTS cto; if (!GetDefaultCommConfig (name, &commdefault, &commsize)) { /* get default comm parameters */ error = GetLastError (); /* function failed; get error */ if (error != ERROR_INVALID_PARAMETER) /* not a communications port name? */ sim_error_serial ("GetDefaultCommConfig", (int) error); /* no, so report unexpected error */ return INVALID_HANDLE; /* indicate bad port name */ } hPort = CreateFile (name, GENERIC_READ | GENERIC_WRITE, /* open the port */ 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (hPort == INVALID_HANDLE_VALUE) { /* open failed? */ error = GetLastError (); /* get error code */ if ((error != ERROR_FILE_NOT_FOUND) && /* bad filename? */ (error != ERROR_ACCESS_DENIED)) /* already open? */ sim_error_serial ("CreateFile", (int) error); /* no, so report unexpected error */ return INVALID_HANDLE; /* indicate bad port name */ } port = (SERHANDLE)calloc (1, sizeof(*port)); /* instantiate the SERHANDLE */ port->hPort = hPort; if (!GetCommState (port->hPort, &dcb)) { /* get the current comm parameters */ error = GetLastError (); /* function failed; get error */ if (error != ERROR_INVALID_PARAMETER) /* not a serial port name? */ sim_error_serial ("GetCommState", (int) error); /* no, so report unexpected error */ sim_close_os_serial (port); /* close port */ return INVALID_HANDLE; /* and indicate bad port name */ } dcb.BaudRate = commdefault.dcb.BaudRate; /* copy default parameters of interest */ dcb.Parity = commdefault.dcb.Parity; dcb.ByteSize = commdefault.dcb.ByteSize; dcb.StopBits = commdefault.dcb.StopBits; dcb.fOutX = commdefault.dcb.fOutX; dcb.fInX = commdefault.dcb.fInX; dcb.fDtrControl = DTR_CONTROL_DISABLE; /* disable DTR initially until poll connects */ if (!SetCommState (port->hPort, &dcb)) { /* configure the port with default parameters */ sim_error_serial ("SetCommState", /* function failed; report unexpected error */ (int) GetLastError ()); sim_close_os_serial (port); /* close port */ return INVALID_HANDLE; /* and indicate failure to caller */ } cto.ReadIntervalTimeout = MAXDWORD; /* set port to return immediately on read */ cto.ReadTotalTimeoutMultiplier = 0; /* i.e., to enable polling */ cto.ReadTotalTimeoutConstant = 0; cto.WriteTotalTimeoutMultiplier = 0; cto.WriteTotalTimeoutConstant = 0; if (!SetCommTimeouts (port->hPort, &cto)) { /* configure port timeouts */ sim_error_serial ("SetCommTimeouts", /* function failed; report unexpected error */ (int) GetLastError ()); sim_close_os_serial (port); /* close port */ return INVALID_HANDLE; /* and indicate failure to caller */ } /* Create an event object for use by WaitCommEvent. */ port->oWriteReady.hEvent = CreateEvent(NULL, /* default security attributes */ TRUE, /* manual-reset event */ TRUE, /* signaled */ NULL); /* no name */ if (port->oWriteReady.hEvent == NULL) { sim_error_serial ("CreateEvent", /* function failed; report unexpected error */ (int) GetLastError ()); sim_close_os_serial (port); /* close port */ return INVALID_HANDLE; /* and indicate failure to caller */ } port->oReadSync.hEvent = CreateEvent(NULL, /* default security attributes */ TRUE, /* manual-reset event */ FALSE, /* not signaled */ NULL); /* no name */ if (port->oReadSync.hEvent == NULL) { sim_error_serial ("CreateEvent", /* function failed; report unexpected error */ (int) GetLastError ()); sim_close_os_serial (port); /* close port */ return INVALID_HANDLE; /* and indicate failure to caller */ } port->oWriteSync.hEvent = CreateEvent(NULL, /* default security attributes */ TRUE, /* manual-reset event */ FALSE, /* not signaled */ NULL); /* no name */ if (port->oWriteSync.hEvent == NULL) { sim_error_serial ("CreateEvent", /* function failed; report unexpected error */ (int) GetLastError ()); sim_close_os_serial (port); /* close port */ return INVALID_HANDLE; /* and indicate failure to caller */ } if (!SetCommMask (port->hPort, EV_TXEMPTY)) { sim_error_serial ("SetCommMask", /* function failed; report unexpected error */ (int) GetLastError ()); sim_close_os_serial (port); /* close port */ return INVALID_HANDLE; /* and indicate failure to caller */ } return port; /* return port handle on success */ } /* Configure a serial port. Port parameters are configured as specified in the "config" structure. If "config" contains an invalid configuration value, or if the host system rejects the configuration (e.g., by requesting an unsupported combination of character size and stop bits), SCPE_ARG is returned to the caller. If an unexpected error occurs, SCPE_IOERR is returned. If the configuration succeeds, SCPE_OK is returned. Implementation notes: 1. We do not enable input parity checking, as the multiplexer library has no way of communicating parity errors back to the target simulator. 2. A zero value for the "stopbits" field of the "config" structure implies 1.5 stop bits. */ static t_stat sim_config_os_serial (SERHANDLE port, SERCONFIG config) { static const struct { char parity; BYTE parity_code; } parity_map [] = { { 'E', EVENPARITY }, { 'M', MARKPARITY }, { 'N', NOPARITY }, { 'O', ODDPARITY }, { 'S', SPACEPARITY } }; static const int32 parity_count = sizeof (parity_map) / sizeof (parity_map [0]); DCB dcb; DWORD error; int32 i; if (!GetCommState (port->hPort, &dcb)) { /* get the current comm parameters */ sim_error_serial ("GetCommState", /* function failed; report unexpected error */ (int) GetLastError ()); return SCPE_IOERR; /* return failure status */ } dcb.BaudRate = config.baudrate; /* assign baud rate */ if (config.charsize >= 5 && config.charsize <= 8) /* character size OK? */ dcb.ByteSize = (BYTE)config.charsize; /* assign character size */ else return SCPE_ARG; /* not a valid size */ for (i = 0; i < parity_count; i++) /* assign parity */ if (config.parity == parity_map [i].parity) { /* match mapping value? */ dcb.Parity = parity_map [i].parity_code; /* assign corresponding code */ break; } if (i == parity_count) /* parity assigned? */ return SCPE_ARG; /* not a valid parity specifier */ if (config.stopbits == 1) /* assign stop bits */ dcb.StopBits = ONESTOPBIT; else if (config.stopbits == 2) dcb.StopBits = TWOSTOPBITS; else if (config.stopbits == 0) /* 0 implies 1.5 stop bits */ dcb.StopBits = ONE5STOPBITS; else return SCPE_ARG; /* not a valid number of stop bits */ if (!SetCommState (port->hPort, &dcb)) { /* set the configuration */ error = GetLastError (); /* check for error */ if (error == ERROR_INVALID_PARAMETER) /* invalid configuration? */ return SCPE_ARG; /* report as argument error */ sim_error_serial ("SetCommState", (int) error); /* function failed; report unexpected error */ return SCPE_IOERR; /* return failure status */ } return SCPE_OK; /* return success status */ } /* Control a serial port. The DTR and RTS line of the serial port is set or cleared as indicated in the respective bits_to_set or bits_to_clear parameters. If the incoming_bits parameter is not NULL, then the modem status bits DCD, RNG, DSR and CTS are returned. If unreasonable or nonsense bits_to_set or bits_to_clear bits are specified, then the return status is SCPE_ARG; If an error occurs, SCPE_IOERR is returned. */ t_stat sim_control_serial (SERHANDLE port, int32 bits_to_set, int32 bits_to_clear, int32 *incoming_bits) { if ((bits_to_set & ~(TMXR_MDM_OUTGOING)) || /* Assure only settable bits */ (bits_to_clear & ~(TMXR_MDM_OUTGOING)) || (bits_to_set & bits_to_clear)) /* and can't set and clear the same bits */ return SCPE_ARG; if (bits_to_set&TMXR_MDM_DTR) if (!EscapeCommFunction (port->hPort, SETDTR)) { sim_error_serial ("EscapeCommFunction", (int) GetLastError ()); return SCPE_IOERR; } if (bits_to_clear&TMXR_MDM_DTR) if (!EscapeCommFunction (port->hPort, CLRDTR)) { sim_error_serial ("EscapeCommFunction", (int) GetLastError ()); return SCPE_IOERR; } if (bits_to_set&TMXR_MDM_RTS) if (!EscapeCommFunction (port->hPort, SETRTS)) { sim_error_serial ("EscapeCommFunction", (int) GetLastError ()); return SCPE_IOERR; } if (bits_to_clear&TMXR_MDM_RTS) if (!EscapeCommFunction (port->hPort, CLRRTS)) { sim_error_serial ("EscapeCommFunction", (int) GetLastError ()); return SCPE_IOERR; } if (incoming_bits) { DWORD ModemStat; if (GetCommModemStatus (port->hPort, &ModemStat)) { sim_error_serial ("GetCommModemStatus", (int) GetLastError ()); return SCPE_IOERR; } *incoming_bits = ((ModemStat&MS_CTS_ON) ? TMXR_MDM_CTS : 0) | ((ModemStat&MS_DSR_ON) ? TMXR_MDM_DSR : 0) | ((ModemStat&MS_RING_ON) ? TMXR_MDM_RNG : 0) | ((ModemStat&MS_RLSD_ON) ? TMXR_MDM_DCD : 0); } return SCPE_OK; } /* Read from a serial port. The port is checked for available characters. If any are present, they are copied to the passed buffer, and the count of characters is returned. If no characters are available, 0 is returned. If an error occurs, -1 is returned. If a BREAK is detected on the communications line, the corresponding flag in the "brk" array is set. Implementation notes: 1. The "ClearCommError" function will set the CE_BREAK flag in the returned errors value if a BREAK has occurred. However, we do not know where in the serial stream it happened, as CE_BREAK isn't associated with a specific character. Because the "brk" array does want a flag associated with a specific character, we guess at the proper location by setting the "brk" entry corresponding to the first NUL in the character stream. If no NUL is present, then the "brk" entry associated with the first character is set. */ int32 sim_read_serial (SERHANDLE port, char *buffer, int32 count, char *brk) { DWORD read; DWORD commerrors; COMSTAT cs; char *bptr; if (!ClearCommError (port->hPort, &commerrors, &cs)) { /* get the comm error flags */ sim_error_serial ("ClearCommError", /* function failed; report unexpected error */ (int) GetLastError ()); return -1; /* return failure to caller */ } if (!ReadFile (port->hPort, (LPVOID) buffer, /* read any available characters */ (DWORD) count, &read, &port->oReadSync)) { sim_error_serial ("ReadFile", /* function failed; report unexpected error */ (int) GetLastError ()); return -1; /* return failure to caller */ } if (commerrors & CE_BREAK) { /* was a BREAK detected? */ bptr = (char *) memchr (buffer, 0, read); /* search for the first NUL in the buffer */ if (bptr) /* was one found? */ brk = brk + (bptr - buffer); /* calculate corresponding position */ *brk = 1; /* set the BREAK flag */ } return read; /* return the number of characters read */ } /* Write to a serial port. "Count" characters are written from "buffer" to the serial port. The actual number of characters written to the port is returned. If an error occurred on writing, -1 is returned. */ int32 sim_write_serial (SERHANDLE port, char *buffer, int32 count) { if (WaitForSingleObject (port->oWriteReady.hEvent, 0) == WAIT_TIMEOUT) return 0; if ((!WriteFile (port->hPort, (LPVOID) buffer, /* write the buffer to the serial port */ (DWORD) count, NULL, &port->oWriteSync)) && (GetLastError () != ERROR_IO_PENDING)) { sim_error_serial ("WriteFile", /* function failed; report unexpected error */ (int) GetLastError ()); return -1; /* return failure to caller */ } if ((!WaitCommEvent (port->hPort, &port->dwEvtMask, &port->oWriteReady)) && (GetLastError () != ERROR_IO_PENDING)) { sim_error_serial ("WaitCommEvent", /* function failed; report unexpected error */ (int) GetLastError ()); return -1; /* return failure to caller */ } return count; /* return number of characters written/queued */ } /* Close a serial port. The serial port is closed. Errors are ignored. */ static void sim_close_os_serial (SERHANDLE port) { if (port->oWriteReady.hEvent) CloseHandle (port->oWriteReady.hEvent); /* close the event handle */ if (port->oReadSync.hEvent) CloseHandle (port->oReadSync.hEvent); /* close the event handle */ if (port->oWriteSync.hEvent) CloseHandle (port->oWriteSync.hEvent); /* close the event handle */ if (port->hPort) CloseHandle (port->hPort); /* close the port */ free (port); } #elif defined (__unix__) || defined(__APPLE__) || defined(__hpux) struct SERPORT { int port; }; #if defined(__linux) || defined(__linux__) #include <dirent.h> #include <libgen.h> #include <unistd.h> #include <sys/stat.h> #endif /* __linux__ */ /* UNIX implementation */ /* Enumerate the available serial ports. The serial port names generated by attempting to open /dev/ttyS0 thru /dev/ttyS63 and /dev/ttyUSB0 thru /dev/ttyUSB63 and /dev/tty.serial0 thru /dev/tty.serial63. Ones we can open and are ttys (as determined by isatty()) are added to the list. The list is sorted alphabetically by device name. */ static int sim_serial_os_devices (int max, SERIAL_LIST* list) { int i; int port; int ports = 0; memset(list, 0, max*sizeof(*list)); #if defined(__linux) || defined(__linux__) if (1) { struct dirent **namelist; struct stat st; i = scandir("/sys/class/tty/", &namelist, NULL, NULL); while (i--) { if (strcmp(namelist[i]->d_name, ".") && strcmp(namelist[i]->d_name, "..")) { char path[1024], devicepath[1024], driverpath[1024]; sprintf (path, "/sys/class/tty/%s", namelist[i]->d_name); sprintf (devicepath, "/sys/class/tty/%s/device", namelist[i]->d_name); sprintf (driverpath, "/sys/class/tty/%s/device/driver", namelist[i]->d_name); if ((lstat(devicepath, &st) == 0) && S_ISLNK(st.st_mode)) { char buffer[1024]; memset (buffer, 0, sizeof(buffer)); if (readlink(driverpath, buffer, sizeof(buffer)) > 0) { sprintf (list[ports].name, "/dev/%s", basename (path)); port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ if (port != -1) { /* open OK? */ if (isatty (port)) /* is device a TTY? */ ++ports; close (port); } } } } free (namelist[i]); } free (namelist); } #elif defined(__hpux) for (i=0; (ports < max) && (i < 64); ++i) { sprintf (list[ports].name, "/dev/tty%dp%d", i/8, i%8); port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ if (port != -1) { /* open OK? */ if (isatty (port)) /* is device a TTY? */ ++ports; close (port); } } #else /* Non Linux/HP-UX, just try some well known device names */ for (i=0; (ports < max) && (i < 64); ++i) { sprintf (list[ports].name, "/dev/ttyS%d", i); port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ if (port != -1) { /* open OK? */ if (isatty (port)) /* is device a TTY? */ ++ports; close (port); } } for (i=0; (ports < max) && (i < 64); ++i) { sprintf (list[ports].name, "/dev/ttyUSB%d", i); port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ if (port != -1) { /* open OK? */ if (isatty (port)) /* is device a TTY? */ ++ports; close (port); } } for (i=1; (ports < max) && (i < 64); ++i) { sprintf (list[ports].name, "/dev/tty.serial%d", i); port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ if (port != -1) { /* open OK? */ if (isatty (port)) /* is device a TTY? */ ++ports; close (port); } } for (i=0; (ports < max) && (i < 64); ++i) { sprintf (list[ports].name, "/dev/tty%02d", i); port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ if (port != -1) { /* open OK? */ if (isatty (port)) /* is device a TTY? */ ++ports; close (port); } } for (i=0; (ports < max) && (i < 8); ++i) { sprintf (list[ports].name, "/dev/ttyU%d", i); port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ if (port != -1) { /* open OK? */ if (isatty (port)) /* is device a TTY? */ ++ports; close (port); } } #endif return ports; } /* Open a serial port. The serial port designated by "name" is opened, and the handle to the port is returned. If an error occurs, INVALID_HANDLE is returned instead. After opening, the port is configured to "raw" mode. Implementation notes: 1. We use a non-blocking open to allow for polling during reads. 2. There is no way to limit "open" just to serial ports, so we must check after the port is opened. We do this with a combination of "isatty" and "tcgetattr". 3. We configure with PARMRK set and IGNBRK and BRKINT cleared. This will mark a communication line BREAK condition in the input stream with the three-character sequence \377 \000 \000. This is detected during reading. */ static SERHANDLE sim_open_os_serial (char *name) { static const tcflag_t i_clear = IGNBRK | /* ignore BREAK */ BRKINT | /* signal on BREAK */ INPCK | /* enable parity checking */ ISTRIP | /* strip character to 7 bits */ INLCR | /* map NL to CR */ IGNCR | /* ignore CR */ ICRNL | /* map CR to NL */ IXON | /* enable XON/XOFF output control */ IXOFF; /* enable XON/XOFF input control */ static const tcflag_t i_set = PARMRK | /* mark parity errors and line breaks */ IGNPAR; /* ignore parity errors */ static const tcflag_t o_clear = OPOST; /* post-process output */ static const tcflag_t o_set = 0; static const tcflag_t c_clear = HUPCL; /* hang up line on last close */ static const tcflag_t c_set = CREAD | /* enable receiver */ CLOCAL; /* ignore modem status lines */ static const tcflag_t l_clear = ISIG | /* enable signals */ ICANON | /* canonical input */ ECHO | /* echo characters */ ECHOE | /* echo ERASE as an error correcting backspace */ ECHOK | /* echo KILL */ ECHONL | /* echo NL */ NOFLSH | /* disable flush after interrupt */ TOSTOP | /* send SIGTTOU for background output */ IEXTEN; /* enable extended functions */ static const tcflag_t l_set = 0; int port; SERHANDLE serport; struct termios tio; port = open (name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ if (port == -1) { /* open failed? */ if (errno != ENOENT && errno != EACCES) /* file not found or can't open? */ sim_error_serial ("open", errno); /* no, so report unexpected error */ return INVALID_HANDLE; /* indicate failure to caller */ } if (!isatty (port)) { /* is device a TTY? */ close (port); /* no, so close it */ return INVALID_HANDLE; /* and return failure to caller */ } if (tcgetattr (port, &tio)) { /* get the terminal attributes */ sim_error_serial ("tcgetattr", errno); /* function failed; report unexpected error */ close (port); /* close the port */ return INVALID_HANDLE; /* and return failure to caller */ } // which of these methods is best? #if 1 tio.c_iflag = (tio.c_iflag & ~i_clear) | i_set; /* configure the serial line for raw mode */ tio.c_oflag = (tio.c_oflag & ~o_clear) | o_set; tio.c_cflag = (tio.c_cflag & ~c_clear) | c_set; tio.c_lflag = (tio.c_lflag & ~l_clear) | l_set; #ifdef VMIN tio.c_cc[VMIN] = 1; #endif #ifdef VTIME tio.c_cc[VTIME] = 0; #endif #elif 0 tio.c_iflag &= ~(IGNBRK | BRKINT | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF); tio.c_iflag |= PARMRK | IGNPAR; tio.c_oflag &= ~(OPOST); tio.c_cflag &= ~(HUPCL); tio.c_cflag |= CREAD | CLOCAL; tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | NOFLSH | TOSTOP | IEXTEN); #elif 0 tio.c_iflag = PARMRK | IGNPAR; tio.c_oflag = 0; tio.c_cflag = tio.c_cflag | CLOCAL | CREAD; tio.c_lflag = 0; #endif if (tcsetattr (port, TCSANOW, &tio)) { /* set the terminal attributes */ sim_error_serial ("tcsetattr", errno); /* function failed; report unexpected error */ close (port); /* close the port */ return INVALID_HANDLE; /* and return failure to caller */ } serport = (SERHANDLE)calloc (1, sizeof(*serport)); serport->port = port; return serport; /* return port fd for success */ } /* Configure a serial port. Port parameters are configured as specified in the "config" structure. If "config" contains an invalid configuration value, or if the host system rejects the configuration (e.g., by requesting an unsupported combination of character size and stop bits), SCPE_ARG is returned to the caller. If an unexpected error occurs, SCPE_IOERR is returned. If the configuration succeeds, SCPE_OK is returned. Implementation notes: 1. 1.5 stop bits is not a supported configuration. */ static t_stat sim_config_os_serial (SERHANDLE port, SERCONFIG config) { struct termios tio; int32 i; static const struct { uint32 rate; speed_t rate_code; } baud_map [] = { { 50, B50 }, { 75, B75 }, { 110, B110 }, { 134, B134 }, { 150, B150 }, { 200, B200 }, { 300, B300 }, { 600, B600 }, { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 }, { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 } }; static const int32 baud_count = sizeof (baud_map) / sizeof (baud_map [0]); static const tcflag_t charsize_map [4] = { CS5, CS6, CS7, CS8 }; if (tcgetattr (port->port, &tio)) { /* get the current configuration */ sim_error_serial ("tcgetattr", errno); /* function failed; report unexpected error */ return SCPE_IOERR; /* return failure status */ } for (i = 0; i < baud_count; i++) /* assign baud rate */ if (config.baudrate == baud_map [i].rate) { /* match mapping value? */ cfsetispeed(&tio, baud_map [i].rate_code); /* set input rate */ cfsetospeed(&tio, baud_map [i].rate_code); /* set output rate */ break; } if (i == baud_count) /* baud rate assigned? */ return SCPE_ARG; /* invalid rate specified */ if ((config.charsize >= 5) && (config.charsize <= 8)) /* character size OK? */ tio.c_cflag = (tio.c_cflag & ~CSIZE) | /* replace character size code */ charsize_map [config.charsize - 5]; else return SCPE_ARG; /* not a valid size */ switch (config.parity) { /* assign parity */ case 'E': tio.c_cflag = (tio.c_cflag & ~PARODD) | PARENB; /* set for even parity */ break; case 'N': tio.c_cflag = tio.c_cflag & ~PARENB; /* set for no parity */ break; case 'O': tio.c_cflag = tio.c_cflag | PARODD | PARENB; /* set for odd parity */ break; default: return SCPE_ARG; /* not a valid parity specifier */ } if (config.stopbits == 1) /* one stop bit? */ tio.c_cflag = tio.c_cflag & ~CSTOPB; /* clear two-bits flag */ else if (config.stopbits == 2) /* two stop bits? */ tio.c_cflag = tio.c_cflag | CSTOPB; /* set two-bits flag */ else /* some other number? */ return SCPE_ARG; /* not a valid number of stop bits */ if (tcsetattr (port->port, TCSAFLUSH, &tio)) { /* set the new configuration */ sim_error_serial ("tcsetattr", errno); /* function failed; report unexpected error */ return SCPE_IERR; /* return failure status */ } return SCPE_OK; /* configuration set successfully */ } /* Control a serial port. The DTR and RTS line of the serial port is set or cleared as indicated in the respective bits_to_set or bits_to_clear parameters. If the incoming_bits parameter is not NULL, then the modem status bits DCD, RNG, DSR and CTS are returned. If unreasonable or nonsense bits_to_set or bits_to_clear bits are specified, then the return status is SCPE_ARG; If an error occurs, SCPE_IOERR is returned. */ t_stat sim_control_serial (SERHANDLE port, int32 bits_to_set, int32 bits_to_clear, int32 *incoming_bits) { int bits; if ((bits_to_set & ~(TMXR_MDM_OUTGOING)) || /* Assure only settable bits */ (bits_to_clear & ~(TMXR_MDM_OUTGOING)) || (bits_to_set & bits_to_clear)) /* and can't set and clear the same bits */ return SCPE_ARG; if (bits_to_set) { bits = ((bits_to_set&TMXR_MDM_DTR) ? TIOCM_DTR : 0) | ((bits_to_set&TMXR_MDM_RTS) ? TIOCM_RTS : 0); if (ioctl (port->port, TIOCMBIS, &bits)) { /* set the desired bits */ sim_error_serial ("ioctl", errno); /* report unexpected error */ return SCPE_IOERR; /* return failure status */ } } if (bits_to_clear) { bits = ((bits_to_clear&TMXR_MDM_DTR) ? TIOCM_DTR : 0) | ((bits_to_clear&TMXR_MDM_RTS) ? TIOCM_RTS : 0); if (ioctl (port->port, TIOCMBIC, &bits)) { /* clear the desired bits */ sim_error_serial ("ioctl", errno); /* report unexpected error */ return SCPE_IOERR; /* return failure status */ } } if (incoming_bits) { if (ioctl (port->port, TIOCMGET, &bits)) { /* get the modem bits */ sim_error_serial ("ioctl", errno); /* report unexpected error */ return SCPE_IOERR; /* return failure status */ } *incoming_bits = ((bits&TIOCM_CTS) ? TMXR_MDM_CTS : 0) | ((bits&TIOCM_DSR) ? TMXR_MDM_DSR : 0) | ((bits&TIOCM_RNG) ? TMXR_MDM_RNG : 0) | ((bits&TIOCM_CAR) ? TMXR_MDM_DCD : 0); } return SCPE_OK; } /* Read from a serial port. The port is checked for available characters. If any are present, they are copied to the passed buffer, and the count of characters is returned. If no characters are available, 0 is returned. If an error occurs, -1 is returned. If a BREAK is detected on the communications line, the corresponding flag in the "brk" array is set. Implementation notes: 1. A character with a framing or parity error is indicated in the input stream by the three-character sequence \377 \000 \ccc, where "ccc" is the bad character. A communications line BREAK is indicated by the sequence \377 \000 \000. A received \377 character is indicated by the two-character sequence \377 \377. If we find any of these sequences, they are replaced by the single intended character by sliding the succeeding characters backward by one or two positions. If a BREAK sequence was encountered, the corresponding location in the "brk" array is determined, and the flag is set. Note that there may be multiple sequences in the buffer. */ int32 sim_read_serial (SERHANDLE port, char *buffer, int32 count, char *brk) { int read_count; char *bptr, *cptr; int32 remaining; read_count = read (port->port, (void *) buffer, (size_t) count);/* read from the serial port */ if (read_count == -1) /* read error? */ if (errno == EAGAIN) /* no characters available? */ return 0; /* return 0 to indicate */ else /* some other problem */ sim_error_serial ("read", errno); /* report unexpected error */ else { /* read succeeded */ cptr = buffer; /* point at start of buffer */ remaining = read_count - 1; /* stop search one char from end of string */ while (remaining > 0 && /* still characters to search? */ (bptr = (char*)memchr (cptr, '\377', remaining))) {/* search for start of PARMRK sequence */ remaining = remaining - (bptr - cptr) - 1; /* calc characters remaining */ if (*(bptr + 1) == '\377') { /* is it a \377 \377 sequence? */ memmove (bptr + 1, bptr + 2, remaining); /* slide string backward to leave first \377 */ remaining = remaining - 1; /* drop remaining count */ read_count = read_count - 1; /* and read count by char eliminated */ } else if (remaining > 0 && *(bptr + 1) == '\0') { /* is it a \377 \000 \ccc sequence? */ memmove (bptr, bptr + 2, remaining); /* slide string backward to leave \ccc */ remaining = remaining - 2; /* drop remaining count */ read_count = read_count - 2; /* and read count by chars eliminated */ if (*bptr == '\0') /* is it a BREAK sequence? */ *(brk + (bptr - buffer)) = 1; /* set corresponding BREAK flag */ } cptr = bptr + 1; /* point at remainder of string */ } } return (int32) read_count; /* return the number of characters read */ } /* Write to a serial port. "Count" characters are written from "buffer" to the serial port. The actual number of characters written to the port is returned. If an error occurred on writing, -1 is returned. */ int32 sim_write_serial (SERHANDLE port, char *buffer, int32 count) { int written; written = write (port->port, (void *) buffer, (size_t) count);/* write the buffer to the serial port */ if (written == -1) { if (errno == EWOULDBLOCK) written = 0; /* not an error, but nothing written */ #if defined(EAGAIN) else if (errno == EAGAIN) written = 0; /* not an error, but nothing written */ #endif else /* unexpected error? */ sim_error_serial ("write", errno); /* report it */ } return (int32) written; /* return number of characters written */ } /* Close a serial port. The serial port is closed. Errors are ignored. */ static void sim_close_os_serial (SERHANDLE port) { close (port->port); /* close the port */ free (port); } #elif defined (VMS) /* VMS implementation */ #if defined(__VAX) #define sys$assign SYS$ASSIGN #define sys$qio SYS$QIO #define sys$qiow SYS$QIOW #define sys$dassgn SYS$DASSGN #define sys$device_scan SYS$DEVICE_SCAN #define sys$getdviw SYS$GETDVIW #endif #include <descrip.h> #include <ttdef.h> #include <tt2def.h> #include <iodef.h> #include <ssdef.h> #include <dcdef.h> #include <dvsdef.h> #include <dvidef.h> #include <starlet.h> #include <unistd.h> typedef struct { unsigned short sense_count; unsigned char sense_first_char; unsigned char sense_reserved; unsigned int stat; unsigned int stat2; } SENSE_BUF; typedef struct { unsigned short status; unsigned short count; unsigned int dev_status; } IOSB; typedef struct { unsigned short buffer_size; unsigned short item_code; void *buffer_address; void *return_length_address; } ITEM; struct SERPORT { uint32 port; IOSB write_iosb; }; /* Enumerate the available serial ports. The serial port names generated by attempting to open /dev/ttyS0 thru /dev/ttyS53 and /dev/ttyUSB0 thru /dev/ttyUSB0. Ones we can open and are ttys (as determined by isatty()) are added to the list. The list is sorted alphabetically by device name. */ static int sim_serial_os_devices (int max, SERIAL_LIST* list) { $DESCRIPTOR (wild, "*"); char devstr[sizeof(list[0].name)]; $DESCRIPTOR (device, devstr); int ports; IOSB iosb; uint32 status; uint32 devsts; #define UCB$M_TEMPLATE 0x2000 /* Device is a template device */ #define UCB$M_ONLINE 0x0010 /* Device is online */ uint32 devtype; uint32 devdepend; #define DEV$M_RTM 0x20000000 uint32 devnamlen = 0; t_bool done = FALSE; uint32 context[2]; uint32 devclass = DC$_TERM; /* Only interested in terminal devices */ ITEM select_items[] = { {sizeof (devclass), DVS$_DEVCLASS, &devclass, NULL}, { 0, 0, NULL, NULL}}; ITEM valid_items[] = { { sizeof (devsts), DVI$_STS, &devsts, NULL}, { sizeof(devstr), DVI$_DEVNAM, devstr, &devnamlen}, { sizeof(devtype), DVI$_DEVTYPE, &devtype, NULL}, { sizeof(devdepend), DVI$_DEVDEPEND, &devdepend, NULL}, { 0, 0, NULL, NULL}}; memset(context, 0, sizeof(context)); memset(devstr, 0, sizeof(devstr)); memset(list, 0, max*sizeof(*list)); for (ports=0; (ports < max); ++ports) { device.dsc$w_length = sizeof (devstr) - 1; status = sys$device_scan (&device, &device.dsc$w_length, &wild, select_items, &context); switch (status) { case SS$_NOSUCHDEV: case SS$_NOMOREDEV: done = TRUE; break; default: if (0 == (status&1)) done = TRUE; else { status = sys$getdviw (0, 0, &device, valid_items, &iosb, NULL, 0, NULL); if (status == SS$_NORMAL) status = iosb.status; if (status != SS$_NORMAL) { done = TRUE; break; } device.dsc$w_length = devnamlen; if ((0 == (devsts & UCB$M_TEMPLATE)) && (0 != (devsts & UCB$M_ONLINE)) && (0 == (devdepend & DEV$M_RTM))) { devstr[device.dsc$w_length] = '\0'; strcpy (list[ports].name, devstr); while (list[ports].name[0] == '_') strcpy (list[ports].name, list[ports].name+1); } else --ports; } break; } if (done) break; } return ports; } /* Open a serial port. The serial port designated by "name" is opened, and the handle to the port is returned. If an error occurs, INVALID_HANDLE is returned instead. After opening, the port is configured to "raw" mode. Implementation notes: 1. We use a non-blocking open to allow for polling during reads. 2. There is no way to limit "open" just to serial ports, so we must check after the port is opened. We do this with sys$getdvi. */ static SERHANDLE sim_open_os_serial (char *name) { uint32 status; uint32 chan = 0; IOSB iosb; $DESCRIPTOR (devnam, name); uint32 devclass; ITEM items[] = { {sizeof (devclass), DVI$_DEVCLASS, &devclass, NULL}, { 0, 0, NULL, NULL}}; SENSE_BUF start_mode = { 0 }; SENSE_BUF run_mode = { 0 }; SERHANDLE port; devnam.dsc$w_length = strlen (devnam.dsc$a_pointer); status = sys$assign (&devnam, &chan, 0, 0); if (status != SS$_NORMAL) return INVALID_HANDLE; status = sys$getdviw (0, chan, NULL, items, &iosb, NULL, 0, NULL); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL) || (devclass != DC$_TERM)) { sys$dassgn (chan); return INVALID_HANDLE; } status = sys$qiow (0, chan, IO$_SENSEMODE, &iosb, 0, 0, &start_mode, sizeof (start_mode), 0, 0, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) { sys$dassgn (chan); return INVALID_HANDLE; } run_mode = start_mode; run_mode.stat = start_mode.stat | TT$M_NOECHO & ~(TT$M_HOSTSYNC | TT$M_TTSYNC | TT$M_HALFDUP); run_mode.stat2 = start_mode.stat2 | TT2$M_PASTHRU; status = sys$qiow (0, chan, IO$_SETMODE, &iosb, 0, 0, &run_mode, sizeof (run_mode), 0, 0, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) { sys$dassgn (chan); return INVALID_HANDLE; } port = (SERHANDLE)calloc (1, sizeof(*port)); port->port = chan; port->write_iosb.status = 1; return port; /* return channel for success */ } /* Configure a serial port. Port parameters are configured as specified in the "config" structure. If "config" contains an invalid configuration value, or if the host system rejects the configuration (e.g., by requesting an unsupported combination of character size and stop bits), SCPE_ARG is returned to the caller. If an unexpected error occurs, SCPE_IOERR is returned. If the configuration succeeds, SCPE_OK is returned. Implementation notes: 1. 1.5 stop bits is not a supported configuration. */ static t_stat sim_config_os_serial (SERHANDLE port, SERCONFIG config) { int32 i; SENSE_BUF sense; uint32 status, speed, parity, charsize, stopbits; IOSB iosb; static const struct { uint32 rate; uint32 rate_code; } baud_map [] = { { 50, TT$C_BAUD_50 }, { 75, TT$C_BAUD_75 }, { 110, TT$C_BAUD_110 }, { 134, TT$C_BAUD_134 }, { 150, TT$C_BAUD_150 }, { 300, TT$C_BAUD_300 }, { 600, TT$C_BAUD_600 }, { 1200, TT$C_BAUD_1200 }, { 1800, TT$C_BAUD_1800 }, { 2000, TT$C_BAUD_2000 }, { 2400, TT$C_BAUD_2400 }, { 3600, TT$C_BAUD_3600 }, { 4800, TT$C_BAUD_4800 }, { 7200, TT$C_BAUD_7200 }, { 9600, TT$C_BAUD_9600 }, { 19200, TT$C_BAUD_19200 }, { 38400, TT$C_BAUD_38400 }, { 57600, TT$C_BAUD_57600 }, { 76800, TT$C_BAUD_76800 }, { 115200, TT$C_BAUD_115200} }; static const int32 baud_count = sizeof (baud_map) / sizeof (baud_map [0]); status = sys$qiow (0, port->port, IO$_SENSEMODE, &iosb, 0, 0, &sense, sizeof(sense), 0, NULL, 0, 0); if (status == SS$_NORMAL) status = iosb.status; if (status != SS$_NORMAL) { sim_error_serial ("config-SENSEMODE", status); /* report unexpected error */ return SCPE_IOERR; } for (i = 0; i < baud_count; i++) /* assign baud rate */ if (config.baudrate == baud_map [i].rate) { /* match mapping value? */ speed = baud_map [i].rate_code << 8 | /* set input rate */ baud_map [i].rate_code; /* set output rate */ break; } if (i == baud_count) /* baud rate assigned? */ return SCPE_ARG; /* invalid rate specified */ if (config.charsize >= 5 && config.charsize <= 8) /* character size OK? */ charsize = TT$M_ALTFRAME | config.charsize; /* set character size */ else return SCPE_ARG; /* not a valid size */ switch (config.parity) { /* assign parity */ case 'E': parity = TT$M_ALTRPAR | TT$M_PARITY; /* set for even parity */ break; case 'N': parity = TT$M_ALTRPAR; /* set for no parity */ break; case 'O': parity = TT$M_ALTRPAR | TT$M_PARITY | TT$M_ODD; /* set for odd parity */ break; default: return SCPE_ARG; /* not a valid parity specifier */ } switch (config.stopbits) { case 1: /* one stop bit? */ stopbits = 0; break; case 2: /* two stop bits? */ if ((speed & 0xff) <= TT$C_BAUD_150) { /* Only valid for */ stopbits = TT$M_TWOSTOP; /* speeds 150baud or less */ break; } default: return SCPE_ARG; /* not a valid number of stop bits */ } status = sys$qiow (0, port->port, IO$_SETMODE, &iosb, 0, 0, &sense, sizeof (sense), speed, 0, parity | charsize | stopbits, 0); if (status == SS$_NORMAL) status = iosb.status; if (status != SS$_NORMAL) { sim_error_serial ("config-SETMODE", status); /* report unexpected error */ return SCPE_IOERR; } return SCPE_OK; /* configuration set successfully */ } /* Control a serial port. The DTR and RTS line of the serial port is set or cleared as indicated in the respective bits_to_set or bits_to_clear parameters. If the incoming_bits parameter is not NULL, then the modem status bits DCD, RNG, DSR and CTS are returned. If unreasonable or nonsense bits_to_set or bits_to_clear bits are specified, then the return status is SCPE_ARG; If an error occurs, SCPE_IOERR is returned. */ t_stat sim_control_serial (SERHANDLE port, int32 bits_to_set, int32 bits_to_clear, int32 *incoming_bits) { uint32 status; IOSB iosb; uint32 bits[2] = {0, 0}; if ((bits_to_set & ~(TMXR_MDM_OUTGOING)) || /* Assure only settable bits */ (bits_to_clear & ~(TMXR_MDM_OUTGOING)) || (bits_to_set & bits_to_clear)) /* and can't set and clear the same bits */ return SCPE_ARG; if (bits_to_set) bits[0] |= (((bits_to_set&TMXR_MDM_DTR) ? TT$M_DS_DTR : 0) | ((bits_to_set&TMXR_MDM_RTS) ? TT$M_DS_RTS : 0)) << 16; if (bits_to_clear) bits[0] |= (((bits_to_clear&TMXR_MDM_DTR) ? TT$M_DS_DTR : 0) | ((bits_to_clear&TMXR_MDM_RTS) ? TT$M_DS_RTS : 0)) << 24; if (bits_to_set || bits_to_clear) { status = sys$qiow (0, port->port, IO$_SETMODE|IO$M_SET_MODEM|IO$M_MAINT, &iosb, 0, 0, bits, 0, 0, 0, 0, 0); if (status == SS$_NORMAL) status = iosb.status; if (status != SS$_NORMAL) { sim_error_serial ("control-SETMODE", status); /* report unexpected error */ return SCPE_IOERR; } } if (incoming_bits) { uint32 modem; status = sys$qiow (0, port->port, IO$_SENSEMODE|IO$M_RD_MODEM, &iosb, 0, 0, bits, 0, 0, 0, 0, 0); if (status == SS$_NORMAL) status = iosb.status; if (status != SS$_NORMAL) { sim_error_serial ("control-SENSEMODE", status); /* report unexpected error */ return SCPE_IOERR; } modem = bits[0] >> 16; *incoming_bits = ((modem&TT$M_DS_CTS) ? TMXR_MDM_CTS : 0) | ((modem&TT$M_DS_DSR) ? TMXR_MDM_DSR : 0) | ((modem&TT$M_DS_RING) ? TMXR_MDM_RNG : 0) | ((modem&TT$M_DS_CARRIER) ? TMXR_MDM_DCD : 0); } return SCPE_OK; } /* Read from a serial port. The port is checked for available characters. If any are present, they are copied to the passed buffer, and the count of characters is returned. If no characters are available, 0 is returned. If an error occurs, -1 is returned. If a BREAK is detected on the communications line, the corresponding flag in the "brk" array is set. Implementation notes: 1. A character with a framing or parity error is indicated in the input stream by the three-character sequence \377 \000 \ccc, where "ccc" is the bad character. A communications line BREAK is indicated by the sequence \377 \000 \000. A received \377 character is indicated by the two-character sequence \377 \377. If we find any of these sequences, they are replaced by the single intended character by sliding the succeeding characters backward by one or two positions. If a BREAK sequence was encountered, the corresponding location in the "brk" array is determined, and the flag is set. Note that there may be multiple sequences in the buffer. */ int32 sim_read_serial (SERHANDLE port, char *buffer, int32 count, char *brk) { int read_count = 0; uint32 status; static uint32 term[2] = {0, 0}; unsigned char buf[4]; IOSB iosb; SENSE_BUF sense; status = sys$qiow (0, port->port, IO$_SENSEMODE | IO$M_TYPEAHDCNT, &iosb, 0, 0, &sense, 8, 0, term, 0, 0); if (status == SS$_NORMAL) status = iosb.status; if (status != SS$_NORMAL) { sim_error_serial ("read", status); /* report unexpected error */ return -1; } if (sense.sense_count == 0) /* no characters available? */ return 0; /* return 0 to indicate */ status = sys$qiow (0, port->port, IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED | IO$M_TRMNOECHO, &iosb, 0, 0, buffer, (count < sense.sense_count) ? count : sense.sense_count, 0, term, 0, 0); if (status == SS$_NORMAL) status = iosb.status; if (status != SS$_NORMAL) { sim_error_serial ("read", status); /* report unexpected error */ return -1; } return (int32)iosb.count; /* return the number of characters read */ } /* Write to a serial port. "Count" characters are written from "buffer" to the serial port. The actual number of characters written to the port is returned. If an error occurred on writing, -1 is returned. */ int32 sim_write_serial (SERHANDLE port, char *buffer, int32 count) { uint32 status; if (port->write_iosb.status == 0) /* Prior write not done yet? */ return 0; status = sys$qio (0, port->port, IO$_WRITELBLK | IO$M_NOFORMAT, &port->write_iosb, 0, 0, buffer, count, 0, 0, 0, 0); if (status != SS$_NORMAL) { sim_error_serial ("write", status); /* report unexpected error */ return -1; } return (int32)count; /* return number of characters written */ } /* Close a serial port. The serial port is closed. Errors are ignored. */ static void sim_close_os_serial (SERHANDLE port) { sys$dassgn (port->port); /* close the port */ free (port); } #else /* Non-implemented stubs */ /* Enumerate the available serial ports. */ static int sim_serial_os_devices (int max, SERIAL_LIST* list) { return 0; } /* Open a serial port */ static SERHANDLE sim_open_os_serial (char *name) { return INVALID_HANDLE; } /* Configure a serial port */ static t_stat sim_config_os_serial (SERHANDLE port, SERCONFIG config) { return SCPE_IERR; } /* Control a serial port */ t_stat sim_control_serial (SERHANDLE port, int32 bits_to_set, int32 bits_to_clear, int32 *incoming_bits) { return SCPE_NOFNC; } /* Read from a serial port */ int32 sim_read_serial (SERHANDLE port, char *buffer, int32 count, char *brk) { return -1; } /* Write to a serial port */ int32 sim_write_serial (SERHANDLE port, char *buffer, int32 count) { return -1; } /* Close a serial port */ static void sim_close_os_serial (SERHANDLE port) { } #endif /* end else !implemented */ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | /* sim_serial.h: OS-dependent serial port routines header file Copyright (c) 2008, J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the author shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. 07-Oct-08 JDB [serial] Created file */ #ifndef SIM_SERIAL_H_ #define SIM_SERIAL_H_ 0 #ifdef __cplusplus extern "C" { #endif #ifndef SIMH_SERHANDLE_DEFINED #define SIMH_SERHANDLE_DEFINED 0 typedef struct SERPORT *SERHANDLE; #endif /* SERHANDLE_DEFINED */ #if defined (_WIN32) /* Windows definitions */ /* We need the basic Win32 definitions, but including "windows.h" also includes "winsock.h" as well. However, "sim_sock.h" explicitly includes "winsock2.h," and this file cannot coexist with "winsock.h". So we set a guard definition that prevents "winsock.h" from being included. */ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include <windows.h> #if !defined(INVALID_HANDLE) #define INVALID_HANDLE (SERHANDLE)INVALID_HANDLE_VALUE #endif /* !defined(INVALID_HANDLE) */ #elif defined (__unix__) || defined (__APPLE__) || defined (__hpux) /* UNIX definitions */ #include <fcntl.h> #ifdef __hpux #include <sys/modem.h> #endif #include <termios.h> #include <unistd.h> #include <sys/ioctl.h> #if !defined(INVALID_HANDLE) #define INVALID_HANDLE ((SERHANDLE)(void *)-1) #endif /* !defined(INVALID_HANDLE) */ #elif defined (VMS) /* VMS definitions */ #if !defined(INVALID_HANDLE) #define INVALID_HANDLE ((SERHANDLE)(void *)-1) #endif /* !defined(INVALID_HANDLE) */ #else /* Non-implemented definitions */ #if !defined(INVALID_HANDLE) #define INVALID_HANDLE ((SERHANDLE)(void *)-1) #endif /* !defined(INVALID_HANDLE) */ #endif /* OS variants */ /* Common definitions */ /* Global routines */ #include "sim_tmxr.h" /* need TMLN definition and modem definitions */ extern SERHANDLE sim_open_serial (char *name, TMLN *lp, t_stat *status); extern t_stat sim_config_serial (SERHANDLE port, CONST char *config); extern t_stat sim_control_serial (SERHANDLE port, int32 bits_to_set, int32 bits_to_clear, int32 *incoming_bits); extern int32 sim_read_serial (SERHANDLE port, char *buffer, int32 count, char *brk); extern int32 sim_write_serial (SERHANDLE port, char *buffer, int32 count); extern void sim_close_serial (SERHANDLE port); extern t_stat sim_show_serial (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc); #ifdef __cplusplus } #endif #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 | /* sim_sock.c: OS-dependent socket routines Copyright (c) 2001-2010, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 15-Oct-12 MP Added definitions needed to detect possible tcp connect failures 25-Sep-12 MP Reworked for RFC3493 interfaces supporting IPv6 and IPv4 22-Jun-10 RMS Fixed types in sim_accept_conn (from Mark Pizzolato) 19-Nov-05 RMS Added conditional for OpenBSD (from Federico G. Schwindt) 16-Aug-05 RMS Fixed spurious SIGPIPE signal error in Unix 14-Apr-05 RMS Added WSAEINPROGRESS test (from Tim Riker) 09-Jan-04 RMS Fixed typing problem in Alpha Unix (found by Tim Chapman) 17-Apr-03 RMS Fixed non-implemented version of sim_close_sock (found by Mark Pizzolato) 17-Dec-02 RMS Added sim_connect_socket, sim_create_socket 08-Oct-02 RMS Revised for .NET compatibility 22-Aug-02 RMS Changed calling sequence for sim_accept_conn 22-May-02 RMS Added OS2 EMX support from Holger Veit 06-Feb-02 RMS Added VMS support from Robert Alan Byer 16-Sep-01 RMS Added Macintosh support from Peter Schorn 02-Sep-01 RMS Fixed UNIX bugs found by Mirian Lennox and Tom Markson */ #ifdef __cplusplus extern "C" { #endif #include "sim_sock.h" #include <signal.h> #include <stdio.h> #include <stdlib.h> #if defined(AF_INET6) && defined(_WIN32) #include <ws2tcpip.h> #endif #ifdef HAVE_DLOPEN #include <dlfcn.h> #endif #ifndef WSAAPI #define WSAAPI #endif #if defined(SHUT_RDWR) && !defined(SD_BOTH) #define SD_BOTH SHUT_RDWR #endif #ifndef NI_MAXHOST #define NI_MAXHOST 1025 #endif /* OS dependent routines sim_master_sock create master socket sim_connect_sock connect a socket to a remote destination sim_connect_sock_ex connect a socket to a remote destination sim_accept_conn accept connection sim_read_sock read from socket sim_write_sock write from socket sim_close_sock close socket sim_setnonblock set socket non-blocking */ /* First, all the non-implemented versions */ #if defined (__OS2__) && !defined (__EMX__) void sim_init_sock (void) { } void sim_cleanup_sock (void) { } SOCKET sim_master_sock_ex (const char *hostport, int *parse_status, int opt_flags) { return INVALID_SOCKET; } SOCKET sim_connect_sock_ex (const char *sourcehostport, const char *hostport, const char *default_host, const char *default_port, int opt_flags) { return INVALID_SOCKET; } SOCKET sim_accept_conn (SOCKET master, char **connectaddr); { return INVALID_SOCKET; } int sim_read_sock (SOCKET sock, char *buf, int nbytes) { return -1; } int sim_write_sock (SOCKET sock, char *msg, int nbytes) { return 0; } void sim_close_sock (SOCKET sock) { return; } #else /* endif unimpl */ /* UNIX, Win32, Macintosh, VMS, OS2 (Berkeley socket) routines */ static struct sock_errors { int value; const char *text; } sock_errors[] = { {WSAEWOULDBLOCK, "Operation would block"}, {WSAENAMETOOLONG, "File name too long"}, {WSAEINPROGRESS, "Operation now in progress "}, {WSAETIMEDOUT, "Connection timed out"}, {WSAEISCONN, "Transport endpoint is already connected"}, {WSAECONNRESET, "Connection reset by peer"}, {WSAECONNREFUSED, "Connection refused"}, {WSAECONNABORTED, "Connection aborted"}, {WSAEHOSTUNREACH, "No route to host"}, {WSAEADDRINUSE, "Address already in use"}, #if defined (WSAEAFNOSUPPORT) {WSAEAFNOSUPPORT, "Address family not supported by protocol"}, #endif {WSAEACCES, "Permission denied"}, {0, NULL} }; const char *sim_get_err_sock (const char *emsg) { int err = WSAGetLastError (); int i; static char err_buf[512]; for (i=0; (sock_errors[i].text) && (sock_errors[i].value != err); i++) ; if (sock_errors[i].value == err) sprintf (err_buf, "Sockets: %s error %d - %s\n", emsg, err, sock_errors[i].text); else #if defined(_WIN32) sprintf (err_buf, "Sockets: %s error %d\n", emsg, err); #else sprintf (err_buf, "Sockets: %s error %d - %s\n", emsg, err, strerror(err)); #endif return err_buf; } SOCKET sim_err_sock (SOCKET s, const char *emsg) { sim_printf ("%s", sim_get_err_sock (emsg)); if (s != INVALID_SOCKET) { int err = WSAGetLastError (); sim_close_sock (s); WSASetLastError (err); /* Retain Original socket error value */ } return INVALID_SOCKET; } typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo *ai); static freeaddrinfo_func p_freeaddrinfo; typedef int (WSAAPI *getaddrinfo_func) (const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **res); static getaddrinfo_func p_getaddrinfo; #if defined(VMS) typedef size_t socklen_t; #if !defined(EAI_OVERFLOW) #define EAI_OVERFLOW EAI_FAIL #endif #endif #if defined(__hpux) #if !defined(EAI_OVERFLOW) #define EAI_OVERFLOW EAI_FAIL #endif #endif typedef int (WSAAPI *getnameinfo_func) (const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); static getnameinfo_func p_getnameinfo; static void WSAAPI s_freeaddrinfo (struct addrinfo *ai) { struct addrinfo *a, *an; for (a=ai; a != NULL; a=an) { an = a->ai_next; free (a->ai_canonname); free (a->ai_addr); free (a); } } static int WSAAPI s_getaddrinfo (const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **res) { struct hostent *he; struct servent *se = NULL; struct sockaddr_in *sin; struct addrinfo *result = NULL; struct addrinfo *ai, *lai = NULL; struct addrinfo dhints; struct in_addr ipaddr; struct in_addr *fixed[2]; struct in_addr **ips = NULL; struct in_addr **ip; const char *cname = NULL; int port = 0; // Validate parameters if ((hostname == NULL) && (service == NULL)) return EAI_NONAME; if (hints) { if ((hints->ai_family != PF_INET) && (hints->ai_family != PF_UNSPEC)) return EAI_FAMILY; switch (hints->ai_socktype) { default: return EAI_SOCKTYPE; case SOCK_DGRAM: case SOCK_STREAM: case 0: break; } } else { hints = &dhints; memset(&dhints, 0, sizeof(dhints)); dhints.ai_family = PF_UNSPEC; } if (service) { char *c; port = strtoul(service, &c, 10); if ((port == 0) || (*c != '\0')) { switch (hints->ai_socktype) { case SOCK_DGRAM: se = getservbyname(service, "udp"); break; case SOCK_STREAM: case 0: se = getservbyname(service, "tcp"); break; } if (NULL == se) return EAI_SERVICE; port = se->s_port; } } if (hostname) { if ((0xffffffff != (ipaddr.s_addr = inet_addr(hostname))) || (0 == strcmp("255.255.255.255", hostname))) { fixed[0] = &ipaddr; fixed[1] = NULL; } else { if ((0xffffffff != (ipaddr.s_addr = inet_addr(hostname))) || (0 == strcmp("255.255.255.255", hostname))) { fixed[0] = &ipaddr; fixed[1] = NULL; if ((hints->ai_flags & AI_CANONNAME) && !(hints->ai_flags & AI_NUMERICHOST)) { he = gethostbyaddr((char *)&ipaddr, 4, AF_INET); if (NULL != he) cname = he->h_name; else cname = hostname; } ips = fixed; } else { if (hints->ai_flags & AI_NUMERICHOST) return EAI_NONAME; he = gethostbyname(hostname); if (he) { ips = (struct in_addr **)he->h_addr_list; if (hints->ai_flags & AI_CANONNAME) cname = he->h_name; } else { switch (h_errno) { case HOST_NOT_FOUND: case NO_DATA: return EAI_NONAME; case TRY_AGAIN: return EAI_AGAIN; default: return EAI_FAIL; } } } } } else { if (hints->ai_flags & AI_PASSIVE) ipaddr.s_addr = htonl(INADDR_ANY); else ipaddr.s_addr = htonl(INADDR_LOOPBACK); fixed[0] = &ipaddr; fixed[1] = NULL; ips = fixed; } for (ip=ips; (ip != NULL) && (*ip != NULL); ++ip) { ai = (struct addrinfo *)calloc(1, sizeof(*ai)); if (NULL == ai) { s_freeaddrinfo(result); return EAI_MEMORY; } ai->ai_family = PF_INET; ai->ai_socktype = hints->ai_socktype; ai->ai_protocol = hints->ai_protocol; ai->ai_addr = NULL; ai->ai_addrlen = sizeof(struct sockaddr_in); ai->ai_canonname = NULL; ai->ai_next = NULL; ai->ai_addr = (struct sockaddr *)calloc(1, sizeof(struct sockaddr_in)); if (NULL == ai->ai_addr) { free(ai); s_freeaddrinfo(result); return EAI_MEMORY; } sin = (struct sockaddr_in *)ai->ai_addr; sin->sin_family = PF_INET; sin->sin_port = (unsigned short)port; memcpy(&sin->sin_addr, *ip, sizeof(sin->sin_addr)); if (NULL == result) result = ai; else lai->ai_next = ai; lai = ai; } if (cname) { result->ai_canonname = (char *)calloc(1, strlen(cname)+1); if (NULL == result->ai_canonname) { s_freeaddrinfo(result); return EAI_MEMORY; } strcpy(result->ai_canonname, cname); } *res = result; return 0; } #ifndef EAI_OVERFLOW #define EAI_OVERFLOW WSAENAMETOOLONG #endif static int WSAAPI s_getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { struct hostent *he; struct servent *se = NULL; const struct sockaddr_in *sin = (const struct sockaddr_in *)sa; if (sin->sin_family != PF_INET) return EAI_FAMILY; if ((NULL == host) && (NULL == serv)) return EAI_NONAME; if ((serv) && (servlen > 0)) { if (flags & NI_NUMERICSERV) se = NULL; else if (flags & NI_DGRAM) se = getservbyport(sin->sin_port, "udp"); else se = getservbyport(sin->sin_port, "tcp"); if (se) { if (servlen <= strlen(se->s_name)) return EAI_OVERFLOW; strcpy(serv, se->s_name); } else { char buf[16]; sprintf(buf, "%d", ntohs(sin->sin_port)); if (servlen <= strlen(buf)) return EAI_OVERFLOW; strcpy(serv, buf); } } if ((host) && (hostlen > 0)) { if (flags & NI_NUMERICHOST) he = NULL; else he = gethostbyaddr((const char *)&sin->sin_addr, 4, AF_INET); if (he) { if (hostlen < strlen(he->h_name)+1) return EAI_OVERFLOW; strcpy(host, he->h_name); } else { if (flags & NI_NAMEREQD) return EAI_NONAME; if (hostlen < strlen(inet_ntoa(sin->sin_addr))+1) return EAI_OVERFLOW; strcpy(host, inet_ntoa(sin->sin_addr)); } } return 0; } #if defined(_WIN32) || defined(__CYGWIN__) #if !defined(IPV6_V6ONLY) /* Older XP environments may not define IPV6_V6ONLY */ #define IPV6_V6ONLY 27 /* Treat wildcard bind as AF_INET6-only. */ #endif /* Dynamic DLL load variables */ #ifdef _WIN32 static HINSTANCE hLib = 0; /* handle to DLL */ #else static void *hLib = NULL; /* handle to Library */ #endif static int lib_loaded = 0; /* 0=not loaded, 1=loaded, 2=library load failed, 3=Func load failed */ static const char* lib_name = "Ws2_32.dll"; /* load function pointer from DLL */ typedef int (*_func)(); static void load_function(const char* function, _func* func_ptr) { #ifdef _WIN32 *func_ptr = (_func)GetProcAddress(hLib, function); #else *func_ptr = (_func)dlsym(hLib, function); #endif if (*func_ptr == 0) { sim_printf ("Sockets: Failed to find function '%s' in %s\r\n", function, lib_name); lib_loaded = 3; } } /* load Ws2_32.dll as required */ int load_ws2(void) { switch(lib_loaded) { case 0: /* not loaded */ /* attempt to load DLL */ #ifdef _WIN32 hLib = LoadLibraryA(lib_name); #else hLib = dlopen(lib_name, RTLD_NOW); #endif if (hLib == 0) { /* failed to load DLL */ sim_printf ("Sockets: Failed to load %s\r\n", lib_name); lib_loaded = 2; break; } else { /* library loaded OK */ lib_loaded = 1; } /* load required functions; sets dll_load=3 on error */ load_function("getaddrinfo", (_func *) &p_getaddrinfo); load_function("getnameinfo", (_func *) &p_getnameinfo); load_function("freeaddrinfo", (_func *) &p_freeaddrinfo); if (lib_loaded != 1) { /* unsuccessful load, connect stubs */ p_getaddrinfo = (getaddrinfo_func)s_getaddrinfo; p_getnameinfo = (getnameinfo_func)s_getnameinfo; p_freeaddrinfo = (freeaddrinfo_func)s_freeaddrinfo; } break; default: /* loaded or failed */ break; } return (lib_loaded == 1) ? 1 : 0; } #endif /* OS independent routines sim_parse_addr parse a hostname/ipaddress from port and apply defaults and optionally validate an address match */ /* sim_parse_addr host:port Presumption is that the input, if it doesn't contain a ':' character is a port specifier. If the host field contains one or more colon characters (i.e. it is an IPv6 address), the IPv6 address MUST be enclosed in square bracket characters (i.e. Domain Literal format) Inputs: cptr = pointer to input string default_host = optional pointer to default host if none specified host_len = length of host buffer default_port = optional pointer to default port if none specified port_len = length of port buffer validate_addr = optional name/addr which is checked to be equivalent to the host result of parsing the other input. This address would usually be returned by sim_accept_conn. Outputs: host = pointer to buffer for IP address (may be NULL), 0 = none port = pointer to buffer for IP port (may be NULL), 0 = none result = status (0 on complete success or -1 if parsing can't happen due to bad syntax, a value is out of range, a result can't fit into a result buffer, a service name doesn't exist, or a validation name doesn't match the parsed host) */ int sim_parse_addr (const char *cptr, char *host, size_t host_len, const char *default_host, char *port, size_t port_len, const char *default_port, const char *validate_addr) { char gbuf[CBUFSIZE], default_pbuf[CBUFSIZE]; const char *hostp; char *portp; char *endc; unsigned long portval; if ((host != NULL) && (host_len != 0)) memset (host, 0, host_len); if ((port != NULL) && (port_len != 0)) memset (port, 0, port_len); if ((cptr == NULL) || (*cptr == 0)) { if (((default_host == NULL) || (*default_host == 0)) || ((default_port == NULL) || (*default_port == 0))) return -1; if ((host == NULL) || (port == NULL)) return -1; /* no place */ if ((strlen(default_host) >= host_len) || (strlen(default_port) >= port_len)) return -1; /* no room */ strcpy (host, default_host); strcpy (port, default_port); return 0; } memset (default_pbuf, 0, sizeof(default_pbuf)); if (default_port) strncpy (default_pbuf, default_port, sizeof(default_pbuf)-1); gbuf[sizeof(gbuf)-1] = '\0'; strncpy (gbuf, cptr, sizeof(gbuf)-1); hostp = gbuf; /* default addr */ portp = NULL; if ((portp = strrchr (gbuf, ':')) && /* x:y? split */ (NULL == strchr (portp, ']'))) { *portp++ = 0; if (*portp == '\0') portp = default_pbuf; } else { /* No colon in input */ portp = gbuf; /* Input is the port specifier */ hostp = (const char *)default_host; /* host is defaulted if provided */ } if (portp != NULL) { portval = strtoul(portp, &endc, 10); if ((*endc == '\0') && ((portval == 0) || (portval > 65535))) return -1; /* numeric value too big */ if (*endc != '\0') { struct servent *se = getservbyname(portp, "tcp"); if (se == NULL) return -1; /* invalid service name */ } } if (port) /* port wanted? */ if (portp != NULL) { if (strlen(portp) >= port_len) return -1; /* no room */ else strcpy (port, portp); } if (hostp != NULL) { if (']' == hostp[strlen(hostp)-1]) { if ('[' != hostp[0]) return -1; /* invalid domain literal */ /* host may be the const default_host so move to temp buffer before modifying */ strncpy(gbuf, hostp+1, sizeof(gbuf)-1); /* remove brackets from domain literal host */ gbuf[strlen(gbuf)-1] = '\0'; hostp = gbuf; } } if (host) { /* host wanted? */ if (hostp != NULL) { if (strlen(hostp) >= host_len) return -1; /* no room */ else if (('\0' != hostp[0]) || (default_host == NULL)) strcpy (host, hostp); else if (strlen(default_host) >= host_len) return -1; /* no room */ else strcpy (host, default_host); } else { if (default_host) { if (strlen(default_host) >= host_len) return -1; /* no room */ else strcpy (host, default_host); } } } if (validate_addr) { struct addrinfo *ai_host, *ai_validate, *ai, *aiv; int status; if (hostp == NULL) return -1; if (p_getaddrinfo(hostp, NULL, NULL, &ai_host)) return -1; if (p_getaddrinfo(validate_addr, NULL, NULL, &ai_validate)) { p_freeaddrinfo (ai_host); return -1; } status = -1; for (ai = ai_host; ai != NULL; ai = ai->ai_next) { for (aiv = ai_validate; aiv != NULL; aiv = aiv->ai_next) { if ((ai->ai_addrlen == aiv->ai_addrlen) && (ai->ai_family == aiv->ai_family) && (0 == memcmp (ai->ai_addr, aiv->ai_addr, ai->ai_addrlen))) { status = 0; break; } } } if (status != 0) { /* be generous and allow successful validations against variations of localhost addresses */ if (((0 == strcmp("127.0.0.1", hostp)) && (0 == strcmp("::1", validate_addr))) || ((0 == strcmp("127.0.0.1", validate_addr)) && (0 == strcmp("::1", hostp)))) status = 0; } p_freeaddrinfo (ai_host); p_freeaddrinfo (ai_validate); return status; } return 0; } /* sim_parse_addr_ex localport:host:port Presumption is that the input, if it doesn't contain a ':' character is a port specifier. If the host field contains one or more colon characters (i.e. it is an IPv6 address), the IPv6 address MUST be enclosed in square bracket characters (i.e. Domain Literal format) llll:w.x.y.z:rrrr llll:name.domain.com:rrrr llll::rrrr rrrr w.x.y.z:rrrr [w.x.y.z]:rrrr name.domain.com:rrrr Inputs: cptr = pointer to input string default_host = optional pointer to default host if none specified host_len = length of host buffer default_port = optional pointer to default port if none specified port_len = length of port buffer Outputs: host = pointer to buffer for IP address (may be NULL), 0 = none port = pointer to buffer for IP port (may be NULL), 0 = none localport = pointer to buffer for local IP port (may be NULL), 0 = none result = status (SCPE_OK on complete success or SCPE_ARG if parsing can't happen due to bad syntax, a value is out of range, a result can't fit into a result buffer, a service name doesn't exist, or a validation name doesn't match the parsed host) */ int sim_parse_addr_ex (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, char *localport, size_t localport_len, const char *default_port) { const char *hostp; if ((localport != NULL) && (localport_len != 0)) memset (localport, 0, localport_len); hostp = strchr (cptr, ':'); if ((hostp != NULL) && ((hostp[1] == '[') || (NULL != strchr (hostp+1, ':')))) { if ((localport != NULL) && (localport_len != 0)) { localport_len -= 1; if (localport_len > (size_t)(hostp-cptr)) localport_len = (size_t)(hostp-cptr); memcpy (localport, cptr, localport_len); } return sim_parse_addr (hostp+1, host, hostlen, default_host, port, port_len, default_port, NULL); } return sim_parse_addr (cptr, host, hostlen, default_host, port, port_len, default_port, NULL); } void sim_init_sock (void) { #if defined (_WIN32) int err; WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD (2, 2); err = WSAStartup (wVersionRequested, &wsaData); /* start Winsock */ if (err != 0) sim_printf ("Winsock: startup error %d\n", err); #if defined(AF_INET6) load_ws2 (); #endif /* endif AF_INET6 */ #else /* Use native addrinfo APIs */ #if defined(AF_INET6) p_getaddrinfo = (getaddrinfo_func)getaddrinfo; p_getnameinfo = (getnameinfo_func)getnameinfo; p_freeaddrinfo = (freeaddrinfo_func)freeaddrinfo; #else /* Native APIs not available, connect stubs */ p_getaddrinfo = (getaddrinfo_func)s_getaddrinfo; p_getnameinfo = (getnameinfo_func)s_getnameinfo; p_freeaddrinfo = (freeaddrinfo_func)s_freeaddrinfo; #endif /* endif AF_INET6 */ #endif /* endif _WIN32 */ #if defined (SIGPIPE) signal (SIGPIPE, SIG_IGN); /* no pipe signals */ #endif } void sim_cleanup_sock (void) { #if defined (_WIN32) WSACleanup (); #endif } #if defined (_WIN32) /* Windows */ static int sim_setnonblock (SOCKET sock) { unsigned long non_block = 1; return ioctlsocket (sock, FIONBIO, &non_block); /* set nonblocking */ } #elif defined (VMS) /* VMS */ static int sim_setnonblock (SOCKET sock) { int non_block = 1; return ioctl (sock, FIONBIO, &non_block); /* set nonblocking */ } #else /* Mac, Unix, OS/2 */ static int sim_setnonblock (SOCKET sock) { int fl, sta; fl = fcntl (sock, F_GETFL,0); /* get flags */ if (fl == -1) return SOCKET_ERROR; sta = fcntl (sock, F_SETFL, fl | O_NONBLOCK); /* set nonblock */ if (sta == -1) return SOCKET_ERROR; #if !defined (macintosh) && !defined (__EMX__) && \ !defined (__HAIKU__) /* Unix only */ sta = fcntl (sock, F_SETOWN, getpid()); /* set ownership */ if (sta == -1) return SOCKET_ERROR; #endif return 0; } #endif /* endif !Win32 && !VMS */ static int sim_setnodelay (SOCKET sock) { int nodelay = 1; int sta; /* disable Nagle algorithm */ sta = setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); if (sta == -1) return SOCKET_ERROR; #if defined(TCP_NODELAYACK) /* disable delayed ack algorithm */ sta = setsockopt (sock, IPPROTO_TCP, TCP_NODELAYACK, (char *)&nodelay, sizeof(nodelay)); if (sta == -1) return SOCKET_ERROR; #endif #if defined(TCP_QUICKACK) /* disable delayed ack algorithm */ sta = setsockopt (sock, IPPROTO_TCP, TCP_QUICKACK, (char *)&nodelay, sizeof(nodelay)); if (sta == -1) return SOCKET_ERROR; #endif return sta; } static SOCKET sim_create_sock (int af, int opt_flags) { SOCKET newsock; int err; newsock = socket (af, ((opt_flags & SIM_SOCK_OPT_DATAGRAM) ? SOCK_DGRAM : SOCK_STREAM), 0);/* create socket */ if (newsock == INVALID_SOCKET) { /* socket error? */ err = WSAGetLastError (); #if defined(WSAEAFNOSUPPORT) if (err == WSAEAFNOSUPPORT) /* expected error, just return */ return newsock; #endif return sim_err_sock (newsock, "socket"); /* report error and return */ } return newsock; } /* Some platforms and/or network stacks have varying support for listening on an IPv6 socket and receiving connections from both IPv4 and IPv6 client connections. This is known as IPv4-Mapped. Some platforms claim such support (i.e. some Windows versions), but it doesn't work in all cases. */ SOCKET sim_master_sock_ex (const char *hostport, int *parse_status, int opt_flags) { SOCKET newsock = INVALID_SOCKET; int sta; char host[CBUFSIZE], port[CBUFSIZE]; int r; struct addrinfo hints; struct addrinfo *result = NULL, *preferred; r = sim_parse_addr (hostport, host, sizeof(host), NULL, port, sizeof(port), NULL, NULL); if (parse_status) *parse_status = r; if (r) return newsock; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC; hints.ai_protocol = IPPROTO_TCP; hints.ai_socktype = SOCK_STREAM; if (p_getaddrinfo(host[0] ? host : NULL, port[0] ? port : NULL, &hints, &result)) { if (parse_status) *parse_status = -1; return newsock; } preferred = result; #ifdef IPV6_V6ONLY /* When we can create a dual stack socket, be sure to find the IPv6 addrinfo to bind to. */ for (; preferred != NULL; preferred = preferred->ai_next) { if (preferred->ai_family == AF_INET6) break; } if (preferred == NULL) preferred = result; #endif retry: newsock = sim_create_sock (preferred->ai_family, 0); /* create socket */ if (newsock == INVALID_SOCKET) { /* socket error? */ #ifndef IPV6_V6ONLY if (preferred->ai_next) { preferred = preferred->ai_next; goto retry; } #else if ((preferred->ai_family == AF_INET6) && (preferred != result)) { preferred = result; goto retry; } #endif p_freeaddrinfo(result); return newsock; } #ifdef IPV6_V6ONLY if (preferred->ai_family == AF_INET6) { int off = 0; sta = setsockopt (newsock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&off, sizeof(off)); } #endif if (opt_flags & SIM_SOCK_OPT_REUSEADDR) { int on = 1; sta = setsockopt (newsock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); } #if defined (SO_EXCLUSIVEADDRUSE) else { int on = 1; sta = setsockopt (newsock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&on, sizeof(on)); } #endif sta = bind (newsock, preferred->ai_addr, preferred->ai_addrlen); p_freeaddrinfo(result); if (sta == SOCKET_ERROR) /* bind error? */ return sim_err_sock (newsock, "bind"); if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) { sta = sim_setnonblock (newsock); /* set nonblocking */ if (sta == SOCKET_ERROR) /* fcntl error? */ return sim_err_sock (newsock, "fcntl"); } sta = listen (newsock, 1); /* listen on socket */ if (sta == SOCKET_ERROR) /* listen error? */ return sim_err_sock (newsock, "listen"); return newsock; /* got it! */ } SOCKET sim_connect_sock_ex (const char *sourcehostport, const char *hostport, const char *default_host, const char *default_port, int opt_flags) { SOCKET newsock = INVALID_SOCKET; int sta; char host[CBUFSIZE], port[CBUFSIZE]; struct addrinfo hints; struct addrinfo *result = NULL, *source = NULL; if (sim_parse_addr (hostport, host, sizeof(host), default_host, port, sizeof(port), default_port, NULL)) return INVALID_SOCKET; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_protocol = ((opt_flags & SIM_SOCK_OPT_DATAGRAM) ? IPPROTO_UDP : IPPROTO_TCP); hints.ai_socktype = ((opt_flags & SIM_SOCK_OPT_DATAGRAM) ? SOCK_DGRAM : SOCK_STREAM); if (p_getaddrinfo(host[0] ? host : NULL, port[0] ? port : NULL, &hints, &result)) return INVALID_SOCKET; if (sourcehostport) { /* Validate the local/source side address which we'll bind to */ if (sim_parse_addr (sourcehostport, host, sizeof(host), NULL, port, sizeof(port), NULL, NULL)) { p_freeaddrinfo (result); return INVALID_SOCKET; } memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = result->ai_family; /* Same family as connect destination */ hints.ai_protocol = ((opt_flags & SIM_SOCK_OPT_DATAGRAM) ? IPPROTO_UDP : IPPROTO_TCP); hints.ai_socktype = ((opt_flags & SIM_SOCK_OPT_DATAGRAM) ? SOCK_DGRAM : SOCK_STREAM); if (p_getaddrinfo(host[0] ? host : NULL, port[0] ? port : NULL, &hints, &source)) { p_freeaddrinfo (result); return INVALID_SOCKET; } newsock = sim_create_sock (result->ai_family, opt_flags & SIM_SOCK_OPT_DATAGRAM);/* create socket */ if (newsock == INVALID_SOCKET) { /* socket error? */ p_freeaddrinfo (result); p_freeaddrinfo (source); return newsock; } sta = bind (newsock, source->ai_addr, source->ai_addrlen); p_freeaddrinfo(source); source = NULL; if (sta == SOCKET_ERROR) { /* bind error? */ p_freeaddrinfo (result); return sim_err_sock (newsock, "bind"); } } if (newsock == INVALID_SOCKET) { /* socket error? */ newsock = sim_create_sock (result->ai_family, opt_flags & SIM_SOCK_OPT_DATAGRAM);/* create socket */ if (newsock == INVALID_SOCKET) { /* socket error? */ p_freeaddrinfo (result); return newsock; } } if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) { sta = sim_setnonblock (newsock); /* set nonblocking */ if (sta == SOCKET_ERROR) { /* fcntl error? */ p_freeaddrinfo (result); return sim_err_sock (newsock, "fcntl"); } } if ((!(opt_flags & SIM_SOCK_OPT_DATAGRAM)) && (opt_flags & SIM_SOCK_OPT_NODELAY)) { sta = sim_setnodelay (newsock); /* set nodelay */ if (sta == SOCKET_ERROR) { /* setsock error? */ p_freeaddrinfo (result); return sim_err_sock (newsock, "setnodelay"); } } if (!(opt_flags & SIM_SOCK_OPT_DATAGRAM)) { int keepalive = 1; /* enable TCP Keep Alives */ sta = setsockopt (newsock, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive, sizeof(keepalive)); if (sta == -1) return sim_err_sock (newsock, "setsockopt KEEPALIVE"); } sta = connect (newsock, result->ai_addr, result->ai_addrlen); p_freeaddrinfo (result); if (sta == SOCKET_ERROR) { if (opt_flags & SIM_SOCK_OPT_BLOCKING) { if ((WSAGetLastError () == WSAETIMEDOUT) || /* expected errors after a connect failure */ (WSAGetLastError () == WSAEHOSTUNREACH) || (WSAGetLastError () == WSAECONNREFUSED) || (WSAGetLastError () == WSAECONNABORTED) || (WSAGetLastError () == WSAECONNRESET)) { sim_close_sock (newsock); newsock = INVALID_SOCKET; } else return sim_err_sock (newsock, "connect"); } else /* Non Blocking case won't return errors until some future read */ if ((WSAGetLastError () != WSAEWOULDBLOCK) && (WSAGetLastError () != WSAEINPROGRESS)) return sim_err_sock (newsock, "connect"); } return newsock; /* got it! */ } SOCKET sim_accept_conn_ex (SOCKET master, char **connectaddr, int opt_flags) { int sta = 0, err; int keepalive = 1; #if defined (macintosh) || defined (__linux) || defined (__linux__) || \ defined (__APPLE__) || defined (__OpenBSD__) || \ defined(__NetBSD__) || defined(__FreeBSD__) || \ (defined(__hpux) && defined(_XOPEN_SOURCE_EXTENDED)) || \ defined (__HAIKU__) socklen_t size; #elif defined (_WIN32) || defined (__EMX__) || \ (defined (__ALPHA) && defined (__unix__)) || \ defined (__hpux) int size; #else size_t size; #endif SOCKET newsock; struct sockaddr_storage clientname; if (master == 0) /* not attached? */ return INVALID_SOCKET; size = sizeof (clientname); memset (&clientname, 0, sizeof(clientname)); newsock = accept (master, (struct sockaddr *) &clientname, &size); if (newsock == INVALID_SOCKET) { /* error? */ err = WSAGetLastError (); if (err != WSAEWOULDBLOCK) sim_err_sock(newsock, "accept"); return INVALID_SOCKET; } if (connectaddr != NULL) { *connectaddr = (char *)calloc(1, NI_MAXHOST+1); #ifdef AF_INET6 p_getnameinfo((struct sockaddr *)&clientname, size, *connectaddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (0 == memcmp("::ffff:", *connectaddr, 7)) /* is this a IPv4-mapped IPv6 address? */ memmove(*connectaddr, 7+*connectaddr, /* prefer bare IPv4 address */ strlen(*connectaddr) - 7 + 1); /* length to include terminating \0 */ #else strcpy(*connectaddr, inet_ntoa(((struct sockaddr_in *)&connectaddr)->s_addr)); #endif } if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) { sta = sim_setnonblock (newsock); /* set nonblocking */ if (sta == SOCKET_ERROR) /* fcntl error? */ return sim_err_sock (newsock, "fcntl"); } if ((opt_flags & SIM_SOCK_OPT_NODELAY)) { sta = sim_setnodelay (newsock); /* set nonblocking */ if (sta == SOCKET_ERROR) /* setsockopt error? */ return sim_err_sock (newsock, "setnodelay"); } /* enable TCP Keep Alives */ sta = setsockopt (newsock, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive, sizeof(keepalive)); if (sta == -1) return sim_err_sock (newsock, "setsockopt KEEPALIVE"); return newsock; } int sim_check_conn (SOCKET sock, int rd) { fd_set rw_set, er_set; fd_set *rw_p = &rw_set; fd_set *er_p = &er_set; struct timeval zero; struct sockaddr_storage peername; #if defined (macintosh) || defined (__linux) || defined (__linux__) || \ defined (__APPLE__) || defined (__OpenBSD__) || \ defined(__NetBSD__) || defined(__FreeBSD__) || \ (defined(__hpux) && defined(_XOPEN_SOURCE_EXTENDED)) || \ defined (__HAIKU__) socklen_t peernamesize = (socklen_t)sizeof(peername); #elif defined (_WIN32) || defined (__EMX__) || \ (defined (__ALPHA) && defined (__unix__)) || \ defined (__hpux) int peernamesize = (int)sizeof(peername); #else size_t peernamesize = sizeof(peername); #endif memset (&zero, 0, sizeof(zero)); FD_ZERO (rw_p); FD_ZERO (er_p); FD_SET (sock, rw_p); FD_SET (sock, er_p); if (rd) (void)select ((int) sock + 1, rw_p, NULL, er_p, &zero); else (void)select ((int) sock + 1, NULL, rw_p, er_p, &zero); if (FD_ISSET (sock, er_p)) return -1; if (FD_ISSET (sock, rw_p)) { if (0 == getpeername (sock, (struct sockaddr *)&peername, &peernamesize)) return 1; else return -1; } return 0; } static int _sim_getaddrname (struct sockaddr *addr, size_t addrsize, char *hostnamebuf, char *portnamebuf) { #if defined (macintosh) || defined (__linux) || defined (__linux__) || \ defined (__APPLE__) || defined (__OpenBSD__) || \ defined(__NetBSD__) || defined(__FreeBSD__) || \ (defined(__hpux) && defined(_XOPEN_SOURCE_EXTENDED)) || \ defined (__HAIKU__) socklen_t size = (socklen_t)addrsize; #elif defined (_WIN32) || defined (__EMX__) || \ (defined (__ALPHA) && defined (__unix__)) || \ defined (__hpux) int size = (int)addrsize; #else size_t size = addrsize; #endif int ret = 0; #ifdef AF_INET6 *hostnamebuf = '\0'; *portnamebuf = '\0'; ret = p_getnameinfo(addr, size, hostnamebuf, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (0 == memcmp("::ffff:", hostnamebuf, 7)) /* is this a IPv4-mapped IPv6 address? */ memmove(hostnamebuf, 7+hostnamebuf, /* prefer bare IPv4 address */ strlen(hostnamebuf) + 7 - 1); /* length to include terminating \0 */ if (!ret) ret = p_getnameinfo(addr, size, NULL, 0, portnamebuf, NI_MAXSERV, NI_NUMERICSERV); #else strcpy(hostnamebuf, inet_ntoa(((struct sockaddr_in *)addr)->s_addr)); sprintf(portnamebuf, "%d", (int)ntohs(((struct sockaddr_in *)addr)->s_port))); #endif return ret; } int sim_getnames_sock (SOCKET sock, char **socknamebuf, char **peernamebuf) { struct sockaddr_storage sockname, peername; #if defined (macintosh) || defined (__linux) || defined (__linux__) || \ defined (__APPLE__) || defined (__OpenBSD__) || \ defined(__NetBSD__) || defined(__FreeBSD__) || \ (defined(__hpux) && defined(_XOPEN_SOURCE_EXTENDED)) || \ defined (__HAIKU__) socklen_t socknamesize = (socklen_t)sizeof(sockname); socklen_t peernamesize = (socklen_t)sizeof(peername); #elif defined (_WIN32) || defined (__EMX__) || \ (defined (__ALPHA) && defined (__unix__)) || \ defined (__hpux) int socknamesize = (int)sizeof(sockname); int peernamesize = (int)sizeof(peername); #else size_t socknamesize = sizeof(sockname); size_t peernamesize = sizeof(peername); #endif char hostbuf[NI_MAXHOST+1]; char portbuf[NI_MAXSERV+1]; if (socknamebuf) *socknamebuf = (char *)calloc(1, NI_MAXHOST+NI_MAXSERV+4); if (peernamebuf) *peernamebuf = (char *)calloc(1, NI_MAXHOST+NI_MAXSERV+4); (void)getsockname (sock, (struct sockaddr *)&sockname, &socknamesize); (void)getpeername (sock, (struct sockaddr *)&peername, &peernamesize); if (socknamebuf != NULL) { _sim_getaddrname ((struct sockaddr *)&sockname, (size_t)socknamesize, hostbuf, portbuf); sprintf(*socknamebuf, "[%s]:%s", hostbuf, portbuf); } if (peernamebuf != NULL) { _sim_getaddrname ((struct sockaddr *)&peername, (size_t)peernamesize, hostbuf, portbuf); sprintf(*peernamebuf, "[%s]:%s", hostbuf, portbuf); } return 0; } int sim_read_sock (SOCKET sock, char *buf, int nbytes) { int rbytes, err; rbytes = recv (sock, buf, nbytes, 0); if (rbytes == 0) /* disconnect */ return -1; if (rbytes == SOCKET_ERROR) { err = WSAGetLastError (); if (err == WSAEWOULDBLOCK) /* no data */ return 0; #if defined(EAGAIN) if (err == EAGAIN) /* no data */ return 0; #endif if ((err != WSAETIMEDOUT) && /* expected errors after a connect failure */ (err != WSAEHOSTUNREACH) && (err != WSAECONNREFUSED) && (err != WSAECONNABORTED) && (err != WSAECONNRESET) && (err != WSAEINTR)) /* or a close of a blocking read */ sim_err_sock (INVALID_SOCKET, "read"); return -1; } return rbytes; } int sim_write_sock (SOCKET sock, const char *msg, int nbytes) { int err, sbytes = send (sock, msg, nbytes, 0); if (sbytes == SOCKET_ERROR) { err = WSAGetLastError (); if (err == WSAEWOULDBLOCK) /* no data */ return 0; #if defined(EAGAIN) if (err == EAGAIN) /* no data */ return 0; #endif } return sbytes; } void sim_close_sock (SOCKET sock) { shutdown(sock, SD_BOTH); closesocket (sock); } #endif /* end else !implemented */ #ifdef __cplusplus } #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | /* sim_sock.h: OS-dependent socket routines header file Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 15-Oct-12 MP Added definitions needed to detect possible tcp connect failures 25-Sep-12 MP Reworked for RFC3493 interfaces supporting IPv6 and IPv4 04-Jun-08 RMS Addes sim_create_sock, for IBM 1130 14-Apr-05 RMS Added WSAEINPROGRESS (from Tim Riker) 20-Aug-04 HV Added missing definition for OS/2 (from Holger Veit) 22-Oct-03 MP Changed WIN32 winsock include to use winsock2.h to avoid a conflict if sim_sock.h and sim_ether.h get included by the same module. 20-Mar-03 RMS Added missing timerclear definition for VMS (from Robert Alan Byer) 15-Feb-03 RMS Added time.h for EMX (from Holger Veit) 17-Dec-02 RMS Added sim_connect_sock 08-Oct-02 RMS Revised for .NET compatibility 20-Aug-02 RMS Changed calling sequence for sim_accept_conn 30-Apr-02 RMS Changed VMS stropts include to ioctl 06-Feb-02 RMS Added VMS support from Robert Alan Byer 16-Sep-01 RMS Added Macintosh support from Peter Schorn */ #ifndef SIM_SOCK_H_ #define SIM_SOCK_H_ 0 #ifdef __cplusplus extern "C" { #endif #if defined (_WIN32) /* Windows */ #include <winsock2.h> #elif !defined (__OS2__) || defined (__EMX__) /* VMS, Mac, Unix, OS/2 EMX */ #include <sys/types.h> /* for fcntl, getpid */ #include <sys/socket.h> /* for sockets */ #include <string.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #include <netinet/in.h> /* for sockaddr_in */ #include <netinet/tcp.h> /* for TCP_NODELAY */ #include <arpa/inet.h> /* for inet_addr and inet_ntoa */ #include <netdb.h> #include <sys/time.h> /* for EMX */ #define WSAGetLastError() errno /* Windows macros */ #define WSASetLastError(err) errno = err #define closesocket close #define SOCKET int #if defined(__hpux) #define WSAEWOULDBLOCK EAGAIN #else #define WSAEWOULDBLOCK EWOULDBLOCK #endif #define WSAENAMETOOLONG ENAMETOOLONG #define WSAEINPROGRESS EINPROGRESS #define WSAETIMEDOUT ETIMEDOUT #define WSAEISCONN EISCONN #define WSAECONNRESET ECONNRESET #define WSAECONNREFUSED ECONNREFUSED #define WSAECONNABORTED ECONNABORTED #define WSAEHOSTUNREACH EHOSTUNREACH #define WSAEADDRINUSE EADDRINUSE #if defined(EAFNOSUPPORT) #define WSAEAFNOSUPPORT EAFNOSUPPORT #endif #define WSAEACCES EACCES #define WSAEINTR EINTR #define INVALID_SOCKET ((SOCKET)-1) #define SOCKET_ERROR -1 #endif #if defined (VMS) /* VMS unique */ #include <ioctl.h> /* for ioctl */ #if !defined (AI_NUMERICHOST) #define AI_NUMERICHOST 0 #endif #if defined (__VAX) #define sockaddr_storage sockaddr #endif #endif #if !defined(CBUFSIZE) #define CBUFSIZE 1024 #define sim_printf printf #endif int sim_parse_addr (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, const char *default_port, const char *validate_addr); int sim_parse_addr_ex (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, char *localport, size_t local_port_len, const char *default_port); #define SIM_SOCK_OPT_REUSEADDR 0x0001 #define SIM_SOCK_OPT_DATAGRAM 0x0002 #define SIM_SOCK_OPT_NODELAY 0x0004 #define SIM_SOCK_OPT_BLOCKING 0x0008 SOCKET sim_master_sock_ex (const char *hostport, int *parse_status, int opt_flags); #define sim_master_sock(hostport, parse_status) sim_master_sock_ex(hostport, parse_status, ((sim_switches & SWMASK ('U')) ? SIM_SOCK_OPT_REUSEADDR : 0)) SOCKET sim_connect_sock_ex (const char *sourcehostport, const char *hostport, const char *default_host, const char *default_port, int opt_flags); #define sim_connect_sock(hostport, default_host, default_port) sim_connect_sock_ex(NULL, hostport, default_host, default_port, 0) SOCKET sim_accept_conn_ex (SOCKET master, char **connectaddr, int opt_flags); #define sim_accept_conn(master, connectaddr) sim_accept_conn_ex(master, connectaddr, 0) int sim_check_conn (SOCKET sock, int rd); int sim_read_sock (SOCKET sock, char *buf, int nbytes); int sim_write_sock (SOCKET sock, const char *msg, int nbytes); void sim_close_sock (SOCKET sock); const char *sim_get_err_sock (const char *emsg); SOCKET sim_err_sock (SOCKET sock, const char *emsg); int sim_getnames_sock (SOCKET sock, char **socknamebuf, char **peernamebuf); void sim_init_sock (void); void sim_cleanup_sock (void); #ifdef __cplusplus } #endif #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 | /* sim_tape.c: simulator tape support library Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. Ultimately, this will be a place to hide processing of various tape formats, as well as OS-specific direct hardware access. 23-Jan-12 MP Added support for Logical EOT detection while positioning 05-Feb-11 MP Refactored to prepare for SIM_ASYNC_IO support Added higher level routines: sim_tape_wreomrw - erase remainder of tape & rewind sim_tape_sprecsf - skip records sim_tape_spfilef - skip files sim_tape_sprecsr - skip records rev sim_tape_spfiler - skip files rev sim_tape_position - general purpose position These routines correspond to natural tape operations and will align better when physical tape support is included here. 08-Jun-08 JDB Fixed signed/unsigned warning in sim_tape_set_fmt 23-Jan-07 JDB Fixed backspace over gap at BOT 22-Jan-07 RMS Fixed bug in P7B format read reclnt rev (found by Rich Cornwell) 15-Dec-06 RMS Added support for small capacity tapes 30-Aug-06 JDB Added erase gap support 14-Feb-06 RMS Added variable tape capacity 23-Jan-06 JDB Fixed odd-byte-write problem in sim_tape_wrrecf 17-Dec-05 RMS Added write support for Paul Pierce 7b format 16-Aug-05 RMS Fixed C++ declaration and cast problems 02-May-05 RMS Added support for Pierce 7b format 28-Jul-04 RMS Fixed bug in writing error records (found by Dave Bryan) RMS Fixed incorrect error codes (found by Dave Bryan) 05-Jan-04 RMS Revised for file I/O library 25-Apr-03 RMS Added extended file support 28-Mar-03 RMS Added E11 and TPC format support Public routines: sim_tape_attach attach tape unit sim_tape_detach detach tape unit sim_tape_attach_help help routine for attaching tapes sim_tape_rdrecf read tape record forward sim_tape_rdrecr read tape record reverse sim_tape_wrrecf write tape record forward sim_tape_sprecf space tape record forward sim_tape_sprecr space tape record reverse sim_tape_wrtmk write tape mark sim_tape_wreom erase remainder of tape sim_tape_wreomrw erase remainder of tape & rewind sim_tape_wrgap write erase gap sim_tape_sprecsf space records forward sim_tape_spfilef space files forward sim_tape_sprecsr space records reverse sim_tape_spfiler space files reverse sim_tape_position generalized position sim_tape_rewind rewind sim_tape_reset reset unit sim_tape_bot TRUE if at beginning of tape sim_tape_eot TRUE if at or beyond end of tape sim_tape_wrp TRUE if write protected sim_tape_set_fmt set tape format sim_tape_show_fmt show tape format sim_tape_set_capac set tape capacity sim_tape_show_capac show tape capacity sim_tape_set_dens set tape density sim_tape_show_dens show tape density sim_tape_set_async enable asynchronous operation sim_tape_clr_async disable asynchronous operation */ #include "sim_defs.h" #include "sim_tape.h" #include <ctype.h> #if defined SIM_ASYNCH_IO #include <pthread.h> #endif struct sim_tape_fmt { const char *name; /* name */ int32 uflags; /* unit flags */ t_addr bot; /* bot test */ }; static struct sim_tape_fmt fmts[MTUF_N_FMT] = { { "SIMH", 0, sizeof (t_mtrlnt) - 1 }, { "E11", 0, sizeof (t_mtrlnt) - 1 }, { "TPC", UNIT_RO, sizeof (t_tpclnt) - 1 }, { "P7B", 0, 0 }, /* { "TPF", UNIT_RO, 0 }, */ { NULL, 0, 0 } }; static const uint32 bpi [] = { /* tape density table, indexed by MT_DENS constants */ 0, /* 0 = MT_DENS_NONE -- density not set */ 200, /* 1 = MT_DENS_200 -- 200 bpi NRZI */ 556, /* 2 = MT_DENS_556 -- 556 bpi NRZI */ 800, /* 3 = MT_DENS_800 -- 800 bpi NRZI */ 1600, /* 4 = MT_DENS_1600 -- 1600 bpi PE */ 6250 /* 5 = MT_DENS_6250 -- 6250 bpi GCR */ }; #define BPI_COUNT (sizeof (bpi) / sizeof (bpi [0])) /* count of density table entries */ static t_stat sim_tape_ioerr (UNIT *uptr); static t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat); static uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map, uint32 mapsize); static t_stat sim_tape_simh_check (UNIT *uptr); static t_stat sim_tape_e11_check (UNIT *uptr); static t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map); static void sim_tape_data_trace (UNIT *uptr, const uint8 *data, size_t len, const char* txt, int detail, uint32 reason); static t_stat tape_erase_fwd (UNIT *uptr, t_mtrlnt gap_size); static t_stat tape_erase_rev (UNIT *uptr, t_mtrlnt gap_size); struct tape_context { DEVICE *dptr; /* Device for unit (access to debug flags) */ uint32 dbit; /* debugging bit for trace */ uint32 auto_format; /* Format determined dynamically */ #if defined SIM_ASYNCH_IO int asynch_io; /* Asynchronous Interrupt scheduling enabled */ int asynch_io_latency; /* instructions to delay pending interrupt */ pthread_mutex_t lock; pthread_t io_thread; /* I/O Thread Id */ pthread_mutex_t io_lock; pthread_cond_t io_cond; pthread_cond_t io_done; pthread_cond_t startup_cond; int io_top; uint8 *buf; uint32 *bc; uint32 *fc; uint32 vbc; uint32 max; uint32 gaplen; uint32 bpi; uint32 *objupdate; TAPE_PCALLBACK callback; t_stat io_status; #endif }; #define tape_ctx up8 /* Field in Unit structure which points to the tape_context */ #if defined SIM_ASYNCH_IO #define AIO_CALLSETUP \ struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; \ \ if (ctx == NULL) \ return sim_messagef (SCPE_IERR, "Bad Attach\n"); \ if ((!callback) || !ctx->asynch_io) #define AIO_CALL(op, _buf, _bc, _fc, _max, _vbc, _gaplen, _bpi, _obj, _callback)\ if (ctx->asynch_io) { \ struct tape_context *ctx = \ (struct tape_context *)uptr->tape_ctx; \ \ pthread_mutex_lock (&ctx->io_lock); \ \ sim_debug (ctx->dbit, ctx->dptr, \ "sim_tape AIO_CALL(op=%d, unit=%d)\n", op, (int)(uptr-ctx->dptr->units));\ \ if (ctx->callback) \ abort(); /* horrible mistake, stop */ \ ctx->io_top = op; \ ctx->buf = _buf; \ ctx->bc = _bc; \ ctx->fc = _fc; \ ctx->max = _max; \ ctx->vbc = _vbc; \ ctx->gaplen = _gaplen; \ ctx->bpi = _bpi; \ ctx->objupdate = _obj; \ ctx->callback = _callback; \ pthread_cond_signal (&ctx->io_cond); \ pthread_mutex_unlock (&ctx->io_lock); \ } \ else \ if (_callback) \ (_callback) (uptr, r); #define TOP_DONE 0 /* close */ #define TOP_RDRF 1 /* sim_tape_rdrecf_a */ #define TOP_RDRR 2 /* sim_tape_rdrecr_a */ #define TOP_WREC 3 /* sim_tape_wrrecf_a */ #define TOP_WTMK 4 /* sim_tape_wrtmk_a */ #define TOP_WEOM 5 /* sim_tape_wreom_a */ #define TOP_WEMR 6 /* sim_tape_wreomrw_a */ #define TOP_WGAP 7 /* sim_tape_wrgap_a */ #define TOP_SPRF 8 /* sim_tape_sprecf_a */ #define TOP_SRSF 9 /* sim_tape_sprecsf_a */ #define TOP_SPRR 10 /* sim_tape_sprecr_a */ #define TOP_SRSR 11 /* sim_tape_sprecsr_a */ #define TOP_SPFF 12 /* sim_tape_spfilef */ #define TOP_SFRF 13 /* sim_tape_spfilebyrecf */ #define TOP_SPFR 14 /* sim_tape_spfiler */ #define TOP_SFRR 15 /* sim_tape_spfilebyrecr */ #define TOP_RWND 16 /* sim_tape_rewind_a */ #define TOP_POSN 17 /* sim_tape_position_a */ static void * _tape_io(void *arg) { UNIT* volatile uptr = (UNIT*)arg; struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; /* Boost Priority for this I/O thread vs the CPU instruction execution thread which in general won't be readily yielding the processor when this thread needs to run */ sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); sim_debug (ctx->dbit, ctx->dptr, "_tape_io(unit=%d) starting\n", (int)(uptr-ctx->dptr->units)); pthread_mutex_lock (&ctx->io_lock); pthread_cond_signal (&ctx->startup_cond); /* Signal we're ready to go */ while (1) { pthread_cond_wait (&ctx->io_cond, &ctx->io_lock); if (ctx->io_top == TOP_DONE) break; pthread_mutex_unlock (&ctx->io_lock); switch (ctx->io_top) { case TOP_RDRF: ctx->io_status = sim_tape_rdrecf (uptr, ctx->buf, ctx->bc, ctx->max); break; case TOP_RDRR: ctx->io_status = sim_tape_rdrecr (uptr, ctx->buf, ctx->bc, ctx->max); break; case TOP_WREC: ctx->io_status = sim_tape_wrrecf (uptr, ctx->buf, ctx->vbc); break; case TOP_WTMK: ctx->io_status = sim_tape_wrtmk (uptr); break; case TOP_WEOM: ctx->io_status = sim_tape_wreom (uptr); break; case TOP_WEMR: ctx->io_status = sim_tape_wreomrw (uptr); break; case TOP_WGAP: ctx->io_status = sim_tape_wrgap (uptr, ctx->gaplen); break; case TOP_SPRF: ctx->io_status = sim_tape_sprecf (uptr, ctx->bc); break; case TOP_SRSF: ctx->io_status = sim_tape_sprecsf (uptr, ctx->vbc, ctx->bc); break; case TOP_SPRR: ctx->io_status = sim_tape_sprecr (uptr, ctx->bc); break; case TOP_SRSR: ctx->io_status = sim_tape_sprecsr (uptr, ctx->vbc, ctx->bc); break; case TOP_SPFF: ctx->io_status = sim_tape_spfilef (uptr, ctx->vbc, ctx->bc); break; case TOP_SFRF: ctx->io_status = sim_tape_spfilebyrecf (uptr, ctx->vbc, ctx->bc, ctx->fc, ctx->max); break; case TOP_SPFR: ctx->io_status = sim_tape_spfiler (uptr, ctx->vbc, ctx->bc); break; case TOP_SFRR: ctx->io_status = sim_tape_spfilebyrecr (uptr, ctx->vbc, ctx->bc, ctx->fc); break; case TOP_RWND: ctx->io_status = sim_tape_rewind (uptr); break; case TOP_POSN: ctx->io_status = sim_tape_position (uptr, ctx->vbc, ctx->gaplen, ctx->bc, ctx->bpi, ctx->fc, ctx->objupdate); break; } pthread_mutex_lock (&ctx->io_lock); ctx->io_top = TOP_DONE; pthread_cond_signal (&ctx->io_done); sim_activate (uptr, ctx->asynch_io_latency); } pthread_mutex_unlock (&ctx->io_lock); sim_debug (ctx->dbit, ctx->dptr, "_tape_io(unit=%d) exiting\n", (int)(uptr-ctx->dptr->units)); return NULL; } /* This routine is called in the context of the main simulator thread before processing events for any unit. It is only called when an asynchronous thread has called sim_activate() to activate a unit. The job of this routine is to put the unit in proper condition to digest what may have occurred in the asynchronous thread. Since tape processing only handles a single I/O at a time to a particular tape device, we have the opportunity to possibly detect improper attempts to issue multiple concurrent I/O requests. */ static void _tape_completion_dispatch (UNIT *uptr) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; TAPE_PCALLBACK callback = ctx->callback; sim_debug (ctx->dbit, ctx->dptr, "_tape_completion_dispatch(unit=%d, top=%d, callback=%p)\n", (int)(uptr-ctx->dptr->units), ctx->io_top, ctx->callback); if (ctx->io_top != TOP_DONE) abort(); /* horribly wrong, stop */ if (ctx->callback && ctx->io_top == TOP_DONE) { ctx->callback = NULL; callback (uptr, ctx->io_status); } } static t_bool _tape_is_active (UNIT *uptr) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; if (ctx) { sim_debug (ctx->dbit, ctx->dptr, "_tape_is_active(unit=%d, top=%d)\n", (int)(uptr-ctx->dptr->units), ctx->io_top); return (ctx->io_top != TOP_DONE); } return FALSE; } static t_bool _tape_cancel (UNIT *uptr) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; if (ctx) { sim_debug (ctx->dbit, ctx->dptr, "_tape_cancel(unit=%d, top=%d)\n", (int)(uptr-ctx->dptr->units), ctx->io_top); if (ctx->asynch_io) { pthread_mutex_lock (&ctx->io_lock); while (ctx->io_top != TOP_DONE) pthread_cond_wait (&ctx->io_done, &ctx->io_lock); pthread_mutex_unlock (&ctx->io_lock); } } return FALSE; } #else #define AIO_CALLSETUP \ if (uptr->tape_ctx == NULL) \ return sim_messagef (SCPE_IERR, "Bad Attach\n"); #define AIO_CALL(op, _buf, _fc, _bc, _max, _vbc, _gaplen, _bpi, _obj, _callback) \ if (_callback) \ (_callback) (uptr, r); #endif /* Enable asynchronous operation */ t_stat sim_tape_set_async (UNIT *uptr, int latency) { #if !defined(SIM_ASYNCH_IO) sim_printf ("Tape: can't operate asynchronously\r\n"); return SCPE_NOFNC; #else struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; pthread_attr_t attr; ctx->asynch_io = sim_asynch_enabled; ctx->asynch_io_latency = latency; if (ctx->asynch_io) { pthread_mutex_init (&ctx->io_lock, NULL); pthread_cond_init (&ctx->io_cond, NULL); pthread_cond_init (&ctx->io_done, NULL); pthread_cond_init (&ctx->startup_cond, NULL); pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); pthread_mutex_lock (&ctx->io_lock); pthread_create (&ctx->io_thread, &attr, _tape_io, (void *)uptr); pthread_attr_destroy(&attr); pthread_cond_wait (&ctx->startup_cond, &ctx->io_lock); /* Wait for thread to stabilize */ pthread_mutex_unlock (&ctx->io_lock); pthread_cond_destroy (&ctx->startup_cond); } uptr->a_check_completion = _tape_completion_dispatch; uptr->a_is_active = _tape_is_active; uptr->cancel = _tape_cancel; return SCPE_OK; #endif } /* Disable asynchronous operation */ t_stat sim_tape_clr_async (UNIT *uptr) { #if !defined(SIM_ASYNCH_IO) return SCPE_NOFNC; #else struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; /* make sure device exists */ if (!ctx) return SCPE_UNATT; if (ctx->asynch_io) { pthread_mutex_lock (&ctx->io_lock); ctx->asynch_io = 0; pthread_cond_signal (&ctx->io_cond); pthread_mutex_unlock (&ctx->io_lock); pthread_join (ctx->io_thread, NULL); pthread_mutex_destroy (&ctx->io_lock); pthread_cond_destroy (&ctx->io_cond); pthread_cond_destroy (&ctx->io_done); } return SCPE_OK; #endif } /* This routine is called when the simulator stops and any time the asynch mode is changed (enabled or disabled) */ static void _sim_tape_io_flush (UNIT *uptr) { #if defined (SIM_ASYNCH_IO) struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; sim_tape_clr_async (uptr); if (sim_asynch_enabled) sim_tape_set_async (uptr, ctx->asynch_io_latency); #endif fflush (uptr->fileref); } /* Attach tape unit */ t_stat sim_tape_attach (UNIT *uptr, CONST char *cptr) { DEVICE *dptr; if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_NOATT; return sim_tape_attach_ex (uptr, cptr, (dptr->flags & DEV_DEBUG) ? 0xFFFFFFFF : 0, 0); } t_stat sim_tape_attach_ex (UNIT *uptr, const char *cptr, uint32 dbit, int completion_delay) { struct tape_context *ctx; uint32 objc; DEVICE *dptr; char gbuf[CBUFSIZE]; t_stat r; t_bool auto_format = FALSE; if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_NOATT; if (sim_switches & SWMASK ('F')) { /* format spec? */ cptr = get_glyph (cptr, gbuf, 0); /* get spec */ if (*cptr == 0) /* must be more */ return SCPE_2FARG; if (sim_tape_set_fmt (uptr, 0, gbuf, NULL) != SCPE_OK) return sim_messagef (SCPE_ARG, "Invalid Tape Format: %s\n", gbuf); sim_switches = sim_switches & ~(SWMASK ('F')); /* Record Format specifier already processed */ auto_format = TRUE; } if (MT_GET_FMT (uptr) == MTUF_F_TPC) sim_switches |= SWMASK ('R'); /* Force ReadOnly attach for TPC tapes */ r = attach_unit (uptr, (CONST char *)cptr); /* attach unit */ if (r != SCPE_OK) /* error? */ return sim_messagef (r, "Can't open tape image: %s\n", cptr); switch (MT_GET_FMT (uptr)) { /* case on format */ case MTUF_F_STD: /* SIMH */ if (SCPE_OK != sim_tape_simh_check (uptr)) { sim_tape_detach (uptr); return SCPE_FMT; /* yes, complain */ } break; case MTUF_F_E11: /* E11 */ if (SCPE_OK != sim_tape_e11_check (uptr)) { sim_tape_detach (uptr); return SCPE_FMT; /* yes, complain */ } break; case MTUF_F_TPC: /* TPC */ objc = sim_tape_tpc_map (uptr, NULL, 0); /* get # objects */ if (objc == 0) { /* tape empty? */ sim_tape_detach (uptr); return SCPE_FMT; /* yes, complain */ } uptr->filebuf = calloc (objc + 1, sizeof (t_addr)); if (uptr->filebuf == NULL) { /* map allocated? */ sim_tape_detach (uptr); return SCPE_MEM; /* no, complain */ } uptr->hwmark = objc + 1; /* save map size */ sim_tape_tpc_map (uptr, (t_addr *) uptr->filebuf, objc);/* fill map */ break; default: break; } uptr->tape_ctx = ctx = (struct tape_context *)calloc(1, sizeof(struct tape_context)); ctx->dptr = dptr; /* save DEVICE pointer */ ctx->dbit = dbit; /* save debug bit */ ctx->auto_format = auto_format; /* save that we auto selected format */ sim_tape_rewind (uptr); #if defined (SIM_ASYNCH_IO) sim_tape_set_async (uptr, completion_delay); #endif uptr->io_flush = _sim_tape_io_flush; return SCPE_OK; } /* Detach tape unit */ t_stat sim_tape_detach (UNIT *uptr) { struct tape_context *ctx; uint32 f; t_stat r; t_bool auto_format = FALSE; if (uptr == NULL) return SCPE_IERR; ctx = (struct tape_context *)uptr->tape_ctx; f = MT_GET_FMT (uptr); if ((ctx == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_IERR; if (uptr->io_flush) uptr->io_flush (uptr); /* flush buffered data */ if (ctx) auto_format = ctx->auto_format; sim_tape_clr_async (uptr); r = detach_unit (uptr); /* detach unit */ if (r != SCPE_OK) return r; switch (f) { /* case on format */ case MTUF_F_TPC: /* TPC */ if (uptr->filebuf) /* free map */ free (uptr->filebuf); uptr->filebuf = NULL; uptr->hwmark = 0; break; default: break; } sim_tape_rewind (uptr); free (uptr->tape_ctx); uptr->tape_ctx = NULL; uptr->io_flush = NULL; if (auto_format) /* format was determined or specified at attach time? */ sim_tape_set_fmt (uptr, 0, "SIMH", NULL); /* restore default format */ return SCPE_OK; } t_stat sim_tape_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { fprintf (st, "%s Tape Attach Help\n\n", dptr->name); if (0 == (uptr-dptr->units)) { if (dptr->numunits > 1) { uint32 i; for (i=0; i < dptr->numunits; ++i) if (dptr->units[i].flags & UNIT_ATTABLE) fprintf (st, " sim> ATTACH {switches} %s%d tapefile\n\n", dptr->name, i); } else fprintf (st, " sim> ATTACH {switches} %s tapefile\n\n", dptr->name); } else fprintf (st, " sim> ATTACH {switches} %s tapefile\n\n", dptr->name); fprintf (st, "Attach command switches\n"); fprintf (st, " -R Attach Read Only.\n"); fprintf (st, " -E Must Exist (if not specified an attempt to create the indicated\n"); fprintf (st, " virtual tape will be attempted).\n"); fprintf (st, " -F Open the indicated tape container in a specific format (default\n"); fprintf (st, " is SIMH, alternatives are E11, TPC and P7B)\n"); return SCPE_OK; } static void sim_tape_data_trace(UNIT *uptr, const uint8 *data, size_t len, const char* txt, int detail, uint32 reason) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; if (ctx == NULL) return; if (sim_deb && (ctx->dptr->dctrl & reason)) sim_data_trace(ctx->dptr, uptr, (detail ? data : NULL), "", len, txt, reason); } /* Read record length forward (internal routine) Inputs: uptr = pointer to tape unit bc = pointer to returned record length Outputs: status = operation status exit condition tape position ------------------ ----------------------------------------------------- unit unattached unchanged read error unchanged, PNU set end of file/medium updated if a gap precedes, else unchanged and PNU set tape mark updated tape runaway updated data record updated, sim_fread will read record forward This routine is called to set up a record read or spacing in the forward direction. On return, status is MTSE_OK and the tape is positioned at the first data byte if a record was encountered, or status is an MTSE error code giving the reason that the operation did not succeed and the tape position is as indicated above. The ANSI standards for magnetic tape recording (X3.32, X3.39, and X3.54) and the equivalent ECMA standard (ECMA-62) specify a maximum erase gap length of 25 feet (7.6 meters). While gaps of any length may be written, gaps longer than this are non-standard and may indicate that an unrecorded or erased tape is being read. If the tape density has been set via a previous "sim_tape_set_dens" call, then the length is monitored when skipping over erase gaps. If the length reaches 25 feet, motion is terminated, and MTSE_RUNAWAY status is returned. Runaway status is also returned if an end-of-medium marker or the physical end of file is encountered while spacing over a gap; however, MTSE_EOM is returned if the tape is positioned at the EOM on entry. If the density has not been set, then a gap of any length is skipped, and MTSE_RUNAWAY status is never returned. In effect, erase gaps present in the tape image file will be transparent to the caller. Erase gaps are currently supported only in SIMH (MTUF_F_STD) tape format. Because gaps may be partially overwritten with data records, gap metadata must be examined marker-by-marker. To reduce the number of file read calls, a buffer of metadata elements is used. The buffer size is initially established at 256 elements but may be set to any size desired. To avoid a large read for the typical case where an erase gap is not present, the first read is of a single metadatum marker. If that is a gap marker, then additional buffered reads are performed. See the notes at "sim_tape_wrgap" regarding the erase gap implementation. Implementation notes: 1. For programming convenience, erase gap processing is performed for both SIMH standard and E11 tape formats, although the latter will never contain erase gaps, as the "sim_tape_wrgap" call takes no action for the E11 format. 2. The "feof" call cannot return a non-zero value on the first pass through the loop, because the "sim_fseek" call resets the internal end-of-file indicator. Subsequent passes only occur if an erase gap is present, so a non-zero return indicates an EOF was seen while reading through a gap. 3. The dynamic start/stop test of the HP 3000 magnetic tape diagnostic heavily exercises the erase gap scanning code. Sample test execution times for various buffer sizes on a 2 GHz host platform are: buffer size execution time (elements) (CPU seconds) ----------- -------------- 1 7200 32 783 128 237 256 203 512 186 1024 171 4. Because an erase gap may precede the logical end-of-medium, represented either by the physical end-of-file or by an EOM marker, the "position not updated" flag is set only if the tape is positioned at the EOM when the routine is entered. If at least one gap marker precedes the EOM, then the PNU flag is not set. This ensures that a backspace-and-retry sequence will work correctly in both cases. */ static t_stat sim_tape_rdlntf (UNIT *uptr, t_mtrlnt *bc) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; uint8 c; t_bool all_eof; uint32 f = MT_GET_FMT (uptr); t_mtrlnt sbc; t_tpclnt tpcbc; t_mtrlnt buffer [256]; /* local tape buffer */ uint32 bufcntr, bufcap; /* buffer counter and capacity */ int32 runaway_counter, sizeof_gap; /* bytes remaining before runaway and bytes per gap */ t_stat r = MTSE_OK; MT_CLR_PNU (uptr); /* clear the position-not-updated flag */ if ((uptr->flags & UNIT_ATT) == 0) /* if the unit is not attached */ return MTSE_UNATT; /* then quit with an error */ if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set the initial tape position */ switch (f) { /* the read method depends on the tape format */ case MTUF_F_STD: case MTUF_F_E11: runaway_counter = 25 * 12 * bpi [MT_DENS (uptr->dynflags)]; /* set the largest legal gap size in bytes */ if (runaway_counter == 0) { /* if tape density has not been not set */ sizeof_gap = 0; /* then disable runaway detection */ runaway_counter = INT_MAX; /* to allow gaps of any size */ } else /* otherwise */ sizeof_gap = sizeof (t_mtrlnt); /* set the size of the gap */ bufcntr = 0; /* force an initial read */ bufcap = 0; /* but of just one metadata marker */ do { /* loop until a record, gap, or error is seen */ if (bufcntr == bufcap) { /* if the buffer is empty then refill it */ if (feof (uptr->fileref)) { /* if we hit the EOF while reading a gap */ if (sizeof_gap > 0) /* then if detection is enabled */ r = MTSE_RUNAWAY; /* then report a tape runaway */ else /* otherwise report the physical EOF */ r = MTSE_EOM; /* as the end-of-medium */ break; } else if (bufcap == 0) /* otherwise if this is the initial read */ bufcap = 1; /* then start with just one marker */ else /* otherwise reset the capacity */ bufcap = sizeof (buffer) /* to the full size of the buffer */ / sizeof (buffer [0]); bufcap = sim_fread (buffer, /* fill the buffer */ sizeof (t_mtrlnt), /* with tape metadata */ bufcap, uptr->fileref); if (ferror (uptr->fileref)) { /* if a file I/O error occurred */ if (bufcntr == 0) /* then if this is the initial read */ MT_SET_PNU (uptr); /* then set position not updated */ r = sim_tape_ioerr (uptr); /* report the error and quit */ break; } else if (bufcap == 0 /* otherwise if positioned at the physical EOF */ || buffer [0] == MTR_EOM) /* or at the logical EOM */ if (bufcntr == 0) { /* then if this is the initial read */ MT_SET_PNU (uptr); /* then set position not updated */ r = MTSE_EOM; /* and report the end-of-medium and quit */ break; } else { /* otherwise some gap has already been skipped */ if (sizeof_gap > 0) /* so if detection is enabled */ r = MTSE_RUNAWAY; /* then report a tape runaway */ else /* otherwise report the physical EOF */ r = MTSE_EOM; /* as the end-of-medium */ break; } else /* otherwise reset the index */ bufcntr = 0; /* to the start of the buffer */ } *bc = buffer [bufcntr++]; /* store the metadata marker value */ if (*bc == MTR_EOM) { /* if an end-of-medium marker is seen */ if (sizeof_gap > 0) /* then if detection is enabled */ r = MTSE_RUNAWAY; /* then report a tape runaway */ else /* otherwise report the physical EOF */ r = MTSE_EOM; /* as the end-of-medium */ break; } uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* space over the marker */ if (*bc == MTR_TMK) { /* if the value is a tape mark */ r = MTSE_TMK; /* then quit with tape mark status */ break; } else if (*bc == MTR_GAP) /* otherwise if the value is a full gap */ runaway_counter -= sizeof_gap; /* then decrement the gap counter */ else if (*bc == MTR_FHGAP) { /* otherwise if the value if a half gap */ uptr->pos = uptr->pos - sizeof (t_mtrlnt) / 2; /* then back up */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* to resync */ bufcntr = bufcap; /* mark the buffer as invalid to force a read */ *bc = MTR_GAP; /* reset the marker */ runaway_counter -= sizeof_gap / 2; /* and decrement the gap counter */ } else { /* otherwise it's a record marker */ if (bufcntr < bufcap) /* if the position is within the buffer */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* then seek to the data area */ sbc = MTR_L (*bc); /* extract the record length */ uptr->pos = uptr->pos + sizeof (t_mtrlnt) /* position to the start */ + (f == MTUF_F_STD ? (sbc + 1) & ~1 : sbc); /* of the record */ } } while (*bc == MTR_GAP && runaway_counter > 0); /* continue until data or runaway occurs */ if (r == MTSE_OK && runaway_counter <= 0) /* if a tape runaway occurred */ r = MTSE_RUNAWAY; /* then report it */ break; /* otherwise the operation succeeded */ case MTUF_F_TPC: sim_fread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref); *bc = tpcbc; /* save rec lnt */ if (ferror (uptr->fileref)) { /* error? */ MT_SET_PNU (uptr); /* pos not upd */ return sim_tape_ioerr (uptr); } if (feof (uptr->fileref)) { /* eof? */ MT_SET_PNU (uptr); /* pos not upd */ r = MTSE_EOM; break; } uptr->pos = uptr->pos + sizeof (t_tpclnt); /* spc over reclnt */ if (tpcbc == TPC_TMK) /* tape mark? */ r = MTSE_TMK; uptr->pos = uptr->pos + ((tpcbc + 1) & ~1); /* spc over record */ break; case MTUF_F_P7B: for (sbc = 0, all_eof = 1; ; sbc++) { /* loop thru record */ sim_fread (&c, sizeof (uint8), 1, uptr->fileref); if (ferror (uptr->fileref)) { /* error? */ MT_SET_PNU (uptr); /* pos not upd */ return sim_tape_ioerr (uptr); } if (feof (uptr->fileref)) { /* eof? */ if (sbc == 0) /* no data? eom */ return MTSE_EOM; break; /* treat like eor */ } if ((sbc != 0) && (c & P7B_SOR)) /* next record? */ break; if ((c & P7B_DPAR) != P7B_EOF) all_eof = 0; } *bc = sbc; /* save rec lnt */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for read */ uptr->pos = uptr->pos + sbc; /* spc over record */ if (all_eof) /* tape mark? */ r = MTSE_TMK; break; default: return MTSE_FMT; } sim_debug (MTSE_DBG_STR, ctx->dptr, "rd_lnt: st: %d, lnt: %d, pos: %" T_ADDR_FMT "u\n", r, *bc, uptr->pos); return r; } /* Read record length reverse (internal routine) Inputs: uptr = pointer to tape unit bc = pointer to returned record length Outputs: status = operation status exit condition tape position ------------------ ------------------------------------------- unit unattached unchanged beginning of tape unchanged read error unchanged end of file unchanged end of medium updated tape mark updated tape runaway updated data record updated, sim_fread will read record forward This routine is called to set up a record read or spacing in the reverse direction. On return, status is MTSE_OK and the tape is positioned at the first data byte if a record was encountered, or status is an MTSE error code giving the reason that the operation did not succeed and the tape position is as indicated above. See the notes at "sim_tape_rdlntf" and "sim_tape_wrgap" regarding tape runaway and the erase gap implementation, respectively. */ static t_stat sim_tape_rdlntr (UNIT *uptr, t_mtrlnt *bc) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; uint8 c; t_bool all_eof; uint32 f = MT_GET_FMT (uptr); t_addr ppos; t_mtrlnt sbc; t_tpclnt tpcbc; t_mtrlnt buffer [256]; /* local tape buffer */ uint32 bufcntr, bufcap; /* buffer counter and capacity */ int32 runaway_counter, sizeof_gap; /* bytes remaining before runaway and bytes per gap */ t_stat r = MTSE_OK; MT_CLR_PNU (uptr); /* clear the position-not-updated flag */ if ((uptr->flags & UNIT_ATT) == 0) /* if the unit is not attached */ return MTSE_UNATT; /* then quit with an error */ if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ if (sim_tape_bot (uptr)) /* if the unit is positioned at the BOT */ return MTSE_BOT; /* then reading backward is not possible */ switch (f) { /* the read method depends on the tape format */ case MTUF_F_STD: case MTUF_F_E11: runaway_counter = 25 * 12 * bpi [MT_DENS (uptr->dynflags)]; /* set largest legal gap size in bytes */ if (runaway_counter == 0) { /* if tape density has not been not set */ sizeof_gap = 0; /* then disable runaway detection */ runaway_counter = INT_MAX; /* to allow gaps of any size */ } else /* otherwise */ sizeof_gap = sizeof (t_mtrlnt); /* set the size of the gap */ bufcntr = 0; /* force an initial read */ bufcap = 1; /* but of just one metadata marker */ do { /* loop until a record, gap, or error seen */ if (bufcntr == 0) { /* if the buffer is empty then refill it */ if (sim_tape_bot (uptr)) { /* if the search has backed into the BOT */ r = MTSE_BOT; /* then quit with an error */ break; } else if (uptr->pos < sizeof (buffer)) /* if less than a full buffer remains */ bufcap = (uint32) uptr->pos /* then reduce the capacity accordingly */ / sizeof (t_mtrlnt); sim_fseek (uptr->fileref, /* seek back to the location */ uptr->pos - bufcap * sizeof (t_mtrlnt), /* corresponding to the start */ SEEK_SET); /* of the buffer */ bufcntr = sim_fread (buffer, sizeof (t_mtrlnt), /* fill the buffer */ bufcap, uptr->fileref); /* with tape metadata */ if (ferror (uptr->fileref)) { /* if a file I/O error occurred */ MT_SET_PNU (uptr); /* then set position not updated */ r = sim_tape_ioerr (uptr); /* report the error and quit */ break; } else /* otherwise reset the capacity */ bufcap = sizeof (buffer) /* to the full size of the buffer */ / sizeof (buffer [0]); } *bc = buffer [--bufcntr]; /* store the metadata marker value */ uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* backspace over the marker */ if (*bc == MTR_TMK) { /* if the marker is a tape mark */ r = MTSE_TMK; /* then quit with tape mark status */ break; } else if (*bc == MTR_GAP) /* otherwise if the marker is a full gap */ runaway_counter -= sizeof_gap; /* then decrement the gap counter */ else if ((*bc & MTR_M_RHGAP) == MTR_RHGAP /* otherwise if the marker */ || *bc == MTR_RRGAP) { /* is a half gap */ uptr->pos = uptr->pos + sizeof (t_mtrlnt) / 2; /* then position forward to resync */ bufcntr = 0; /* mark the buffer as invalid to force a read */ *bc = MTR_GAP; /* reset the marker */ runaway_counter -= sizeof_gap / 2; /* and decrement the gap counter */ } else { /* otherwise it's a record marker */ sbc = MTR_L (*bc); /* extract the record length */ uptr->pos = uptr->pos - sizeof (t_mtrlnt) /* position to the start */ - (f == MTUF_F_STD ? (sbc + 1) & ~1 : sbc); /* of the record */ sim_fseek (uptr->fileref, /* seek to the data area */ uptr->pos + sizeof (t_mtrlnt), SEEK_SET); } } while (*bc == MTR_GAP && runaway_counter > 0); /* continue until data or runaway occurs */ if (r == MTSE_OK && runaway_counter <= 0) /* if a tape runaway occurred */ r = MTSE_RUNAWAY; /* then report it */ break; /* otherwise the operation succeeded */ case MTUF_F_TPC: ppos = sim_tape_tpc_fnd (uptr, (t_addr *) uptr->filebuf); /* find prev rec */ sim_fseek (uptr->fileref, ppos, SEEK_SET); /* position */ sim_fread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref); *bc = tpcbc; /* save rec lnt */ if (ferror (uptr->fileref)) /* error? */ return sim_tape_ioerr (uptr); if (feof (uptr->fileref)) { /* eof? */ r = MTSE_EOM; break; } uptr->pos = ppos; /* spc over record */ if (*bc == MTR_TMK) { /* tape mark? */ r = MTSE_TMK; break; } sim_fseek (uptr->fileref, uptr->pos + sizeof (t_tpclnt), SEEK_SET); break; case MTUF_F_P7B: for (sbc = 1, all_eof = 1; (t_addr) sbc <= uptr->pos ; sbc++) { sim_fseek (uptr->fileref, uptr->pos - sbc, SEEK_SET); sim_fread (&c, sizeof (uint8), 1, uptr->fileref); if (ferror (uptr->fileref)) /* error? */ return sim_tape_ioerr (uptr); if (feof (uptr->fileref)) { /* eof? */ r = MTSE_EOM; break; } if ((c & P7B_DPAR) != P7B_EOF) all_eof = 0; if (c & P7B_SOR) /* start of record? */ break; } uptr->pos = uptr->pos - sbc; /* update position */ *bc = sbc; /* save rec lnt */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for read */ if (all_eof) /* tape mark? */ r = MTSE_TMK; break; default: return MTSE_FMT; } sim_debug (MTSE_DBG_STR, ctx->dptr, "rd_lnt: st: %d, lnt: %d, pos: %" T_ADDR_FMT "u\n", r, *bc, uptr->pos); return r; } /* Read record forward Inputs: uptr = pointer to tape unit buf = pointer to buffer bc = pointer to returned record length max = maximum record size Outputs: status = operation status exit condition position unit unattached unchanged read error unchanged, PNU set end of file/medium unchanged, PNU set invalid record unchanged, PNU set tape mark updated data record updated data record error updated */ t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; uint32 f = MT_GET_FMT (uptr); t_mtrlnt i, tbc, rbc; t_addr opos; t_stat st; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_rdrecf(unit=%d, buf=%p, max=%d)\n", (int)(uptr-ctx->dptr->units), buf, max); opos = uptr->pos; /* old position */ if (MTSE_OK != (st = sim_tape_rdlntf (uptr, &tbc))) /* read rec lnt */ return st; *bc = rbc = MTR_L (tbc); /* strip error flag */ if (rbc > max) { /* rec out of range? */ MT_SET_PNU (uptr); uptr->pos = opos; return MTSE_INVRL; } i = (t_mtrlnt)sim_fread (buf, sizeof (uint8), rbc, uptr->fileref);/* read record */ if (ferror (uptr->fileref)) { /* error? */ MT_SET_PNU (uptr); uptr->pos = opos; return sim_tape_ioerr (uptr); } for ( ; i < rbc; i++) /* fill with 0's */ buf[i] = 0; if (f == MTUF_F_P7B) /* p7b? strip SOR */ buf[0] = buf[0] & P7B_DPAR; sim_tape_data_trace(uptr, buf, rbc, "Record Read", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR); return (MTR_F (tbc)? MTSE_RECE: MTSE_OK); } t_stat sim_tape_rdrecf_a (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max, TAPE_PCALLBACK callback) { t_stat r = SCPE_OK; AIO_CALLSETUP r = sim_tape_rdrecf (uptr, buf, bc, max); AIO_CALL(TOP_RDRF, buf, bc, NULL, max, 0, 0, 0, NULL, callback); return r; } /* Read record reverse Inputs: uptr = pointer to tape unit buf = pointer to buffer bc = pointer to returned record length max = maximum record size Outputs: status = operation status exit condition position unit unattached unchanged read error unchanged end of file unchanged end of medium updated invalid record unchanged tape mark updated data record updated data record error updated */ t_stat sim_tape_rdrecr (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; uint32 f = MT_GET_FMT (uptr); t_mtrlnt i, rbc, tbc; t_stat st; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_rdrecr(unit=%d, buf=%p, max=%d)\n", (int)(uptr-ctx->dptr->units), buf, max); if (MTSE_OK != (st = sim_tape_rdlntr (uptr, &tbc))) /* read rec lnt */ return st; *bc = rbc = MTR_L (tbc); /* strip error flag */ if (rbc > max) /* rec out of range? */ return MTSE_INVRL; i = (t_mtrlnt)sim_fread (buf, sizeof (uint8), rbc, uptr->fileref);/* read record */ if (ferror (uptr->fileref)) /* error? */ return sim_tape_ioerr (uptr); for ( ; i < rbc; i++) /* fill with 0's */ buf[i] = 0; if (f == MTUF_F_P7B) /* p7b? strip SOR */ buf[0] = buf[0] & P7B_DPAR; sim_tape_data_trace(uptr, buf, rbc, "Record Read Reverse", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR); return (MTR_F (tbc)? MTSE_RECE: MTSE_OK); } t_stat sim_tape_rdrecr_a (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max, TAPE_PCALLBACK callback) { t_stat r = SCPE_OK; AIO_CALLSETUP r = sim_tape_rdrecr (uptr, buf, bc, max); AIO_CALL(TOP_RDRR, buf, bc, NULL, max, 0, 0, 0, NULL, callback); return r; } /* Write record forward Inputs: uptr = pointer to tape unit buf = pointer to buffer bc = record length Outputs: status = operation status exit condition position unit unattached unchanged write protect unchanged write error unchanged, PNU set data record updated */ t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; uint32 f = MT_GET_FMT (uptr); t_mtrlnt sbc; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_wrrecf(unit=%d, buf=%p, bc=%d)\n", (int)(uptr-ctx->dptr->units), buf, bc); sim_tape_data_trace(uptr, buf, bc, "Record Write", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR); MT_CLR_PNU (uptr); sbc = MTR_L (bc); if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ return MTSE_UNATT; if (sim_tape_wrp (uptr)) /* write prot? */ return MTSE_WRP; if (sbc == 0) /* nothing to do? */ return MTSE_OK; sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ switch (f) { /* case on format */ case MTUF_F_STD: /* standard */ sbc = MTR_L ((bc + 1) & ~1); /* pad odd length */ case MTUF_F_E11: /* E11 */ sim_fwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref); sim_fwrite (buf, sizeof (uint8), sbc, uptr->fileref); sim_fwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref); if (ferror (uptr->fileref)) { /* error? */ MT_SET_PNU (uptr); return sim_tape_ioerr (uptr); } uptr->pos = uptr->pos + sbc + (2 * sizeof (t_mtrlnt)); /* move tape */ break; case MTUF_F_P7B: /* Pierce 7B */ buf[0] = buf[0] | P7B_SOR; /* mark start of rec */ sim_fwrite (buf, sizeof (uint8), sbc, uptr->fileref); sim_fwrite (buf, sizeof (uint8), 1, uptr->fileref); /* delimit rec */ if (ferror (uptr->fileref)) { /* error? */ MT_SET_PNU (uptr); return sim_tape_ioerr (uptr); } uptr->pos = uptr->pos + sbc; /* move tape */ break; } sim_tape_data_trace(uptr, buf, sbc, "Record Written", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR); return MTSE_OK; } t_stat sim_tape_wrrecf_a (UNIT *uptr, uint8 *buf, t_mtrlnt bc, TAPE_PCALLBACK callback) { t_stat r = SCPE_OK; AIO_CALLSETUP r = sim_tape_wrrecf (uptr, buf, bc); AIO_CALL(TOP_WREC, buf, 0, NULL, 0, bc, 0, 0, NULL, callback); return r; } /* Write metadata forward (internal routine) */ static t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; MT_CLR_PNU (uptr); if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ return MTSE_UNATT; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ if (sim_tape_wrp (uptr)) /* write prot? */ return MTSE_WRP; sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ sim_fwrite (&dat, sizeof (t_mtrlnt), 1, uptr->fileref); if (ferror (uptr->fileref)) { /* error? */ MT_SET_PNU (uptr); return sim_tape_ioerr (uptr); } sim_debug (MTSE_DBG_STR, ctx->dptr, "wr_lnt: lnt: %d, pos: %" T_ADDR_FMT "u\n", dat, uptr->pos); uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* move tape */ return MTSE_OK; } /* Write tape mark */ t_stat sim_tape_wrtmk (UNIT *uptr) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_wrtmk(unit=%d)\n", (int)(uptr-ctx->dptr->units)); if (MT_GET_FMT (uptr) == MTUF_F_P7B) { /* P7B? */ uint8 buf = P7B_EOF; /* eof mark */ return sim_tape_wrrecf (uptr, &buf, 1); /* write char */ } return sim_tape_wrdata (uptr, MTR_TMK); } t_stat sim_tape_wrtmk_a (UNIT *uptr, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_wrtmk (uptr); AIO_CALL(TOP_WTMK, NULL, NULL, NULL, 0, 0, 0, 0, NULL, callback); return r; } /* Write end of medium */ t_stat sim_tape_wreom (UNIT *uptr) { t_stat result; struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_wreom(unit=%d)\n", (int)(uptr-ctx->dptr->units)); if (MT_GET_FMT (uptr) == MTUF_F_P7B) /* cant do P7B */ return MTSE_FMT; result = sim_tape_wrdata (uptr, MTR_EOM); /* write the EOM marker */ uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* restore original tape position */ MT_SET_PNU (uptr); /* indicate that position was not updated */ return result; } t_stat sim_tape_wreom_a (UNIT *uptr, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_wreom (uptr); AIO_CALL(TOP_WEOM, NULL, NULL, NULL, 0, 0, 0, 0, NULL, callback); return r; } /* Write end of medium-rewind */ t_stat sim_tape_wreomrw (UNIT *uptr) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; t_stat r; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_wreomrw(unit=%d)\n", (int)(uptr-ctx->dptr->units)); if (MT_GET_FMT (uptr) == MTUF_F_P7B) /* cant do P7B */ return MTSE_FMT; r = sim_tape_wrdata (uptr, MTR_EOM); if (r == MTSE_OK) r = sim_tape_rewind (uptr); return r; } t_stat sim_tape_wreomrw_a (UNIT *uptr, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_wreomrw (uptr); AIO_CALL(TOP_WEMR, NULL, NULL, NULL, 0, 0, 0, 0, NULL, callback); return r; } /* Write erase gap Inputs: uptr = pointer to tape unit gaplen = length of gap in tenths of an inch Outputs: status = operation status exit condition position ------------------ ------------------ unit unattached unchanged unsupported format unchanged write protected unchanged read error unchanged, PNU set write error unchanged, PNU set gap written updated An erase gap is represented in the tape image file by a special metadata value. This value is chosen so that it is still recognizable even if it has been "cut in half" by a subsequent data overwrite that does not end on a metadatum-sized boundary. In addition, a range of metadata values are reserved for detection in the reverse direction. Erase gaps are currently supported only in SIMH (MTUF_F_STD) tape format. This implementation supports erasing gaps in the middle of a populated tape image and will always produce a valid image. It also produces valid images when overwriting gaps with data records, with one exception: a data write that leaves only two bytes of gap remaining will produce an invalid tape. This limitation is deemed acceptable, as it is analogous to the existing limitation that data records cannot overwrite other data records without producing an invalid tape. Because SIMH tape images do not carry physical parameters (e.g., recording density), overwriting a tape image file containing gap metadata is problematic if the density setting is not the same as that used during recording. There is no way to establish a gap of a certain length unequivocally in an image file, so this implementation establishes a gap of a certain number of bytes that reflect the desired gap length at the tape density in bits per inch used during writing. To write an erase gap, the implementation uses one of two approaches, depending on whether or not the current tape position is at EOM. Erasing at EOM presents no special difficulties; gap metadata markers are written for the prescribed number of bytes. If the tape is not at EOM, then erasing must take into account the existing record structure to ensure that a valid tape image is maintained. The general approach is to erase for the nominal number of bytes but to increase that length, if necessary, to ensure that a partially overwritten data record at the end of the gap can be altered to maintain validity. Because the smallest legal tape record requires space for two metadata markers plus two data bytes, an erasure that would leave less than that is increased to consume the entire record. Otherwise, the final record is truncated appropriately by rewriting the leading and trailing length words appropriately. When reading in either direction, gap metadata markers are ignored (skipped) until a record length header, EOF marker, EOM marker, or physical EOF is encountered. Thus, tape images containing gap metadata are transparent to the calling simulator (unless tape runaway support is enabled -- see the notes at "sim_tape_rdlntf" for details). The permissibility of data record lengths that are not multiples of the metadatum size presents a difficulty when reading. If such an "odd length" record is written over a gap, half of a metadata marker will exist immediately after the trailing record length. This condition is detected when reading forward by the appearance of a "reversed" marker. The value appears reversed because the value is made up of half of one marker and half of the next. This is handled by seeking forward two bytes to resync (the stipulation above that the overwrite cannot leave only two bytes of gap means that at least one "whole" metadata marker will follow). Reading in reverse presents a more complex problem, because half of the marker is from the preceding trailing record length marker and therefore could be any of a range of values. However, that range is restricted by the SIMH tape specification requirement that record length metadata values must have bits 30:24 set to zero. This allows unambiguous detection of the condition. The value chosen for gap metadata and the values reserved for "half-gap" detection are: 0xFFFFFFFE - primary gap value 0xFFFEFFFF - reserved (indicates half-gap in forward reads) 0xFFFF0000:0xFFFF00FF - reserved (indicates half-gap in reverse reads) 0xFFFF8000:0xFFFF80FF - reserved (indicates half-gap in reverse reads) If the tape density has been set via a previous sim_tape_set_dens call, and the tape format is set to SIMH format, then this routine will write a gap of the appropriate size. If the density has not been set, then no action will be taken, and either MTSE_IOERR or MTSE_OK status will be returned, depending on whether SIMH or another format is selected, respectively. A simulator that calls this routine must set the density beforehand; failure to do so is an error. However, calling while another format is enabled is OK and is treated as a no-operation. This allows a device simulator that supports writing erase gaps to use the same code without worrying about the tape format currently selected by the user. */ t_stat sim_tape_wrgap (UNIT *uptr, uint32 gaplen) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; t_stat st; t_mtrlnt meta, sbc, new_len, rec_size; t_addr gap_pos = uptr->pos; uint32 file_size, marker_count, tape_density; int32 gap_needed; uint32 gap_alloc = 0; /* gap currently allocated from the tape */ const uint32 format = MT_GET_FMT (uptr); /* tape format */ const uint32 meta_size = sizeof (t_mtrlnt); /* bytes per metadatum */ const uint32 min_rec_size = 2 + sizeof (t_mtrlnt) * 2; /* smallest data record size */ if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_wrgap(unit=%d, gaplen=%u)\n", (int)(uptr-ctx->dptr->units), gaplen); MT_CLR_PNU (uptr); if ((uptr->flags & UNIT_ATT) == 0) /* if the unit is not attached */ return MTSE_UNATT; /* then we cannot proceed */ else if (sim_tape_wrp (uptr)) /* otherwise if the unit is write protected */ return MTSE_WRP; /* then we cannot write */ tape_density = bpi [MT_DENS (uptr->dynflags)]; /* get the density of the tape */ if (format != MTUF_F_STD) /* if erase gaps aren't supported by the format */ return MTSE_OK; /* then take no action */ else if (tape_density == 0) /* otherwise if the density is not set */ return MTSE_IOERR; /* then report an I/O error */ else /* otherwise */ gap_needed = (gaplen * tape_density) / 10; /* determine the gap size needed in bytes */ file_size = sim_fsize (uptr->fileref); /* get file size */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position tape */ /* Read tape records and allocate to gap until amount required is consumed. Read next metadatum from tape: - EOF or EOM: allocate remainder of bytes needed. - TMK or GAP: allocate sizeof(metadatum) bytes. - Reverse GAP: allocate sizeof(metadatum) / 2 bytes. - Data record: see below. Loop until bytes needed = 0. */ do { sim_fread (&meta, meta_size, 1, uptr->fileref); /* read metadatum */ if (ferror (uptr->fileref)) { /* read error? */ uptr->pos = gap_pos; /* restore original position */ MT_SET_PNU (uptr); /* position not updated */ return sim_tape_ioerr (uptr); /* translate error */ } else uptr->pos = uptr->pos + meta_size; /* move tape over datum */ if (feof (uptr->fileref) || (meta == MTR_EOM)) { /* at eof or eom? */ gap_alloc = gap_alloc + gap_needed; /* allocate remainder */ gap_needed = 0; } else if ((meta == MTR_GAP) || (meta == MTR_TMK)) { /* gap or tape mark? */ gap_alloc = gap_alloc + meta_size; /* allocate marker space */ gap_needed = gap_needed - meta_size; /* reduce requirement */ } else if (meta == MTR_FHGAP) { /* half gap? */ uptr->pos = uptr->pos - meta_size / 2; /* backup to resync */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position tape */ gap_alloc = gap_alloc + meta_size / 2; /* allocate marker space */ gap_needed = gap_needed - meta_size / 2; /* reduce requirement */ } else if (uptr->pos + MTR_L (meta) + meta_size > file_size) { /* rec len out of range? */ gap_alloc = gap_alloc + gap_needed; /* presume overwritten tape */ gap_needed = 0; /* allocate remainder */ } /* Allocate a data record: - Determine record size in bytes (including metadata) - If record size - bytes needed < smallest allowed record size, allocate entire record to gap, else allocate needed amount and truncate data record to reflect remainder. */ else { /* data record */ sbc = MTR_L (meta); /* get record data length */ rec_size = ((sbc + 1) & ~1) + meta_size * 2; /* overall size in bytes */ if (rec_size < gap_needed + min_rec_size) { /* rec too small? */ uptr->pos = uptr->pos - meta_size + rec_size; /* position past record */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* move tape */ gap_alloc = gap_alloc + rec_size; /* allocate record */ gap_needed = gap_needed - rec_size; /* reduce requirement */ } else { /* record size OK */ uptr->pos = uptr->pos - meta_size + gap_needed; /* position to end of gap */ new_len = MTR_F (meta) | (sbc - gap_needed); /* truncate to new len */ st = sim_tape_wrdata (uptr, new_len); /* write new rec len */ if (st != MTSE_OK) { /* write OK? */ uptr->pos = gap_pos; /* restore orig pos */ return st; /* PNU was set by wrdata */ } uptr->pos = uptr->pos + sbc - gap_needed; /* position to end of data */ st = sim_tape_wrdata (uptr, new_len); /* write new rec len */ if (st != MTSE_OK) { /* write OK? */ uptr->pos = gap_pos; /* restore orig pos */ return st; /* PNU was set by wrdata */ } gap_alloc = gap_alloc + gap_needed; /* allocate remainder */ gap_needed = 0; } } } while (gap_needed > 0); uptr->pos = gap_pos; /* reposition to gap start */ if (gap_alloc & (meta_size - 1)) { /* gap size "odd?" */ st = sim_tape_wrdata (uptr, MTR_FHGAP); /* write half gap marker */ if (st != MTSE_OK) { /* write OK? */ uptr->pos = gap_pos; /* restore orig pos */ return st; /* PNU was set by wrdata */ } uptr->pos = uptr->pos - meta_size / 2; /* realign position */ gap_alloc = gap_alloc - 2; /* decrease gap to write */ } marker_count = gap_alloc / meta_size; /* count of gap markers */ do { st = sim_tape_wrdata (uptr, MTR_GAP); /* write gap markers */ if (st != MTSE_OK) { /* write OK? */ uptr->pos = gap_pos; /* restore orig pos */ return st; /* PNU was set by wrdata */ } } while (--marker_count > 0); return MTSE_OK; } t_stat sim_tape_wrgap_a (UNIT *uptr, uint32 gaplen, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_wrgap (uptr, gaplen); AIO_CALL(TOP_RDRR, NULL, NULL, NULL, 0, 0, gaplen, 0, NULL, callback); return r; } /* Erase a record forward. An erase gap is written in the forward direction on the tape unit specified by "uptr" for a length corresponding to a record containing the number of bytes specified by "bc", and the status of the operation is returned. The resulting gap will occupy "bc" bytes plus the size of the record length metadata. This function may be used to erase a record of length "n" in place by requesting a gap of length "n". After erasure, the tape will be positioned at the end of the gap. */ t_stat sim_tape_errecf (UNIT *uptr, t_mtrlnt bc) { const t_mtrlnt meta_size = sizeof (t_mtrlnt); /* the number of bytes per metadatum */ const t_mtrlnt gap_size = bc + 2 * meta_size; /* the requested gap size in bytes */ return MTSE_IOERR; /* stub return */ } /* Erase a record reverse. An erase gap is written in the reverse direction on the tape unit specified by "uptr" for a length corresponding to a record containing the number of bytes specified by "bc", and the status of the operation is returned. The resulting gap will occupy "bc" bytes plus the size of the record length metadata. This function may be used to erase a record of length "n" in place by requesting a gap of length "n". After erasure, the tape will be positioned at the start of the gap. */ t_stat sim_tape_errecr (UNIT *uptr, t_mtrlnt bc) { const t_mtrlnt meta_size = sizeof (t_mtrlnt); /* the number of bytes per metadatum */ const t_mtrlnt gap_size = bc + 2 * meta_size; /* the requested gap size in bytes */ return MTSE_IOERR; /* stub return */ } /* Space record forward Inputs: uptr = pointer to tape unit bc = pointer to size of record skipped Outputs: status = operation status exit condition position unit unattached unchanged read error unchanged, PNU set end of file/medium unchanged, PNU set tape mark updated data record updated data record error updated */ t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; t_stat st; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_sprecf(unit=%d)\n", (int)(uptr-ctx->dptr->units)); st = sim_tape_rdlntf (uptr, bc); /* get record length */ *bc = MTR_L (*bc); return st; } t_stat sim_tape_sprecf_a (UNIT *uptr, t_mtrlnt *bc, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_sprecf (uptr, bc); AIO_CALL(TOP_SPRF, NULL, bc, NULL, 0, 0, 0, 0, NULL, callback); return r; } /* Space records forward Inputs: uptr = pointer to tape unit count = count of records to skip skipped = pointer to number of records actually skipped Outputs: status = operation status exit condition position unit unattached unchanged read error unchanged, PNU set end of file/medium unchanged, PNU set tape mark updated data record updated data record error updated */ t_stat sim_tape_sprecsf (UNIT *uptr, uint32 count, uint32 *skipped) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; t_stat st; t_mtrlnt tbc; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_sprecsf(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count); *skipped = 0; while (*skipped < count) { /* loopo */ st = sim_tape_sprecf (uptr, &tbc); /* spc rec */ if (st != MTSE_OK) return st; *skipped = *skipped + 1; /* # recs skipped */ } return MTSE_OK; } t_stat sim_tape_sprecsf_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_sprecsf (uptr, count, skipped); AIO_CALL(TOP_SRSF, NULL, skipped, NULL, 0, count, 0, 0, NULL, callback); return r; } /* Space record reverse Inputs: uptr = pointer to tape unit bc = pointer to size of records skipped Outputs: status = operation status exit condition position unit unattached unchanged beginning of tape unchanged read error unchanged end of file unchanged end of medium updated tape mark updated data record updated */ t_stat sim_tape_sprecr (UNIT *uptr, t_mtrlnt *bc) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; t_stat st; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_sprecr(unit=%d)\n", (int)(uptr-ctx->dptr->units)); if (MT_TST_PNU (uptr)) { MT_CLR_PNU (uptr); *bc = 0; return MTSE_OK; } st = sim_tape_rdlntr (uptr, bc); /* get record length */ *bc = MTR_L (*bc); return st; } t_stat sim_tape_sprecr_a (UNIT *uptr, t_mtrlnt *bc, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_sprecr (uptr, bc); AIO_CALL(TOP_SPRR, NULL, bc, NULL, 0, 0, 0, 0, NULL, callback); return r; } /* Space records reverse Inputs: uptr = pointer to tape unit count = count of records to skip skipped = pointer to number of records actually skipped Outputs: status = operation status exit condition position unit unattached unchanged beginning of tape unchanged read error unchanged end of file unchanged end of medium updated tape mark updated data record updated */ t_stat sim_tape_sprecsr (UNIT *uptr, uint32 count, uint32 *skipped) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; t_stat st; t_mtrlnt tbc; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_sprecsr(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count); *skipped = 0; while (*skipped < count) { /* loopo */ st = sim_tape_sprecr (uptr, &tbc); /* spc rec rev */ if (st != MTSE_OK) return st; *skipped = *skipped + 1; /* # recs skipped */ } return MTSE_OK; } t_stat sim_tape_sprecsr_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_sprecsr (uptr, count, skipped); AIO_CALL(TOP_SRSR, NULL, skipped, NULL, 0, count, 0, 0, NULL, callback); return r; } /* Space files forward by record Inputs: uptr = pointer to tape unit count = count of files to skip skipped = pointer to number of files actually skipped recsskipped = pointer to number of records skipped check_leot = flag to detect and stop skip between two successive tape marks Outputs: status = operation status exit condition position unit unattached unchanged read error unchanged, PNU set end of file/medium unchanged, PNU set tape mark updated data record updated data record error updated */ t_stat sim_tape_spfilebyrecf (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped, t_bool check_leot) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; t_stat st; t_bool last_tapemark = FALSE; uint32 filerecsskipped; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_spfilebyrecf(unit=%d, count=%d, check_leot=%d)\n", (int)(uptr-ctx->dptr->units), count, check_leot); if (check_leot) { t_mtrlnt rbc; st = sim_tape_rdlntr (uptr, &rbc); last_tapemark = (MTSE_TMK == st); if ((st == MTSE_OK) || (st == MTSE_TMK)) sim_tape_rdlntf (uptr, &rbc); } *skipped = 0; *recsskipped = 0; while (*skipped < count) { /* loopo */ while (1) { st = sim_tape_sprecsf (uptr, 0x1ffffff, &filerecsskipped);/* spc recs */ *recsskipped += filerecsskipped; if (st != MTSE_OK) break; } if (st == MTSE_TMK) { *skipped = *skipped + 1; /* # files skipped */ if (check_leot && (filerecsskipped == 0) && last_tapemark) { uint32 filefileskipped; sim_tape_spfilebyrecr (uptr, 1, &filefileskipped, &filerecsskipped); *skipped = *skipped - 1; /* adjust # files skipped */ return MTSE_LEOT; } last_tapemark = TRUE; } else return st; } return MTSE_OK; } t_stat sim_tape_spfilebyrecf_a (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped, t_bool check_leot, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_spfilebyrecf (uptr, count, skipped, recsskipped, check_leot); AIO_CALL(TOP_SFRF, NULL, skipped, recsskipped, check_leot, count, 0, 0, NULL, callback); return r; } /* Space files forward Inputs: uptr = pointer to tape unit count = count of files to skip skipped = pointer to number of files actually skipped Outputs: status = operation status exit condition position unit unattached unchanged read error unchanged, PNU set end of file/medium unchanged, PNU set tape mark updated data record updated data record error updated */ t_stat sim_tape_spfilef (UNIT *uptr, uint32 count, uint32 *skipped) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; uint32 totalrecsskipped; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_spfilef(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count); return sim_tape_spfilebyrecf (uptr, count, skipped, &totalrecsskipped, FALSE); } t_stat sim_tape_spfilef_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_spfilef (uptr, count, skipped); AIO_CALL(TOP_SPFF, NULL, skipped, NULL, 0, count, 0, 0, NULL, callback); return r; } /* Space files reverse by record Inputs: uptr = pointer to tape unit count = count of files to skip skipped = pointer to number of files actually skipped recsskipped = pointer to number of records skipped Outputs: status = operation status exit condition position unit unattached unchanged beginning of tape unchanged read error unchanged end of file unchanged end of medium updated tape mark updated data record updated */ t_stat sim_tape_spfilebyrecr (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; t_stat st; uint32 filerecsskipped; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_spfilebyrecr(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count); *skipped = 0; *recsskipped = 0; while (*skipped < count) { /* loopo */ while (1) { st = sim_tape_sprecsr (uptr, 0x1ffffff, &filerecsskipped);/* spc recs rev */ *recsskipped += filerecsskipped; if (st != MTSE_OK) break; } if (st == MTSE_TMK) *skipped = *skipped + 1; /* # files skipped */ else return st; } return MTSE_OK; } t_stat sim_tape_spfilebyrecr_a (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_spfilebyrecr (uptr, count, skipped, recsskipped); AIO_CALL(TOP_SPFR, NULL, skipped, recsskipped, 0, count, 0, 0, NULL, callback); return r; } /* Space files reverse Inputs: uptr = pointer to tape unit count = count of files to skip skipped = pointer to number of files actually skipped Outputs: status = operation status exit condition position unit unattached unchanged beginning of tape unchanged read error unchanged end of file unchanged end of medium updated tape mark updated data record updated */ t_stat sim_tape_spfiler (UNIT *uptr, uint32 count, uint32 *skipped) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; uint32 totalrecsskipped; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_spfiler(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count); return sim_tape_spfilebyrecr (uptr, count, skipped, &totalrecsskipped); } t_stat sim_tape_spfiler_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_spfiler (uptr, count, skipped); AIO_CALL(TOP_SPFR, NULL, skipped, NULL, 0, count, 0, 0, NULL, callback); return r; } /* Rewind tape */ t_stat sim_tape_rewind (UNIT *uptr) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; if (uptr->flags & UNIT_ATT) { if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n");/* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_rewind(unit=%d)\n", (int)(uptr-ctx->dptr->units)); } uptr->pos = 0; MT_CLR_PNU (uptr); return MTSE_OK; } t_stat sim_tape_rewind_a (UNIT *uptr, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_rewind (uptr); AIO_CALL(TOP_RWND, NULL, NULL, NULL, 0, 0, 0, 0, NULL, callback); return r; } /* Position Tape */ t_stat sim_tape_position (UNIT *uptr, uint32 flags, uint32 recs, uint32 *recsskipped, uint32 files, uint32 *filesskipped, uint32 *objectsskipped) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; t_stat r = MTSE_OK; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_position(unit=%d, flags=0x%X, recs=%d, files=%d)\n", (int)(uptr-ctx->dptr->units), flags, recs, files); *recsskipped = *filesskipped = *objectsskipped = 0; if (flags & MTPOS_M_REW) r = sim_tape_rewind (uptr); if (r != MTSE_OK) return r; if (flags & MTPOS_M_OBJ) { uint32 objs = recs; uint32 skipped; uint32 objsremaining = objs; while (*objectsskipped < objs) { /* loopo */ if (flags & MTPOS_M_REV) /* reverse? */ r = sim_tape_sprecsr (uptr, objsremaining, &skipped); else r = sim_tape_sprecsf (uptr, objsremaining, &skipped); objsremaining = objsremaining - (skipped + ((r == MTSE_TMK) ? 1 : 0)); if ((r == MTSE_TMK) || (r == MTSE_OK)) *objectsskipped = *objectsskipped + skipped + ((r == MTSE_TMK) ? 1 : 0); else return r; } r = MTSE_OK; } else { uint32 fileskiprecs; if (flags & MTPOS_M_REV) /* reverse? */ r = sim_tape_spfilebyrecr (uptr, files, filesskipped, &fileskiprecs); else r = sim_tape_spfilebyrecf (uptr, files, filesskipped, &fileskiprecs, (flags & MTPOS_M_DLE)); if (r != MTSE_OK) return r; if (flags & MTPOS_M_REV) /* reverse? */ r = sim_tape_sprecsr (uptr, recs, recsskipped); else r = sim_tape_sprecsf (uptr, recs, recsskipped); if (r == MTSE_TMK) *filesskipped = *filesskipped + 1; *objectsskipped = fileskiprecs + *filesskipped + *recsskipped; } return r; } t_stat sim_tape_position_a (UNIT *uptr, uint32 flags, uint32 recs, uint32 *recsskipped, uint32 files, uint32 *filesskipped, uint32 *objectsskipped, TAPE_PCALLBACK callback) { t_stat r = MTSE_OK; AIO_CALLSETUP r = sim_tape_position (uptr, flags, recs, recsskipped, files, filesskipped, objectsskipped); AIO_CALL(TOP_POSN, NULL, recsskipped, filesskipped, 0, flags, recs, files, objectsskipped, callback); return r; } /* Reset tape */ t_stat sim_tape_reset (UNIT *uptr) { struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; MT_CLR_PNU (uptr); if (!(uptr->flags & UNIT_ATT)) /* attached? */ return SCPE_OK; if (ctx == NULL) /* if not properly attached? */ return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */ sim_debug (ctx->dbit, ctx->dptr, "sim_tape_reset(unit=%d)\n", (int)(uptr-ctx->dptr->units)); _sim_tape_io_flush(uptr); AIO_VALIDATE; AIO_UPDATE_QUEUE; return SCPE_OK; } /* Test for BOT */ t_bool sim_tape_bot (UNIT *uptr) { uint32 f = MT_GET_FMT (uptr); return (uptr->pos <= fmts[f].bot)? TRUE: FALSE; } /* Test for end of tape */ t_bool sim_tape_eot (UNIT *uptr) { return (uptr->capac && (uptr->pos >= uptr->capac))? TRUE: FALSE; } /* Test for write protect */ t_bool sim_tape_wrp (UNIT *uptr) { return ((uptr->flags & MTUF_WRP) || (MT_GET_FMT (uptr) == MTUF_F_TPC))? TRUE: FALSE; } /* Process I/O error */ static t_stat sim_tape_ioerr (UNIT *uptr) { sim_printf ("%s: Magtape library I/O error: %s\n", sim_uname (uptr), strerror (errno)); clearerr (uptr->fileref); return MTSE_IOERR; } /* Set tape format */ t_stat sim_tape_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { uint32 f; if (uptr == NULL) return SCPE_IERR; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; if (cptr == NULL) return SCPE_ARG; for (f = 0; f < MTUF_N_FMT; f++) { if (fmts[f].name && (strcmp (cptr, fmts[f].name) == 0)) { uptr->flags = (uptr->flags & ~MTUF_FMT) | (f << MTUF_V_FMT) | fmts[f].uflags; return SCPE_OK; } } return SCPE_ARG; } /* Show tape format */ t_stat sim_tape_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { int32 f = MT_GET_FMT (uptr); if (fmts[f].name) fprintf (st, "%s format", fmts[f].name); else fprintf (st, "invalid format"); return SCPE_OK; } /* Map a TPC format tape image */ static uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map, uint32 mapsize) { t_addr tpos, leot; t_addr tape_size; t_tpclnt bc, last_bc = 0xFFFF; uint32 had_double_tape_mark = 0; size_t i; uint32 objc, sizec; uint32 *countmap = NULL; uint8 *recbuf = NULL; DEVICE *dptr = find_dev_from_unit (uptr); if ((uptr == NULL) || (uptr->fileref == NULL)) return 0; countmap = (uint32 *)calloc (65536, sizeof(*countmap)); recbuf = (uint8 *)malloc (65536); tape_size = (t_addr)sim_fsize (uptr->fileref); sim_debug (MTSE_DBG_STR, dptr, "tpc_map: tape_size: %" T_ADDR_FMT "u\n", tape_size); for (objc = 0, sizec = 0, tpos = 0;; ) { sim_fseek (uptr->fileref, tpos, SEEK_SET); i = sim_fread (&bc, sizeof (t_tpclnt), 1, uptr->fileref); if (i == 0) /* past or at eof? */ break; if (countmap[bc] == 0) sizec++; ++countmap[bc]; if (map && (objc < mapsize)) map[objc] = tpos; if (bc) { sim_debug (MTSE_DBG_STR, dptr, "tpc_map: %d byte count at pos: %" T_ADDR_FMT "u\n", bc, tpos); if (sim_deb && (dptr->dctrl & MTSE_DBG_STR)) { sim_fread (recbuf, 1, bc, uptr->fileref); sim_data_trace(dptr, uptr, ((dptr->dctrl & MTSE_DBG_DAT) ? recbuf : NULL), "", bc, "Data Record", MTSE_DBG_STR); } } else sim_debug (MTSE_DBG_STR, dptr, "tpc_map: tape mark at pos: %" T_ADDR_FMT "u\n", tpos); objc++; tpos = tpos + ((bc + 1) & ~1) + sizeof (t_tpclnt); if ((bc == 0) && (last_bc == 0)) { /* double tape mark? */ had_double_tape_mark = objc; leot = tpos; } last_bc = bc; } sim_debug (MTSE_DBG_STR, dptr, "tpc_map: objc: %u, different record sizes: %u\n", objc, sizec); for (i=0; i<65535; i++) { if (countmap[i]) { if (i == 0) sim_debug (MTSE_DBG_STR, dptr, "tpc_map: summary - %u tape marks\n", countmap[i]); else sim_debug (MTSE_DBG_STR, dptr, "tpc_map: summary - %u %d byte record%s\n", countmap[i], (int)i, (countmap[i] > 1) ? "s" : ""); } } if (((last_bc != 0xffff) && (tpos > tape_size) && (!had_double_tape_mark)) || (!had_double_tape_mark) || ((objc == countmap[0]) && (countmap[0] != 2))) { /* Unreasonable format? */ if (last_bc != 0xffff) sim_debug (MTSE_DBG_STR, dptr, "tpc_map: ERROR unexpected EOT byte count: %d\n", last_bc); if (tpos > tape_size) sim_debug (MTSE_DBG_STR, dptr, "tpc_map: ERROR next record position %" T_ADDR_FMT "u beyond EOT: %" T_ADDR_FMT "u\n", tpos, tape_size); if (objc == countmap[0]) sim_debug (MTSE_DBG_STR, dptr, "tpc_map: ERROR tape cnly contains tape marks\n"); free (countmap); free (recbuf); return 0; } if ((last_bc != 0xffff) && (tpos > tape_size)) { sim_debug (MTSE_DBG_STR, dptr, "tpc_map: WARNING unexpected EOT byte count: %d, double tape mark before %" T_ADDR_FMT "u provides logical EOT\n", last_bc, leot); objc = had_double_tape_mark; tpos = leot; } if (map) map[objc] = tpos; sim_debug (MTSE_DBG_STR, dptr, "tpc_map: OK objc: %d\n", objc); free (countmap); free (recbuf); return objc; } /* Check the basic structure of a SIMH format tape image */ static t_stat sim_tape_simh_check (UNIT *uptr) { return SCPE_OK; } /* Check the basic structure of a E11 format tape image */ static t_stat sim_tape_e11_check (UNIT *uptr) { return SCPE_OK; } /* Find the preceding record in a TPC file */ static t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map) { uint32 lo, hi, p; if (map == NULL) return 0; lo = 0; hi = uptr->hwmark - 1; do { p = (lo + hi) >> 1; if (uptr->pos == map[p]) return ((p == 0)? map[p]: map[p - 1]); else if (uptr->pos < map[p]) hi = p - 1; else lo = p + 1; } while (lo <= hi); return ((p == 0)? map[p]: map[p - 1]); } /* Set tape capacity */ t_stat sim_tape_set_capac (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { t_addr cap; t_stat r; if ((cptr == NULL) || (*cptr == 0)) return SCPE_ARG; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; cap = (t_addr) get_uint (cptr, 10, sim_taddr_64? 2000000: 2000, &r); if (r != SCPE_OK) return SCPE_ARG; uptr->capac = cap * ((t_addr) 1000000); return SCPE_OK; } /* Show tape capacity */ t_stat sim_tape_show_capac (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { if (uptr->capac) { if (uptr->capac >= (t_addr) 1000000) fprintf (st, "capacity=%dMB", (uint32) (uptr->capac / ((t_addr) 1000000))); else { if (uptr->capac >= (t_addr) 1000) fprintf (st, "capacity=%dKB", (uint32) (uptr->capac / ((t_addr) 1000))); else fprintf (st, "capacity=%dB", (uint32) uptr->capac); } } else fprintf (st, "unlimited capacity"); return SCPE_OK; } /* Set the tape density. Set the density of the specified tape unit either to the value supplied or to the value represented by the supplied character string. If "desc" is NULL, then "val" must be set to one of the MT_DENS_* constants in sim_tape.h other than MT_DENS_NONE; the supplied value is used as the tape density, and the character string is ignored. Otherwise, "desc" must point at an int32 value containing a set of allowed densities constructed as a bitwise OR of the appropriate MT_*_VALID values. In this case, the string pointed to by "cptr" will be parsed for a decimal value corresponding to the desired density in bits per inch and validated against the set of allowed values. In either case, SCPE_ARG is returned if the density setting is not valid or allowed. If the setting is OK, the new density is set into the unit structure, and SCPE_OK is returned. */ t_stat sim_tape_set_dens (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { uint32 density, new_bpi; t_stat result = SCPE_OK; if (uptr == NULL) /* if the unit pointer is null */ return SCPE_IERR; /* then the caller has screwed up */ else if (desc == NULL) /* otherwise if a validation set was not supplied */ if (val > 0 && val < (int32) BPI_COUNT) /* then if a valid density code was supplied */ uptr->dynflags = (uptr->dynflags & ~MTVF_DENS_MASK) /* then insert the code */ | (val << UNIT_V_DF_TAPE); /* in the unit flags */ else /* otherwise the code is invalid */ return SCPE_ARG; /* so report a bad argument */ else { /* otherwise a validation set was supplied */ if (cptr == NULL || *cptr == 0) /* but if no value is present */ return SCPE_MISVAL; /* then report a missing value */ new_bpi = (uint32) get_uint (cptr, 10, UINT_MAX, &result); /* convert the string value */ if (result != SCPE_OK) /* if the conversion failed */ result = SCPE_ARG; /* then report a bad argument */ else for (density = 0; density < BPI_COUNT; density++) /* otherwise validate the density */ if (new_bpi == bpi [density] /* if it matches a value in the list */ && ((1 << density) & *(const int32 *) desc)) { /* and it's an allowed value */ uptr->dynflags = (uptr->dynflags & ~MTVF_DENS_MASK) /* then store the index of the value */ | density << UNIT_V_DF_TAPE; /* in the unit flags */ return SCPE_OK; /* and return success */ } result = SCPE_ARG; /* if no match, then report a bad argument */ } return result; /* return the result of the operation */ } /* Show the tape density */ t_stat sim_tape_show_dens (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { uint32 tape_density; if (uptr == NULL) /* if the unit pointer is null */ return SCPE_IERR; /* then the caller has screwed up */ else { /* otherwise get the density */ tape_density = bpi [MT_DENS (uptr->dynflags)]; /* of the tape from the unit flags */ if (tape_density) /* if it's set */ fprintf (st, "density=%d bpi", tape_density); /* then report it */ else /* otherwise */ fprintf (st, "density not set"); /* it was never set by the caller */ } return SCPE_OK; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | /* sim_tape.h: simulator tape support library definitions Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 18-Jul-16 JDB Added sim_tape_errecf, sim_tape_errecr functions 15-Dec-14 JDB Added tape density validity flags 04-Nov-14 JDB Added tape density flags 11-Oct-14 JDB Added reverse read half gap, set/show density 22-Sep-14 JDB Added tape runaway support 23-Jan-12 MP Added support for Logical EOT detection while positioning 05-Feb-11 MP Add Asynch I/O support 30-Aug-06 JDB Added erase gap support 14-Feb-06 RMS Added variable tape capacity 17-Dec-05 RMS Added write support for Paul Pierce 7b format 02-May-05 RMS Added support for Paul Pierce 7b format */ #ifndef SIM_TAPE_H_ #define SIM_TAPE_H_ 0 #ifdef __cplusplus extern "C" { #endif /* SIMH/E11 tape format */ typedef uint32 t_mtrlnt; /* magtape rec lnt */ #define MTR_TMK 0x00000000 /* tape mark */ #define MTR_EOM 0xFFFFFFFF /* end of medium */ #define MTR_GAP 0xFFFFFFFE /* primary gap */ #define MTR_RRGAP 0xFFFFFFFF /* reverse read half gap */ #define MTR_FHGAP 0xFFFEFFFF /* fwd half gap (overwrite) */ #define MTR_RHGAP 0xFFFF0000 /* rev half gap (overwrite) */ #define MTR_M_RHGAP (~0x000080FF) /* range mask for rev gap */ #define MTR_MAXLEN 0x00FFFFFF /* max len is 24b */ #define MTR_ERF 0x80000000 /* error flag */ #define MTR_F(x) ((x) & MTR_ERF) /* record error flg */ #define MTR_L(x) ((x) & ~MTR_ERF) /* record length */ /* TPC tape format */ typedef uint16 t_tpclnt; /* magtape rec lnt */ /* P7B tape format */ #define P7B_SOR 0x80 /* start of record */ #define P7B_PAR 0x40 /* parity */ #define P7B_DATA 0x3F /* data */ #define P7B_DPAR (P7B_PAR|P7B_DATA) /* data and parity */ #define P7B_EOF 0x0F /* eof character */ #define TPC_TMK 0x0000 /* tape mark */ /* Unit flags */ #define MTUF_V_PNU (UNIT_V_UF + 0) /* position not upd */ #define MTUF_V_WLK (UNIT_V_UF + 1) /* write locked */ #define MTUF_V_FMT (UNIT_V_UF + 2) /* tape file format */ #define MTUF_W_FMT 3 /* 3b of formats */ #define MTUF_N_FMT (1u << MTUF_W_FMT) /* number of formats */ #define MTUF_M_FMT ((1u << MTUF_W_FMT) - 1) #define MTUF_F_STD 0 /* SIMH format */ #define MTUF_F_E11 1 /* E11 format */ #define MTUF_F_TPC 2 /* TPC format */ #define MTUF_F_P7B 3 /* P7B format */ #define MUTF_F_TDF 4 /* TDF format */ #define MTUF_V_UF (MTUF_V_FMT + MTUF_W_FMT) #define MTUF_PNU (1u << MTUF_V_PNU) #define MTUF_WLK (1u << MTUF_V_WLK) #define MTUF_FMT (MTUF_M_FMT << MTUF_V_FMT) #define MTUF_WRP (MTUF_WLK | UNIT_RO) #define MT_F_STD (MTUF_F_STD << MTUF_V_FMT) #define MT_F_E11 (MTUF_F_E11 << MTUF_V_FMT) #define MT_F_TPC (MTUF_F_TPC << MTUF_V_FMT) #define MT_F_P7B (MTUF_F_P7B << MTUF_V_FMT) #define MT_F_TDF (MTUF_F_TDF << MTUF_V_FMT) #define MT_SET_PNU(u) (u)->flags = (u)->flags | MTUF_PNU #define MT_CLR_PNU(u) (u)->flags = (u)->flags & ~MTUF_PNU #define MT_TST_PNU(u) ((u)->flags & MTUF_PNU) #define MT_GET_FMT(u) (((u)->flags >> MTUF_V_FMT) & MTUF_M_FMT) /* sim_tape_position Position Flags */ #define MTPOS_V_REW 3 #define MTPOS_M_REW (1u << MTPOS_V_REW) /* Rewind First */ #define MTPOS_V_REV 2 #define MTPOS_M_REV (1u << MTPOS_V_REV) /* Reverse Direction */ #define MTPOS_V_OBJ 1 #define MTPOS_M_OBJ (1u << MTPOS_V_OBJ) /* Objects vs Records/Files */ #define MTPOS_V_DLE 4 #define MTPOS_M_DLE (1u << MTPOS_V_DLE) /* Detect LEOT */ /* Tape density values */ #define MT_DENS_NONE 0 /* density not set */ #define MT_DENS_200 1 /* 200 bpi NRZI */ #define MT_DENS_556 2 /* 556 bpi NRZI */ #define MT_DENS_800 3 /* 800 bpi NRZI */ #define MT_DENS_1600 4 /* 1600 bpi PE */ #define MT_DENS_6250 5 /* 6250 bpi GCR */ #define MTVF_DENS_MASK (((1u << UNIT_S_DF_TAPE) - 1) << UNIT_V_DF_TAPE) #define MT_DENS(f) (((f) & MTVF_DENS_MASK) >> UNIT_V_DF_TAPE) #define MT_NONE_VALID (1u << MT_DENS_NONE) /* density not set is valid */ #define MT_200_VALID (1u << MT_DENS_200) /* 200 bpi is valid */ #define MT_556_VALID (1u << MT_DENS_556) /* 556 bpi is valid */ #define MT_800_VALID (1u << MT_DENS_800) /* 800 bpi is valid */ #define MT_1600_VALID (1u << MT_DENS_1600) /* 1600 bpi is valid */ #define MT_6250_VALID (1u << MT_DENS_6250) /* 6250 bpi is valid */ /* Return status codes */ #define MTSE_OK 0 /* no error */ #define MTSE_TMK 1 /* tape mark */ #define MTSE_UNATT 2 /* unattached */ #define MTSE_IOERR 3 /* IO error */ #define MTSE_INVRL 4 /* invalid rec lnt */ #define MTSE_FMT 5 /* invalid format */ #define MTSE_BOT 6 /* beginning of tape */ #define MTSE_EOM 7 /* end of medium */ #define MTSE_RECE 8 /* error in record */ #define MTSE_WRP 9 /* write protected */ #define MTSE_LEOT 10 /* Logical End Of Tape */ #define MTSE_RUNAWAY 11 /* tape runaway */ typedef void (*TAPE_PCALLBACK)(UNIT *unit, t_stat status); /* Tape Internal Debug flags */ #define MTSE_DBG_DAT 0x0400000 /* Debug Data */ #define MTSE_DBG_POS 0x0800000 /* Debug Positioning activities */ #define MTSE_DBG_STR 0x1000000 /* Debug Tape Structure */ /* Prototypes */ t_stat sim_tape_attach_ex (UNIT *uptr, const char *cptr, uint32 dbit, int completion_delay); t_stat sim_tape_attach (UNIT *uptr, CONST char *cptr); t_stat sim_tape_detach (UNIT *uptr); t_stat sim_tape_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max); t_stat sim_tape_rdrecf_a (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max, TAPE_PCALLBACK callback); t_stat sim_tape_rdrecr (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max); t_stat sim_tape_rdrecr_a (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max, TAPE_PCALLBACK callback); t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc); t_stat sim_tape_wrrecf_a (UNIT *uptr, uint8 *buf, t_mtrlnt bc, TAPE_PCALLBACK callback); t_stat sim_tape_wrtmk (UNIT *uptr); t_stat sim_tape_wrtmk_a (UNIT *uptr, TAPE_PCALLBACK callback); t_stat sim_tape_wreom (UNIT *uptr); t_stat sim_tape_wreom_a (UNIT *uptr, TAPE_PCALLBACK callback); t_stat sim_tape_wreomrw (UNIT *uptr); t_stat sim_tape_wreomrw_a (UNIT *uptr, TAPE_PCALLBACK callback); t_stat sim_tape_wrgap (UNIT *uptr, uint32 gaplen); t_stat sim_tape_wrgap_a (UNIT *uptr, uint32 gaplen, TAPE_PCALLBACK callback); t_stat sim_tape_errecf (UNIT *uptr, t_mtrlnt bc); t_stat sim_tape_errecr (UNIT *uptr, t_mtrlnt bc); t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc); t_stat sim_tape_sprecf_a (UNIT *uptr, t_mtrlnt *bc, TAPE_PCALLBACK callback); t_stat sim_tape_sprecsf (UNIT *uptr, uint32 count, uint32 *skipped); t_stat sim_tape_sprecsf_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback); t_stat sim_tape_spfilef (UNIT *uptr, uint32 count, uint32 *skipped); t_stat sim_tape_spfilef_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback); t_stat sim_tape_spfilebyrecf (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped, t_bool check_leot); t_stat sim_tape_spfilebyrecf_a (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped, t_bool check_leot, TAPE_PCALLBACK callback); t_stat sim_tape_sprecr (UNIT *uptr, t_mtrlnt *bc); t_stat sim_tape_sprecr_a (UNIT *uptr, t_mtrlnt *bc, TAPE_PCALLBACK callback); t_stat sim_tape_sprecsr (UNIT *uptr, uint32 count, uint32 *skipped); t_stat sim_tape_sprecsr_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback); t_stat sim_tape_spfiler (UNIT *uptr, uint32 count, uint32 *skipped); t_stat sim_tape_spfiler_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback); t_stat sim_tape_spfilebyrecr (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped); t_stat sim_tape_spfilebyrecr_a (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped, TAPE_PCALLBACK callback); t_stat sim_tape_rewind (UNIT *uptr); t_stat sim_tape_rewind_a (UNIT *uptr, TAPE_PCALLBACK callback); t_stat sim_tape_position (UNIT *uptr, uint32 flags, uint32 recs, uint32 *recskipped, uint32 files, uint32 *fileskipped, uint32 *objectsskipped); t_stat sim_tape_position_a (UNIT *uptr, uint32 flags, uint32 recs, uint32 *recsskipped, uint32 files, uint32 *filesskipped, uint32 *objectsskipped, TAPE_PCALLBACK callback); t_stat sim_tape_reset (UNIT *uptr); t_bool sim_tape_bot (UNIT *uptr); t_bool sim_tape_wrp (UNIT *uptr); t_bool sim_tape_eot (UNIT *uptr); t_stat sim_tape_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_tape_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat sim_tape_set_capac (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_tape_show_capac (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat sim_tape_set_dens (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_tape_show_dens (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat sim_tape_set_asynch (UNIT *uptr, int latency); t_stat sim_tape_clr_asynch (UNIT *uptr); #ifdef __cplusplus } #endif #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 | /* sim_timer.c: simulator timer library Copyright (c) 1993-2010, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 21-Oct-11 MP Fixed throttling in several ways: - Sleep for the observed clock tick size while throttling - Recompute the throttling wait once every 10 seconds to account for varying instruction mixes during different phases of a simulator execution or to accommodate the presence of other load on the host system. - Each of the pre-existing throttling modes (Kcps, Mcps, and %) all compute the appropriate throttling interval dynamically. These dynamic computations assume that 100% of the host CPU is dedicated to the current simulator during this computation. This assumption may not always be true and under certain conditions may never provide a way to correctly determine the appropriate throttling wait. An additional throttling mode has been added which allows the simulator operator to explicitly state the desired throttling wait parameters. These are specified by: SET THROT insts/delay where 'insts' is the number of instructions to execute before sleeping for 'delay' milliseconds. 22-Apr-11 MP Fixed Asynch I/O support to reasonably account cycles when an idle wait is terminated by an external event 05-Jan-11 MP Added Asynch I/O support 29-Dec-10 MP Fixed clock resolution determination for Unix platforms 22-Sep-08 RMS Added "stability threshold" for idle routine 27-May-08 RMS Fixed bug in Linux idle routines (from Walter Mueller) 18-Jun-07 RMS Modified idle to exclude counted delays 22-Mar-07 RMS Added sim_rtcn_init_all 17-Oct-06 RMS Added idle support (based on work by Mark Pizzolato) Added throttle support 16-Aug-05 RMS Fixed C++ declaration and cast problems 02-Jan-04 RMS Split out from SCP This library includes the following routines: sim_timer_init - initialize timing system sim_rtc_init - initialize calibration sim_rtc_calb - calibrate clock sim_idle - virtual machine idle sim_os_msec - return elapsed time in msec sim_os_sleep - sleep specified number of seconds sim_os_ms_sleep - sleep specified number of milliseconds sim_idle_ms_sleep - sleep specified number of milliseconds or until awakened by an asynchronous event sim_timespec_diff subtract two timespec values sim_timer_activate_after schedule unit for specific time sim_timer_activate_time determine activation time sim_timer_activate_time_usecs determine activation time in usecs sim_rom_read_with_delay delay for default or specified delay sim_get_rom_delay_factor get current or initialize 1usec delay factor sim_set_rom_delay_factor set specific delay factor The calibration, idle, and throttle routines are OS-independent; the _os_ routines are not. */ #define NOT_MUX_USING_CODE /* sim_tmxr library provider or agnostic */ #include "sim_defs.h" #include <ctype.h> #include <math.h> #define SIM_INTERNAL_CLK (SIM_NTIMERS+(1<<30)) #define SIM_INTERNAL_UNIT sim_internal_timer_unit #ifndef MIN #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif #ifndef MAX #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #endif uint32 sim_idle_ms_sleep (unsigned int msec); /* MS_MIN_GRANULARITY exists here so that timing behavior for hosts systems */ /* with slow clock ticks can be assessed and tested without actually having */ /* that slow a clock tick on the development platform */ //#define MS_MIN_GRANULARITY 20 /* Uncomment to simulate 20ms host tick size.*/ /* some Solaris and BSD hosts come this way */ #if defined(MS_MIN_GRANULARITY) && (MS_MIN_GRANULARITY != 1) uint32 real_sim_idle_ms_sleep (unsigned int msec); uint32 real_sim_os_msec (void); uint32 real_sim_os_ms_sleep (unsigned int msec); static uint32 real_sim_os_sleep_min_ms = 0; static uint32 real_sim_os_sleep_inc_ms = 0; uint32 sim_idle_ms_sleep (unsigned int msec) { uint32 real_start = real_sim_os_msec (); uint32 start = (real_start / MS_MIN_GRANULARITY) * MS_MIN_GRANULARITY; uint32 tick_left; if (msec == 0) return 0; if (real_start == start) tick_left = 0; else tick_left = MS_MIN_GRANULARITY - (real_start - start); if (msec <= tick_left) real_sim_idle_ms_sleep (tick_left); else real_sim_idle_ms_sleep (((msec + MS_MIN_GRANULARITY - 1) / MS_MIN_GRANULARITY) * MS_MIN_GRANULARITY); return (sim_os_msec () - start); } uint32 sim_os_msec (void) { return (real_sim_os_msec ()/MS_MIN_GRANULARITY)*MS_MIN_GRANULARITY; } uint32 sim_os_ms_sleep (unsigned int msec) { msec = MS_MIN_GRANULARITY*((msec+MS_MIN_GRANULARITY-1)/MS_MIN_GRANULARITY); return real_sim_os_ms_sleep (msec); } #endif /* defined(MS_MIN_GRANULARITY) && (MS_MIN_GRANULARITY != 1) */ t_bool sim_idle_enab = FALSE; /* global flag */ volatile t_bool sim_idle_wait = FALSE; /* global flag */ static int32 sim_calb_tmr = -1; /* the system calibrated timer */ static int32 sim_calb_tmr_last = -1; /* shadow value when at sim> prompt */ static double sim_inst_per_sec_last = 0; /* shadow value when at sim> prompt */ static uint32 sim_idle_rate_ms = 0; static uint32 sim_os_sleep_min_ms = 0; static uint32 sim_os_sleep_inc_ms = 0; static uint32 sim_os_clock_resoluton_ms = 0; static uint32 sim_os_tick_hz = 0; static uint32 sim_idle_stable = SIM_IDLE_STDFLT; static uint32 sim_idle_calib_pct = 0; static uint32 sim_rom_delay = 0; static uint32 sim_throt_ms_start = 0; static uint32 sim_throt_ms_stop = 0; static uint32 sim_throt_type = 0; static uint32 sim_throt_val = 0; static uint32 sim_throt_state = SIM_THROT_STATE_INIT; static double sim_throt_cps; static double sim_throt_inst_start; static uint32 sim_throt_sleep_time = 0; static int32 sim_throt_wait = 0; static UNIT *sim_clock_unit[SIM_NTIMERS+1] = {NULL}; UNIT * volatile sim_clock_cosched_queue[SIM_NTIMERS+1] = {NULL}; static int32 sim_cosched_interval[SIM_NTIMERS+1]; static t_bool sim_catchup_ticks = TRUE; #if defined (SIM_ASYNCH_CLOCKS) && !defined (SIM_ASYNCH_IO) #undef SIM_ASYNCH_CLOCKS #endif t_bool sim_asynch_timer = FALSE; #if defined (SIM_ASYNCH_CLOCKS) UNIT * volatile sim_wallclock_queue = QUEUE_LIST_END; UNIT * volatile sim_wallclock_entry = NULL; #endif #define sleep1Samples 100 static uint32 _compute_minimum_sleep (void) { uint32 i, tot, tim; sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); #if defined(MS_MIN_GRANULARITY) && (MS_MIN_GRANULARITY != 1) real_sim_idle_ms_sleep (1); /* Start sampling on a tick boundary */ for (i = 0, tot = 0; i < sleep1Samples; i++) tot += real_sim_idle_ms_sleep (1); tim = tot / sleep1Samples; /* Truncated average */ real_sim_os_sleep_min_ms = tim; real_sim_idle_ms_sleep (1); /* Start sampling on a tick boundary */ for (i = 0, tot = 0; i < sleep1Samples; i++) tot += real_sim_idle_ms_sleep (real_sim_os_sleep_min_ms + 1); tim = tot / sleep1Samples; /* Truncated average */ real_sim_os_sleep_inc_ms = tim - real_sim_os_sleep_min_ms; #endif /* defined(MS_MIN_GRANULARITY) && (MS_MIN_GRANULARITY != 1) */ sim_idle_ms_sleep (1); /* Start sampling on a tick boundary */ for (i = 0, tot = 0; i < sleep1Samples; i++) tot += sim_idle_ms_sleep (1); tim = tot / sleep1Samples; /* Truncated average */ sim_os_sleep_min_ms = tim; sim_idle_ms_sleep (1); /* Start sampling on a tick boundary */ for (i = 0, tot = 0; i < sleep1Samples; i++) tot += sim_idle_ms_sleep (sim_os_sleep_min_ms + 1); tim = tot / sleep1Samples; /* Truncated average */ sim_os_sleep_inc_ms = tim - sim_os_sleep_min_ms; sim_os_set_thread_priority (PRIORITY_NORMAL); return sim_os_sleep_min_ms; } #if defined(MS_MIN_GRANULARITY) && (MS_MIN_GRANULARITY != 1) #define sim_idle_ms_sleep real_sim_idle_ms_sleep #define sim_os_msec real_sim_os_msec #define sim_os_ms_sleep real_sim_os_ms_sleep #endif /* defined(MS_MIN_GRANULARITY) && (MS_MIN_GRANULARITY != 1) */ #if defined(SIM_ASYNCH_IO) uint32 sim_idle_ms_sleep (unsigned int msec) { uint32 start_time = sim_os_msec(); struct timespec done_time; t_bool timedout = FALSE; clock_gettime(CLOCK_REALTIME, &done_time); done_time.tv_sec += (msec/1000); done_time.tv_nsec += 1000000*(msec%1000); if (done_time.tv_nsec > 1000000000) { done_time.tv_sec += done_time.tv_nsec/1000000000; done_time.tv_nsec = done_time.tv_nsec%1000000000; } pthread_mutex_lock (&sim_asynch_lock); sim_idle_wait = TRUE; if (!pthread_cond_timedwait (&sim_asynch_wake, &sim_asynch_lock, &done_time)) sim_asynch_check = 0; /* force check of asynch queue now */ else timedout = TRUE; sim_idle_wait = FALSE; pthread_mutex_unlock (&sim_asynch_lock); if (!timedout) { AIO_UPDATE_QUEUE; } return sim_os_msec() - start_time; } #else uint32 sim_idle_ms_sleep (unsigned int msec) { return sim_os_ms_sleep (msec); } #endif /* Mark the need for the sim_os_set_thread_priority routine, */ /* allowing the feature and/or platform dependent code to provide it */ #define NEED_THREAD_PRIORITY /* If we've got pthreads support then use pthreads mechanisms */ #if defined(USE_READER_THREAD) #undef NEED_THREAD_PRIORITY #if defined(_WIN32) /* On Windows there are several potentially disjoint threading APIs */ /* in use (base win32 pthreads, libSDL provided threading, and direct */ /* calls to beginthreadex), so go directly to the Win32 threading APIs */ /* to manage thread priority */ t_stat sim_os_set_thread_priority (int below_normal_above) { const static int val[3] = {THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL}; if ((below_normal_above < -1) || (below_normal_above > 1)) return SCPE_ARG; SetThreadPriority (GetCurrentThread(), val[1 + below_normal_above]); return SCPE_OK; } #else /* Native pthreads priority implementation */ t_stat sim_os_set_thread_priority (int below_normal_above) { int sched_policy, min_prio, max_prio; struct sched_param sched_priority; if ((below_normal_above < -1) || (below_normal_above > 1)) return SCPE_ARG; pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority); min_prio = sched_get_priority_min(sched_policy); max_prio = sched_get_priority_max(sched_policy); switch (below_normal_above) { case PRIORITY_BELOW_NORMAL: sched_priority.sched_priority = min_prio; break; case PRIORITY_NORMAL: sched_priority.sched_priority = (max_prio + min_prio) / 2; break; case PRIORITY_ABOVE_NORMAL: sched_priority.sched_priority = max_prio; break; } pthread_setschedparam (pthread_self(), sched_policy, &sched_priority); return SCPE_OK; } #endif #endif /* defined(USE_READER_THREAD) */ /* OS-dependent timer and clock routines */ /* VMS */ #if defined (VMS) #if defined (__VAX) #define sys$gettim SYS$GETTIM #define sys$setimr SYS$SETIMR #define lib$emul LIB$EMUL #define sys$waitfr SYS$WAITFR #define lib$subx LIB$SUBX #define lib$ediv LIB$EDIV #endif #include <starlet.h> #include <lib$routines.h> #include <unistd.h> const t_bool rtc_avail = TRUE; uint32 sim_os_msec (void) { uint32 quo, htod, tod[2]; int32 i; sys$gettim (tod); /* time 0.1usec */ /* To convert to msec, must divide a 64b quantity by 10000. This is actually done by dividing the 96b quantity 0'time by 10000, producing 64b of quotient, the high 32b of which are discarded. This can probably be done by a clever multiply... */ quo = htod = 0; for (i = 0; i < 64; i++) { /* 64b quo */ htod = (htod << 1) | ((tod[1] >> 31) & 1); /* shift divd */ tod[1] = (tod[1] << 1) | ((tod[0] >> 31) & 1); tod[0] = tod[0] << 1; quo = quo << 1; /* shift quo */ if (htod >= 10000) { /* divd work? */ htod = htod - 10000; /* subtract */ quo = quo | 1; /* set quo bit */ } } return quo; } void sim_os_sleep (unsigned int sec) { sleep (sec); return; } uint32 sim_os_ms_sleep_init (void) { return _compute_minimum_sleep (); } uint32 sim_os_ms_sleep (unsigned int msec) { uint32 stime = sim_os_msec (); uint32 qtime[2]; int32 nsfactor = -10000; static int32 zero = 0; lib$emul (&msec, &nsfactor, &zero, qtime); sys$setimr (2, qtime, 0, 0); sys$waitfr (2); return sim_os_msec () - stime; } #ifdef NEED_CLOCK_GETTIME int clock_gettime(int clk_id, struct timespec *tp) { uint32 secs, ns, tod[2], unixbase[2] = {0xd53e8000, 0x019db1de}; if (clk_id != CLOCK_REALTIME) return -1; sys$gettim (tod); /* time 0.1usec */ lib$subx(tod, unixbase, tod); /* convert to unix base */ lib$ediv(&10000000, tod, &secs, &ns); /* isolate seconds & 100ns parts */ tp->tv_sec = secs; tp->tv_nsec = ns*100; return 0; } #endif /* CLOCK_REALTIME */ #elif defined (_WIN32) /* Win32 routines */ const t_bool rtc_avail = TRUE; uint32 sim_os_msec (void) { return timeGetTime (); } void sim_os_sleep (unsigned int sec) { Sleep (sec * 1000); return; } void sim_timer_exit (void) { timeEndPeriod (sim_idle_rate_ms); return; } uint32 sim_os_ms_sleep_init (void) { TIMECAPS timers; if (timeGetDevCaps (&timers, sizeof (timers)) != TIMERR_NOERROR) return 0; if (timers.wPeriodMin == 0) return 0; if (timeBeginPeriod (timers.wPeriodMin) != TIMERR_NOERROR) return 0; atexit (sim_timer_exit); /* return measured actual minimum sleep time */ return _compute_minimum_sleep (); } uint32 sim_os_ms_sleep (unsigned int msec) { uint32 stime = sim_os_msec(); Sleep (msec); return sim_os_msec () - stime; } #if defined(NEED_CLOCK_GETTIME) int clock_gettime(int clk_id, struct timespec *tp) { t_uint64 now, unixbase; if (clk_id != CLOCK_REALTIME) return -1; unixbase = 116444736; unixbase *= 1000000000; GetSystemTimeAsFileTime((FILETIME*)&now); now -= unixbase; tp->tv_sec = (long)(now/10000000); tp->tv_nsec = (now%10000000)*100; return 0; } #endif #elif defined (__OS2__) /* OS/2 routines, from Bruce Ray */ const t_bool rtc_avail = FALSE; uint32 sim_os_msec (void) { return 0; } void sim_os_sleep (unsigned int sec) { return; } uint32 sim_os_ms_sleep_init (void) { return 0; } uint32 sim_os_ms_sleep (unsigned int msec) { return 0; } /* Metrowerks CodeWarrior Macintosh routines, from Ben Supnik */ #elif defined (__MWERKS__) && defined (macintosh) #include <Timer.h> #include <Mactypes.h> #include <sioux.h> #include <unistd.h> #include <siouxglobals.h> #define NANOS_PER_MILLI 1000000 #define MILLIS_PER_SEC 1000 const t_bool rtc_avail = TRUE; uint32 sim_os_msec (void) { unsigned long long micros; UnsignedWide macMicros; unsigned long millis; Microseconds (&macMicros); micros = *((unsigned long long *) &macMicros); millis = micros / 1000LL; return (uint32) millis; } void sim_os_sleep (unsigned int sec) { sleep (sec); return; } uint32 sim_os_ms_sleep_init (void) { return _compute_minimum_sleep (); } uint32 sim_os_ms_sleep (unsigned int milliseconds) { uint32 stime = sim_os_msec (); struct timespec treq; treq.tv_sec = milliseconds / MILLIS_PER_SEC; treq.tv_nsec = (milliseconds % MILLIS_PER_SEC) * NANOS_PER_MILLI; (void) nanosleep (&treq, NULL); return sim_os_msec () - stime; } #if defined(NEED_CLOCK_GETTIME) int clock_gettime(int clk_id, struct timespec *tp) { struct timeval cur; if (clk_id != CLOCK_REALTIME) return -1; gettimeofday (&cur, NULL); tp->tv_sec = cur.tv_sec; tp->tv_nsec = cur.tv_usec*1000; return 0; } #endif #else /* UNIX routines */ #include <time.h> #include <sys/time.h> #include <unistd.h> #define NANOS_PER_MILLI 1000000 #define MILLIS_PER_SEC 1000 const t_bool rtc_avail = TRUE; uint32 sim_os_msec (void) { struct timeval cur; struct timezone foo; uint32 msec; gettimeofday (&cur, &foo); msec = (((uint32) cur.tv_sec) * 1000) + (((uint32) cur.tv_usec) / 1000); return msec; } void sim_os_sleep (unsigned int sec) { sleep (sec); return; } uint32 sim_os_ms_sleep_init (void) { return _compute_minimum_sleep (); } #if !defined(_POSIX_SOURCE) #ifdef NEED_CLOCK_GETTIME typedef int clockid_t; int clock_gettime(clockid_t clk_id, struct timespec *tp) { struct timeval cur; struct timezone foo; if (clk_id != CLOCK_REALTIME) return -1; gettimeofday (&cur, &foo); tp->tv_sec = cur.tv_sec; tp->tv_nsec = cur.tv_usec*1000; return 0; } #endif /* CLOCK_REALTIME */ #endif /* !defined(_POSIX_SOURCE) && defined(SIM_ASYNCH_IO) */ uint32 sim_os_ms_sleep (unsigned int milliseconds) { uint32 stime = sim_os_msec (); struct timespec treq; treq.tv_sec = milliseconds / MILLIS_PER_SEC; treq.tv_nsec = (milliseconds % MILLIS_PER_SEC) * NANOS_PER_MILLI; (void) nanosleep (&treq, NULL); return sim_os_msec () - stime; } #if defined(NEED_THREAD_PRIORITY) #undef NEED_THREAD_PRIORITY #include <sys/time.h> #include <sys/resource.h> t_stat sim_os_set_thread_priority (int below_normal_above) { if ((below_normal_above < -1) || (below_normal_above > 1)) return SCPE_ARG; errno = 0; switch (below_normal_above) { case PRIORITY_BELOW_NORMAL: if ((getpriority (PRIO_PROCESS, 0) <= 0) && /* at or above normal pri? */ (errno == 0)) setpriority (PRIO_PROCESS, 0, 10); break; case PRIORITY_NORMAL: if (getpriority (PRIO_PROCESS, 0) != 0) /* at or above normal pri? */ setpriority (PRIO_PROCESS, 0, 0); break; case PRIORITY_ABOVE_NORMAL: if ((getpriority (PRIO_PROCESS, 0) <= 0) && /* at or above normal pri? */ (errno == 0)) setpriority (PRIO_PROCESS, 0, -10); break; } return SCPE_OK; } #endif /* defined(NEED_THREAD_PRIORITY) */ #endif /* If one hasn't been provided yet, then just stub it */ #if defined(NEED_THREAD_PRIORITY) t_stat sim_os_set_thread_priority (int below_normal_above) { return SCPE_OK; } #endif #if defined(MS_MIN_GRANULARITY) && (MS_MIN_GRANULARITY != 1) /* Make sure to use the substitute routines */ #undef sim_idle_ms_sleep #undef sim_os_msec #undef sim_os_ms_sleep #endif /* defined(MS_MIN_GRANULARITY) && (MS_MIN_GRANULARITY != 1) */ /* diff = min - sub */ void sim_timespec_diff (struct timespec *diff, struct timespec *min, struct timespec *sub) { /* move the minuend value to the difference and operate there. */ *diff = *min; /* Borrow as needed for the nsec value */ while (sub->tv_nsec > diff->tv_nsec) { --diff->tv_sec; diff->tv_nsec += 1000000000; } diff->tv_nsec -= sub->tv_nsec; diff->tv_sec -= sub->tv_sec; /* Normalize the result */ while (diff->tv_nsec > 1000000000) { ++diff->tv_sec; diff->tv_nsec -= 1000000000; } } /* Forward declarations */ static double _timespec_to_double (struct timespec *time); static void _double_to_timespec (struct timespec *time, double dtime); static t_bool _rtcn_tick_catchup_check (int32 tmr, int32 time); static void _rtcn_configure_calibrated_clock (int32 newtmr); static t_bool _sim_coschedule_cancel (UNIT *uptr); static t_bool _sim_wallclock_cancel (UNIT *uptr); static t_bool _sim_wallclock_is_active (UNIT *uptr); t_stat sim_timer_show_idle_mode (FILE* st, UNIT* uptr, int32 val, CONST void * desc); #if defined(SIM_ASYNCH_CLOCKS) static int sim_timespec_compare (struct timespec *a, struct timespec *b) { while (a->tv_nsec > 1000000000) { a->tv_nsec -= 1000000000; ++a->tv_sec; } while (b->tv_nsec > 1000000000) { b->tv_nsec -= 1000000000; ++b->tv_sec; } if (a->tv_sec < b->tv_sec) return -1; if (a->tv_sec > b->tv_sec) return 1; if (a->tv_nsec < b->tv_nsec) return -1; if (a->tv_nsec > b->tv_nsec) return 1; else return 0; } #endif /* defined(SIM_ASYNCH_CLOCKS) */ /* OS independent clock calibration package */ static int32 rtc_ticks[SIM_NTIMERS+1] = { 0 }; /* ticks */ static uint32 rtc_hz[SIM_NTIMERS+1] = { 0 }; /* tick rate */ static uint32 rtc_last_hz[SIM_NTIMERS+1] = { 0 }; /* prior tick rate */ static uint32 rtc_rtime[SIM_NTIMERS+1] = { 0 }; /* real time */ static uint32 rtc_vtime[SIM_NTIMERS+1] = { 0 }; /* virtual time */ static double rtc_gtime[SIM_NTIMERS+1] = { 0 }; /* instruction time */ static uint32 rtc_nxintv[SIM_NTIMERS+1] = { 0 }; /* next interval */ static int32 rtc_based[SIM_NTIMERS+1] = { 0 }; /* base delay */ static int32 rtc_currd[SIM_NTIMERS+1] = { 0 }; /* current delay */ static int32 rtc_initd[SIM_NTIMERS+1] = { 0 }; /* initial delay */ static uint32 rtc_elapsed[SIM_NTIMERS+1] = { 0 }; /* sec since init */ static uint32 rtc_calibrations[SIM_NTIMERS+1] = { 0 }; /* calibration count */ static double rtc_clock_skew_max[SIM_NTIMERS+1] = { 0 }; /* asynchronous max skew */ static double rtc_clock_start_gtime[SIM_NTIMERS+1] = { 0 };/* reference instruction time for clock */ static double rtc_clock_tick_size[SIM_NTIMERS+1] = { 0 }; /* 1/hz */ static uint32 rtc_calib_initializations[SIM_NTIMERS+1] = { 0 };/* Initialization Count */ static double rtc_calib_tick_time[SIM_NTIMERS+1] = { 0 }; /* ticks time */ static double rtc_calib_tick_time_tot[SIM_NTIMERS+1] = { 0 };/* ticks time - total*/ static uint32 rtc_calib_ticks_acked[SIM_NTIMERS+1] = { 0 };/* ticks Acked */ static uint32 rtc_calib_ticks_acked_tot[SIM_NTIMERS+1] = { 0 };/* ticks Acked - total */ static uint32 rtc_clock_ticks[SIM_NTIMERS+1] = { 0 };/* ticks delivered since catchup base */ static uint32 rtc_clock_ticks_tot[SIM_NTIMERS+1] = { 0 };/* ticks delivered since catchup base - total */ static double rtc_clock_init_base_time[SIM_NTIMERS+1] = { 0 };/* reference time for clock initialization */ static double rtc_clock_tick_start_time[SIM_NTIMERS+1] = { 0 };/* reference time when ticking started */ static double rtc_clock_catchup_base_time[SIM_NTIMERS+1] = { 0 };/* reference time for catchup ticks */ static uint32 rtc_clock_catchup_ticks[SIM_NTIMERS+1] = { 0 };/* Record of catchups */ static uint32 rtc_clock_catchup_ticks_tot[SIM_NTIMERS+1] = { 0 };/* Record of catchups - total */ static t_bool rtc_clock_catchup_pending[SIM_NTIMERS+1] = { 0 };/* clock tick catchup pending */ static t_bool rtc_clock_catchup_eligible[SIM_NTIMERS+1] = { 0 };/* clock tick catchup eligible */ static uint32 rtc_clock_time_idled[SIM_NTIMERS+1] = { 0 };/* total time idled */ static uint32 rtc_clock_time_idled_last[SIM_NTIMERS+1] = { 0 };/* total time idled */ static uint32 rtc_clock_calib_skip_idle[SIM_NTIMERS+1] = { 0 };/* Calibrations skipped due to idling */ static uint32 rtc_clock_calib_gap2big[SIM_NTIMERS+1] = { 0 };/* Calibrations skipped Gap Too Big */ static uint32 rtc_clock_calib_backwards[SIM_NTIMERS+1] = { 0 };/* Calibrations skipped Clock Running Backwards */ static uint32 sim_idle_cyc_ms = 0; /* Cycles per millisecond while not idling */ UNIT sim_timer_units[SIM_NTIMERS+1]; /* Clock assist units */ /* one for each timer and one for an internal */ /* clock if no clocks are registered. */ UNIT sim_internal_timer_unit; /* Internal calibration timer */ UNIT sim_throttle_unit; /* one for throttle */ t_stat sim_throt_svc (UNIT *uptr); t_stat sim_timer_tick_svc (UNIT *uptr); #define DBG_IDL TIMER_DBG_IDLE /* idling */ #define DBG_QUE TIMER_DBG_QUEUE /* queue activities */ #define DBG_MUX TIMER_DBG_MUX /* tmxr queue activities */ #define DBG_TRC 0x008 /* tracing */ #define DBG_CAL 0x010 /* calibration activities */ #define DBG_TIM 0x020 /* timer thread activities */ #define DBG_THR 0x040 /* throttle activities */ #define DBG_ACK 0x080 /* interrupt acknowledgement activities */ #define DBG_CHK 0x100 /* check scheduled activation time*/ DEBTAB sim_timer_debug[] = { {"TRACE", DBG_TRC, "Trace routine calls"}, {"IDLE", DBG_IDL, "Idling activities"}, {"QUEUE", DBG_QUE, "Event queuing activities"}, {"IACK", DBG_ACK, "interrupt acknowledgement activities"}, {"CALIB", DBG_CAL, "Calibration activities"}, {"TIME", DBG_TIM, "Activation and scheduling activities"}, {"THROT", DBG_THR, "Throttling activities"}, {"MUX", DBG_MUX, "Tmxr scheduling activities"}, {"CHECK", DBG_CHK, "Check scheduled activation time"}, {0} }; /* Forward device declarations */ extern DEVICE sim_timer_dev; extern DEVICE sim_throttle_dev; void sim_rtcn_init_all (void) { int32 tmr; for (tmr = 0; tmr <= SIM_NTIMERS; tmr++) if (rtc_initd[tmr] != 0) sim_rtcn_init (rtc_initd[tmr], tmr); return; } int32 sim_rtcn_init (int32 time, int32 tmr) { return sim_rtcn_init_unit (NULL, time, tmr); } int32 sim_rtcn_init_unit (UNIT *uptr, int32 time, int32 tmr) { if (time == 0) time = 1; if (tmr == SIM_INTERNAL_CLK) tmr = SIM_NTIMERS; else { if ((tmr < 0) || (tmr >= SIM_NTIMERS)) return time; } /* * If we'd previously succeeded in calibrating a tick value, then use that * delay as a better default to setup when we're re-initialized. * Re-initializing happens on any boot or after any breakpoint/continue. */ if (rtc_currd[tmr]) time = rtc_currd[tmr]; if (!uptr) uptr = sim_clock_unit[tmr]; sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_init_unit(unit=%s, time=%d, tmr=%d)\n", uptr ? sim_uname(uptr) : "", time, tmr); if (uptr) { if (!sim_clock_unit[tmr]) sim_register_clock_unit_tmr (uptr, tmr); } rtc_clock_start_gtime[tmr] = sim_gtime(); rtc_rtime[tmr] = sim_os_msec (); rtc_vtime[tmr] = rtc_rtime[tmr]; rtc_nxintv[tmr] = 1000; rtc_ticks[tmr] = 0; rtc_last_hz[tmr] = rtc_hz[tmr]; rtc_hz[tmr] = 0; rtc_based[tmr] = time; rtc_currd[tmr] = time; rtc_initd[tmr] = time; rtc_elapsed[tmr] = 0; rtc_calibrations[tmr] = 0; rtc_clock_ticks_tot[tmr] += rtc_clock_ticks[tmr]; rtc_clock_ticks[tmr] = 0; rtc_calib_tick_time_tot[tmr] += rtc_calib_tick_time[tmr]; rtc_calib_tick_time[tmr] = 0; rtc_clock_catchup_pending[tmr] = FALSE; rtc_clock_catchup_eligible[tmr] = FALSE; rtc_clock_catchup_ticks_tot[tmr] += rtc_clock_catchup_ticks[tmr]; rtc_clock_catchup_ticks[tmr] = 0; rtc_calib_ticks_acked_tot[tmr] += rtc_calib_ticks_acked[tmr]; rtc_calib_ticks_acked[tmr] = 0; ++rtc_calib_initializations[tmr]; rtc_clock_init_base_time[tmr] = sim_timenow_double (); _rtcn_configure_calibrated_clock (tmr); return time; } int32 sim_rtcn_calb (int32 ticksper, int32 tmr) { uint32 new_rtime, delta_rtime, last_idle_pct; int32 delta_vtime; double new_gtime; int32 new_currd; int32 itmr; if (tmr == SIM_INTERNAL_CLK) tmr = SIM_NTIMERS; else { if ((tmr < 0) || (tmr >= SIM_NTIMERS)) return 10000; } if (rtc_hz[tmr] != ticksper) { /* changing tick rate? */ if (rtc_hz[tmr] == 0) rtc_clock_tick_start_time[tmr] = sim_timenow_double (); rtc_last_hz[tmr] = rtc_hz[tmr]; rtc_hz[tmr] = ticksper; _rtcn_configure_calibrated_clock (tmr); if (ticksper != 0) { rtc_clock_tick_size[tmr] = 1.0 / ticksper; rtc_currd[tmr] = (int32)(sim_timer_inst_per_sec () / ticksper); } } if (ticksper == 0) /* running? */ return 10000; if (sim_clock_unit[tmr] == NULL) { /* Not using TIMER units? */ rtc_clock_ticks[tmr] += 1; rtc_calib_tick_time[tmr] += rtc_clock_tick_size[tmr]; } if (rtc_clock_catchup_pending[tmr]) { /* catchup tick? */ ++rtc_clock_catchup_ticks[tmr]; /* accumulating which were catchups */ rtc_clock_catchup_pending[tmr] = FALSE; } rtc_ticks[tmr] = rtc_ticks[tmr] + 1; /* count ticks */ if (rtc_ticks[tmr] < ticksper) /* 1 sec yet? */ return rtc_currd[tmr]; rtc_ticks[tmr] = 0; /* reset ticks */ rtc_elapsed[tmr] = rtc_elapsed[tmr] + 1; /* count sec */ if (sim_throt_type != SIM_THROT_NONE) { rtc_gtime[tmr] = sim_gtime(); /* save instruction time */ rtc_currd[tmr] = (int32)(sim_throt_cps / ticksper); /* use throttle calibration */ ++rtc_calibrations[tmr]; /* count calibrations */ sim_debug (DBG_CAL, &sim_timer_dev, "using throttle calibrated value - result: %d\n", rtc_currd[tmr]); return rtc_currd[tmr]; } if (!rtc_avail) /* no timer? */ return rtc_currd[tmr]; if (sim_calb_tmr != tmr) { rtc_currd[tmr] = (int32)(sim_timer_inst_per_sec()/ticksper); sim_debug (DBG_CAL, &sim_timer_dev, "calibrated calibrated tmr=%d against system tmr=%d, tickper=%d (result: %d)\n", tmr, sim_calb_tmr, ticksper, rtc_currd[tmr]); return rtc_currd[tmr]; } new_rtime = sim_os_msec (); /* wall time */ ++rtc_calibrations[tmr]; /* count calibrations */ sim_debug (DBG_TRC, &sim_timer_dev, "sim_rtcn_calb(ticksper=%d, tmr=%d)\n", ticksper, tmr); if (new_rtime < rtc_rtime[tmr]) { /* time running backwards? */ /* This happens when the value returned by sim_os_msec wraps (as an uint32) */ /* Wrapping will happen initially sometime before a simulator has been running */ /* for 49 days approximately every 49 days thereafter. */ ++rtc_clock_calib_backwards[tmr]; /* Count statistic */ sim_debug (DBG_CAL, &sim_timer_dev, "time running backwards - OldTime: %u, NewTime: %u, result: %d\n", rtc_rtime[tmr], new_rtime, rtc_currd[tmr]); rtc_rtime[tmr] = new_rtime; /* reset wall time */ return rtc_currd[tmr]; /* can't calibrate */ } delta_rtime = new_rtime - rtc_rtime[tmr]; /* elapsed wtime */ rtc_rtime[tmr] = new_rtime; /* adv wall time */ rtc_vtime[tmr] = rtc_vtime[tmr] + 1000; /* adv sim time */ if (delta_rtime > 30000) { /* gap too big? */ /* This simulator process has somehow been suspended for a significant */ /* amount of time. This will certainly happen if the host system has */ /* slept or hibernated. It also might happen when a simulator */ /* developer stops the simulator at a breakpoint (a process, not simh */ /* breakpoint). To accomodate this, we set the calibration state to */ /* ignore what happened and proceed from here. */ ++rtc_clock_calib_gap2big[tmr]; /* Count statistic */ rtc_vtime[tmr] = rtc_rtime[tmr]; /* sync virtual and real time */ rtc_nxintv[tmr] = 1000; /* reset next interval */ rtc_gtime[tmr] = sim_gtime(); /* save instruction time */ sim_debug (DBG_CAL, &sim_timer_dev, "gap too big: delta = %d - result: %d\n", delta_rtime, rtc_currd[tmr]); return rtc_currd[tmr]; /* can't calibr */ } if (delta_rtime == 0) /* avoid divide by zero */ last_idle_pct = 0; /* force calibration */ else last_idle_pct = MIN(100, (uint32)(100.0 * (((double)(rtc_clock_time_idled[tmr] - rtc_clock_time_idled_last[tmr])) / ((double)delta_rtime)))); rtc_clock_time_idled_last[tmr] = rtc_clock_time_idled[tmr]; if (last_idle_pct > (100 - sim_idle_calib_pct)) { rtc_rtime[tmr] = new_rtime; /* save wall time */ rtc_vtime[tmr] = rtc_vtime[tmr] + 1000; /* adv sim time */ rtc_gtime[tmr] = sim_gtime(); /* save instruction time */ ++rtc_clock_calib_skip_idle[tmr]; sim_debug (DBG_CAL, &sim_timer_dev, "skipping calibration due to idling (%d%%) - result: %d\n", last_idle_pct, rtc_currd[tmr]); return rtc_currd[tmr]; /* avoid calibrating idle checks */ } new_gtime = sim_gtime(); if ((last_idle_pct == 0) && (delta_rtime != 0)) sim_idle_cyc_ms = (uint32)((new_gtime - rtc_gtime[tmr]) / delta_rtime); if (sim_asynch_timer) { /* An asynchronous clock, merely needs to divide the number of */ /* instructions actually executed by the clock rate. */ new_currd = (int32)((new_gtime - rtc_gtime[tmr])/ticksper); /* avoid excessive swings in the calibrated result */ if (new_currd > 10*rtc_currd[tmr]) /* don't swing big too fast */ new_currd = 10*rtc_currd[tmr]; else if (new_currd < rtc_currd[tmr]/10) /* don't swing small too fast */ new_currd = rtc_currd[tmr]/10; rtc_currd[tmr] = new_currd; rtc_gtime[tmr] = new_gtime; /* save instruction time */ sim_debug (DBG_CAL, &sim_timer_dev, "asynch calibration result: %d\n", rtc_currd[tmr]); return rtc_currd[tmr]; /* calibrated result */ } rtc_gtime[tmr] = new_gtime; /* save instruction time */ /* This self regulating algorithm depends directly on the assumption */ /* that this routine is called back after processing the number of */ /* instructions which was returned the last time it was called. */ if (delta_rtime == 0) /* gap too small? */ rtc_based[tmr] = rtc_based[tmr] * ticksper; /* slew wide */ else rtc_based[tmr] = (int32) (((double) rtc_based[tmr] * (double) rtc_nxintv[tmr]) / ((double) delta_rtime));/* new base rate */ delta_vtime = rtc_vtime[tmr] - rtc_rtime[tmr]; /* gap */ if (delta_vtime > SIM_TMAX) /* limit gap */ delta_vtime = SIM_TMAX; else if (delta_vtime < -SIM_TMAX) delta_vtime = -SIM_TMAX; rtc_nxintv[tmr] = 1000 + delta_vtime; /* next wtime */ rtc_currd[tmr] = (int32) (((double) rtc_based[tmr] * (double) rtc_nxintv[tmr]) / 1000.0); /* next delay */ if (rtc_based[tmr] <= 0) /* never negative or zero! */ rtc_based[tmr] = 1; if (rtc_currd[tmr] <= 0) /* never negative or zero! */ rtc_currd[tmr] = 1; sim_debug (DBG_CAL, &sim_timer_dev, "calibrated tmr=%d, tickper=%d (base=%d, nxintv=%u, result: %d)\n", tmr, ticksper, rtc_based[tmr], rtc_nxintv[tmr], rtc_currd[tmr]); /* Adjust calibration for other timers which depend on this timer's calibration */ for (itmr=0; itmr<=SIM_NTIMERS; itmr++) if ((itmr != tmr) && (rtc_hz[itmr] != 0)) rtc_currd[itmr] = (rtc_currd[tmr] * ticksper) / rtc_hz[itmr]; AIO_SET_INTERRUPT_LATENCY(rtc_currd[tmr] * ticksper); /* set interrrupt latency */ return rtc_currd[tmr]; } /* Prior interfaces - default to timer 0 */ int32 sim_rtc_init (int32 time) { return sim_rtcn_init (time, 0); } int32 sim_rtc_calb (int32 ticksper) { return sim_rtcn_calb (ticksper, 0); } /* sim_timer_init - get minimum sleep time available on this host */ t_bool sim_timer_init (void) { int tmr; uint32 clock_start, clock_last, clock_now; sim_debug (DBG_TRC, &sim_timer_dev, "sim_timer_init()\n"); for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { sim_timer_units[tmr].action = &sim_timer_tick_svc; sim_timer_units[tmr].flags = UNIT_DIS | UNIT_IDLE; sim_clock_cosched_queue[tmr] = QUEUE_LIST_END; } SIM_INTERNAL_UNIT.flags = UNIT_IDLE; sim_register_internal_device (&sim_timer_dev); /* Register Clock Assist device */ sim_throttle_unit.action = &sim_throt_svc; sim_register_clock_unit_tmr (&SIM_INTERNAL_UNIT, SIM_INTERNAL_CLK); sim_idle_enab = FALSE; /* init idle off */ sim_idle_rate_ms = sim_os_ms_sleep_init (); /* get OS timer rate */ sim_set_rom_delay_factor (sim_get_rom_delay_factor ()); /* initialize ROM delay factor */ clock_last = clock_start = sim_os_msec (); sim_os_clock_resoluton_ms = 1000; do { uint32 clock_diff; clock_now = sim_os_msec (); clock_diff = clock_now - clock_last; if ((clock_diff > 0) && (clock_diff < sim_os_clock_resoluton_ms)) sim_os_clock_resoluton_ms = clock_diff; clock_last = clock_now; } while (clock_now < clock_start + 100); sim_os_tick_hz = 1000/(sim_os_clock_resoluton_ms * (sim_idle_rate_ms/sim_os_clock_resoluton_ms)); return (sim_idle_rate_ms != 0); } /* sim_timer_idle_capable - tell if the host is Idle capable and what the host OS tick size is */ t_bool sim_timer_idle_capable (uint32 *host_ms_sleep_1, uint32 *host_tick_ms) { if (host_tick_ms) *host_tick_ms = sim_os_clock_resoluton_ms; if (host_ms_sleep_1) *host_ms_sleep_1 = sim_os_sleep_min_ms; return (sim_idle_rate_ms != 0); } /* sim_show_timers - show running timer information */ t_stat sim_show_timers (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc) { int tmr, clocks; struct timespec now; time_t time_t_now; int32 calb_tmr = (sim_calb_tmr == -1) ? sim_calb_tmr_last : sim_calb_tmr; double inst_per_sec = sim_timer_inst_per_sec (); fprintf (st, "Minimum Host Sleep Time: %d ms (%dHz)\n", sim_os_sleep_min_ms, sim_os_tick_hz); if (sim_os_sleep_min_ms != sim_os_sleep_inc_ms) fprintf (st, "Minimum Host Sleep Incr Time: %d ms\n", sim_os_sleep_inc_ms); fprintf (st, "Host Clock Resolution: %d ms\n", sim_os_clock_resoluton_ms); fprintf (st, "Execution Rate: %s instructions/sec\n", sim_fmt_numeric (inst_per_sec)); if (sim_idle_enab) { fprintf (st, "Idling: Enabled\n"); fprintf (st, "Time before Idling starts: %d seconds\n", sim_idle_stable); } if (sim_throt_type != SIM_THROT_NONE) { sim_show_throt (st, NULL, uptr, val, desc); } fprintf (st, "Calibrated Timer: %s\n", (calb_tmr == -1) ? "Undetermined" : ((calb_tmr == SIM_NTIMERS) ? "Internal Timer" : (sim_clock_unit[calb_tmr] ? sim_uname(sim_clock_unit[calb_tmr]) : ""))); if (calb_tmr == SIM_NTIMERS) fprintf (st, "Catchup Ticks: %s for clocks ticking faster than %d Hz\n", sim_catchup_ticks ? "Enabled" : "Disabled", sim_os_tick_hz); if (sim_idle_calib_pct == 0) fprintf (st, "Calibration: Always\n"); else fprintf (st, "Calibration: Skipped when Idle exceeds %d%%\n", sim_idle_calib_pct); fprintf (st, "\n"); for (tmr=clocks=0; tmr<=SIM_NTIMERS; ++tmr) { if (0 == rtc_initd[tmr]) continue; if (sim_clock_unit[tmr]) { ++clocks; fprintf (st, "%s clock device is %s%s%s\n", sim_name, (tmr == SIM_NTIMERS) ? "Internal Calibrated Timer(" : "", sim_uname(sim_clock_unit[tmr]), (tmr == SIM_NTIMERS) ? ")" : ""); } fprintf (st, "%s%sTimer %d:\n", sim_asynch_timer ? "Asynchronous " : "", rtc_hz[tmr] ? "Calibrated " : "Uncalibrated ", tmr); if (rtc_hz[tmr]) { fprintf (st, " Running at: %d Hz\n", rtc_hz[tmr]); fprintf (st, " Tick Size: %s\n", sim_fmt_secs (rtc_clock_tick_size[tmr])); fprintf (st, " Ticks in current second: %d\n", rtc_ticks[tmr]); } fprintf (st, " Seconds Running: %s (%s)\n", sim_fmt_numeric ((double)rtc_elapsed[tmr]), sim_fmt_secs ((double)rtc_elapsed[tmr])); if (tmr == calb_tmr) { fprintf (st, " Calibration Opportunities: %s\n", sim_fmt_numeric ((double)rtc_calibrations[tmr])); if (sim_idle_calib_pct) fprintf (st, " Calib Skip Idle Thresh %%: %u\n", sim_idle_calib_pct); if (rtc_clock_calib_skip_idle[tmr]) fprintf (st, " Calibs Skip While Idle: %u\n", rtc_clock_calib_skip_idle[tmr]); if (rtc_clock_calib_backwards[tmr]) fprintf (st, " Calibs Skip Backwards: %u\n", rtc_clock_calib_backwards[tmr]); if (rtc_clock_calib_gap2big[tmr]) fprintf (st, " Calibs Skip Gap Too Big: %u\n", rtc_clock_calib_gap2big[tmr]); } if (rtc_gtime[tmr]) fprintf (st, " Instruction Time: %.0f\n", rtc_gtime[tmr]); if ((!sim_asynch_timer) && (sim_throt_type == SIM_THROT_NONE)) { fprintf (st, " Real Time: %u\n", rtc_rtime[tmr]); fprintf (st, " Virtual Time: %u\n", rtc_vtime[tmr]); fprintf (st, " Next Interval: %s\n", sim_fmt_numeric ((double)rtc_nxintv[tmr])); fprintf (st, " Base Tick Delay: %s\n", sim_fmt_numeric ((double)rtc_based[tmr])); fprintf (st, " Initial Insts Per Tick: %s\n", sim_fmt_numeric ((double)rtc_initd[tmr])); } fprintf (st, " Current Insts Per Tick: %s\n", sim_fmt_numeric ((double)rtc_currd[tmr])); fprintf (st, " Initializations: %d\n", rtc_calib_initializations[tmr]); fprintf (st, " Ticks: %s\n", sim_fmt_numeric ((double)(rtc_clock_ticks[tmr]))); if (rtc_clock_ticks_tot[tmr]+rtc_clock_ticks[tmr] != rtc_clock_ticks[tmr]) fprintf (st, " Total Ticks: %s\n", sim_fmt_numeric ((double)(rtc_clock_ticks_tot[tmr]+rtc_clock_ticks[tmr]))); if (rtc_clock_skew_max[tmr] != 0.0) fprintf (st, " Peak Clock Skew: %s%s\n", sim_fmt_secs (fabs(rtc_clock_skew_max[tmr])), (rtc_clock_skew_max[tmr] < 0) ? " fast" : " slow"); if (rtc_calib_ticks_acked[tmr]) fprintf (st, " Ticks Acked: %s\n", sim_fmt_numeric ((double)rtc_calib_ticks_acked[tmr])); if (rtc_calib_ticks_acked_tot[tmr]+rtc_calib_ticks_acked[tmr] != rtc_calib_ticks_acked[tmr]) fprintf (st, " Total Ticks Acked: %s\n", sim_fmt_numeric ((double)(rtc_calib_ticks_acked_tot[tmr]+rtc_calib_ticks_acked[tmr]))); if (rtc_calib_tick_time[tmr]) fprintf (st, " Tick Time: %s\n", sim_fmt_secs (rtc_calib_tick_time[tmr])); if (rtc_calib_tick_time_tot[tmr]+rtc_calib_tick_time[tmr] != rtc_calib_tick_time[tmr]) fprintf (st, " Total Tick Time: %s\n", sim_fmt_secs (rtc_calib_tick_time_tot[tmr]+rtc_calib_tick_time[tmr])); if (rtc_clock_catchup_ticks[tmr]) fprintf (st, " Catchup Ticks Sched: %s\n", sim_fmt_numeric ((double)rtc_clock_catchup_ticks[tmr])); if (rtc_clock_catchup_ticks_tot[tmr]+rtc_clock_catchup_ticks[tmr] != rtc_clock_catchup_ticks[tmr]) fprintf (st, " Total Catchup Ticks Sched: %s\n", sim_fmt_numeric ((double)(rtc_clock_catchup_ticks_tot[tmr]+rtc_clock_catchup_ticks[tmr]))); if (rtc_clock_init_base_time[tmr]) { _double_to_timespec (&now, rtc_clock_init_base_time[tmr]); time_t_now = (time_t)now.tv_sec; fprintf (st, " Initialize Base Time: %8.8s.%03d\n", 11+ctime(&time_t_now), (int)(now.tv_nsec/1000000)); } if (rtc_clock_tick_start_time[tmr]) { _double_to_timespec (&now, rtc_clock_tick_start_time[tmr]); time_t_now = (time_t)now.tv_sec; fprintf (st, " Tick Start Time: %8.8s.%03d\n", 11+ctime(&time_t_now), (int)(now.tv_nsec/1000000)); } clock_gettime (CLOCK_REALTIME, &now); time_t_now = (time_t)now.tv_sec; fprintf (st, " Wall Clock Time Now: %8.8s.%03d\n", 11+ctime(&time_t_now), (int)(now.tv_nsec/1000000)); if (rtc_clock_catchup_eligible[tmr]) { _double_to_timespec (&now, rtc_clock_catchup_base_time[tmr]+rtc_calib_tick_time[tmr]); time_t_now = (time_t)now.tv_sec; fprintf (st, " Catchup Tick Time: %8.8s.%03d\n", 11+ctime(&time_t_now), (int)(now.tv_nsec/1000000)); _double_to_timespec (&now, rtc_clock_catchup_base_time[tmr]); time_t_now = (time_t)now.tv_sec; fprintf (st, " Catchup Base Time: %8.8s.%03d\n", 11+ctime(&time_t_now), (int)(now.tv_nsec/1000000)); } if (rtc_clock_time_idled[tmr]) fprintf (st, " Total Time Idled: %s\n", sim_fmt_secs (rtc_clock_time_idled[tmr]/1000.0)); } if (clocks == 0) fprintf (st, "%s clock device is not specified, co-scheduling is unavailable\n", sim_name); return SCPE_OK; } t_stat sim_show_clock_queues (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { int tmr; #if defined (SIM_ASYNCH_CLOCKS) pthread_mutex_lock (&sim_timer_lock); if (sim_asynch_timer) { const char *tim; struct timespec due; time_t time_t_due; if (sim_wallclock_queue == QUEUE_LIST_END) fprintf (st, "%s wall clock event queue empty\n", sim_name); else { fprintf (st, "%s wall clock event queue status\n", sim_name); for (uptr = sim_wallclock_queue; uptr != QUEUE_LIST_END; uptr = uptr->a_next) { if ((dptr = find_dev_from_unit (uptr)) != NULL) { fprintf (st, " %s", sim_dname (dptr)); if (dptr->numunits > 1) fprintf (st, " unit %d", (int32) (uptr - dptr->units)); } else fprintf (st, " Unknown"); tim = sim_fmt_secs(uptr->a_usec_delay/1000000.0); _double_to_timespec (&due, uptr->a_due_time); time_t_due = (time_t)due.tv_sec; fprintf (st, " after %s due at %8.8s.%06d\n", tim, 11+ctime(&time_t_due), (int)(due.tv_nsec/1000)); } } } #endif /* SIM_ASYNCH_CLOCKS */ for (tmr=0; tmr<=SIM_NTIMERS; ++tmr) { if (sim_clock_unit[tmr] == NULL) continue; if (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) { int32 accum; fprintf (st, "%s clock (%s) co-schedule event queue status\n", sim_name, sim_uname(sim_clock_unit[tmr])); accum = 0; for (uptr = sim_clock_cosched_queue[tmr]; uptr != QUEUE_LIST_END; uptr = uptr->next) { if ((dptr = find_dev_from_unit (uptr)) != NULL) { fprintf (st, " %s", sim_dname (dptr)); if (dptr->numunits > 1) fprintf (st, " unit %d", (int32) (uptr - dptr->units)); } else fprintf (st, " Unknown"); if (accum == 0) fprintf (st, " on next tick"); else fprintf (st, " after %d tick%s", accum, (accum > 1) ? "s" : ""); if (uptr->usecs_remaining) fprintf (st, " plus %.0f usecs", uptr->usecs_remaining); fprintf (st, "\n"); accum = accum + uptr->time; } } } #if defined (SIM_ASYNCH_IO) pthread_mutex_unlock (&sim_timer_lock); #endif /* SIM_ASYNCH_IO */ return SCPE_OK; } REG sim_timer_reg[] = { { DRDATAD (IDLE_CYC_MS, sim_idle_cyc_ms, 32, "Cycles Per Millisecond"), PV_RSPC|REG_RO}, { DRDATAD (ROM_DELAY, sim_rom_delay, 32, "ROM memory reference delay"), PV_RSPC|REG_RO}, { NULL } }; REG sim_throttle_reg[] = { { DRDATAD (THROT_MS_START, sim_throt_ms_start, 32, ""), PV_RSPC|REG_RO}, { DRDATAD (THROT_MS_STOP, sim_throt_ms_stop, 32, ""), PV_RSPC|REG_RO}, { DRDATAD (THROT_TYPE, sim_throt_type, 32, ""), PV_RSPC|REG_RO}, { DRDATAD (THROT_VAL, sim_throt_val, 32, ""), PV_RSPC|REG_RO}, { DRDATAD (THROT_STATE, sim_throt_state, 32, ""), PV_RSPC|REG_RO}, { DRDATAD (THROT_SLEEP_TIME, sim_throt_sleep_time, 32, ""), PV_RSPC|REG_RO}, { DRDATAD (THROT_WAIT, sim_throt_wait, 32, ""), PV_RSPC|REG_RO}, { NULL } }; /* Clear, Set and show catchup */ /* Set/Clear catchup */ t_stat sim_timer_set_catchup (int32 flag, CONST char *cptr) { if (flag) { if (!sim_catchup_ticks) sim_catchup_ticks = TRUE; } else { if (sim_catchup_ticks) sim_catchup_ticks = FALSE; } return SCPE_OK; } t_stat sim_timer_show_catchup (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { fprintf (st, "Calibrated Ticks%s", sim_catchup_ticks ? " with Catchup Ticks" : ""); return SCPE_OK; } /* Set idle calibration threshold */ t_stat sim_timer_set_idle_pct (int32 flag, CONST char *cptr) { t_stat r; int32 newpct; if (cptr == NULL) return SCPE_ARG; newpct = (int32) get_uint (cptr, 10, 100, &r); if ((r != SCPE_OK) || (newpct == (int32)(sim_idle_calib_pct))) return r; if (newpct == 0) return SCPE_ARG; sim_idle_calib_pct = (uint32)newpct; return SCPE_OK; } /* Set/Clear asynch */ t_stat sim_timer_set_async (int32 flag, CONST char *cptr) { if (flag) { if (sim_asynch_enabled && (!sim_asynch_timer)) { sim_asynch_timer = TRUE; sim_timer_change_asynch (); } } else { if (sim_asynch_timer) { sim_asynch_timer = FALSE; sim_timer_change_asynch (); } } return SCPE_OK; } static CTAB set_timer_tab[] = { #if defined (SIM_ASYNCH_CLOCKS) { "ASYNCH", &sim_timer_set_async, 1 }, { "NOASYNCH", &sim_timer_set_async, 0 }, #endif { "CATCHUP", &sim_timer_set_catchup, 1 }, { "NOCATCHUP", &sim_timer_set_catchup, 0 }, { "CALIB", &sim_timer_set_idle_pct, 0 }, { NULL, NULL, 0 } }; MTAB sim_timer_mod[] = { { 0 }, }; static t_stat sim_timer_clock_reset (DEVICE *dptr); static const char *sim_timer_description (DEVICE *dptr) { return "Clock Assist facilities"; } static const char *sim_int_timer_description (DEVICE *dptr) { return "Internal Timer"; } static const char *sim_throttle_description (DEVICE *dptr) { return "Throttle facility"; } DEVICE sim_timer_dev = { "INT-CLOCK", sim_timer_units, sim_timer_reg, sim_timer_mod, SIM_NTIMERS+1, 0, 0, 0, 0, 0, NULL, NULL, &sim_timer_clock_reset, NULL, NULL, NULL, NULL, DEV_DEBUG | DEV_NOSAVE, 0, sim_timer_debug}; DEVICE sim_int_timer_dev = { "INT-TIMER", &sim_internal_timer_unit, NULL, NULL, 1, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, DEV_NOSAVE}; DEVICE sim_throttle_dev = { "INT-THROTTLE", &sim_throttle_unit, sim_throttle_reg, NULL, 1}; /* SET CLOCK command */ t_stat sim_set_timers (int32 arg, CONST char *cptr) { char *cvptr, gbuf[CBUFSIZE]; CTAB *ctptr; t_stat r; if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; while (*cptr != 0) { /* do all mods */ cptr = get_glyph_nc (cptr, gbuf, ','); /* get modifier */ if ((cvptr = strchr (gbuf, '='))) /* = value? */ *cvptr++ = 0; get_glyph (gbuf, gbuf, 0); /* modifier to UC */ if ((ctptr = find_ctab (set_timer_tab, gbuf))) { /* match? */ r = ctptr->action (ctptr->arg, cvptr); /* do the rest */ if (r != SCPE_OK) return r; } else return SCPE_NOPARAM; } return SCPE_OK; } /* sim_idle - idle simulator until next event or for specified interval Inputs: tmr = calibrated timer to use Must solve the linear equation ms_to_wait = w * ms_per_wait Or w = ms_to_wait / ms_per_wait */ t_bool sim_idle (uint32 tmr, int sin_cyc) { uint32 w_ms, w_idle, act_ms; int32 act_cyc; if (rtc_clock_catchup_pending[tmr]) { /* Catchup clock tick pending? */ sim_debug (DBG_CAL, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d) - accelerating pending catch-up tick before idling %s\n", tmr, sin_cyc, sim_uname (sim_clock_unit[tmr])); sim_activate_abs (&sim_timer_units[tmr], 0); sim_interval -= sin_cyc; return FALSE; } if ((!sim_idle_enab) || /* idling disabled */ ((sim_clock_queue == QUEUE_LIST_END) && /* or clock queue empty? */ (!sim_asynch_timer))|| /* and not asynch? */ ((sim_clock_queue != QUEUE_LIST_END) && /* or clock queue not empty */ ((sim_clock_queue->flags & UNIT_IDLE) == 0))|| /* and event not idle-able? */ (rtc_elapsed[tmr] < sim_idle_stable)) { /* or timer not stable? */ sim_debug (DBG_IDL, &sim_timer_dev, "Can't idle: %s - elapsed: %d.%03d\n", !sim_idle_enab ? "idle disabled" : ((rtc_elapsed[tmr] < sim_idle_stable) ? "not stable" : ((sim_clock_queue != QUEUE_LIST_END) ? sim_uname (sim_clock_queue) : "")), rtc_elapsed[tmr], rtc_ticks[tmr]); sim_interval -= sin_cyc; return FALSE; } if (_rtcn_tick_catchup_check(tmr, 0)) { sim_debug (DBG_CAL, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d) - rescheduling catchup tick for %s\n", tmr, sin_cyc, sim_uname (sim_clock_unit[tmr])); sim_interval -= sin_cyc; return FALSE; } /* When a simulator is in an instruction path (or under other conditions which would indicate idling), the countdown of sim_interval will not be happening at a pace which is consistent with the rate it happens when not in the 'idle capable' state. The consequence of this is that the clock calibration may produce calibrated results which vary much more than they do when not in the idle able state. Sim_idle also uses the calibrated tick size to approximate an adjustment to sim_interval to reflect the number of instructions which would have executed during the actual idle time, so consistent calibrated numbers produce better adjustments. To negate this effect, we accumulate the time actually idled here. sim_rtcn_calb compares the accumulated idle time during the most recent second and if it exceeds the percentage defined by and sim_idle_calib_pct calibration is suppressed. Thus recalibration only happens if things didn't idle too much. we also check check sim_idle_enab above so that all simulators can avoid directly checking sim_idle_enab before calling sim_idle so that all of the bookkeeping on sim_idle_idled is done here in sim_timer where it means something, while not idling when it isn't enabled. */ sim_debug (DBG_TRC, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d)\n", tmr, sin_cyc); if (sim_idle_cyc_ms == 0) sim_idle_cyc_ms = (rtc_currd[tmr] * rtc_hz[tmr]) / 1000;/* cycles per msec */ if ((sim_idle_rate_ms == 0) || (sim_idle_cyc_ms == 0)) {/* not possible? */ sim_interval -= sin_cyc; sim_debug (DBG_IDL, &sim_timer_dev, "not possible idle_rate_ms=%d - cyc/ms=%d\n", sim_idle_rate_ms, sim_idle_cyc_ms); return FALSE; } w_ms = (uint32) sim_interval / sim_idle_cyc_ms; /* ms to wait */ /* When the host system has a clock tick which is less frequent than the */ /* simulated system's clock, idling will cause delays which will miss */ /* simulated clock ticks. To accomodate this, and still allow idling, if */ /* the simulator acknowledges the processing of clock ticks, then catchup */ /* ticks can be used to make up for missed ticks. */ if (rtc_clock_catchup_eligible[tmr]) w_idle = (sim_interval * 1000) / rtc_currd[tmr]; /* 1000 * pending fraction of tick */ else w_idle = (w_ms * 1000) / sim_idle_rate_ms; /* 1000 * intervals to wait */ if (w_idle < 500) { /* shorter than 1/2 the interval? */ sim_interval -= sin_cyc; sim_debug (DBG_IDL, &sim_timer_dev, "no wait\n"); return FALSE; } if (sim_clock_queue == QUEUE_LIST_END) sim_debug (DBG_IDL, &sim_timer_dev, "sleeping for %d ms - pending event in %d instructions\n", w_ms, sim_interval); else sim_debug (DBG_IDL, &sim_timer_dev, "sleeping for %d ms - pending event on %s in %d instructions\n", w_ms, sim_uname(sim_clock_queue), sim_interval); act_ms = sim_idle_ms_sleep (w_ms); /* wait */ rtc_clock_time_idled[tmr] += act_ms; act_cyc = act_ms * sim_idle_cyc_ms; act_cyc += (sim_idle_cyc_ms * sim_idle_rate_ms) / 2; /* account for half an interval's worth of cycles */ if (sim_interval > act_cyc) sim_interval = sim_interval - act_cyc; /* count down sim_interval */ else sim_interval = 0; /* or fire immediately */ if (sim_clock_queue == QUEUE_LIST_END) sim_debug (DBG_IDL, &sim_timer_dev, "slept for %d ms - pending event in %d instructions\n", act_ms, sim_interval); else sim_debug (DBG_IDL, &sim_timer_dev, "slept for %d ms - pending event on %s in %d instructions\n", act_ms, sim_uname(sim_clock_queue), sim_interval); return TRUE; } /* Set idling - implicitly disables throttling */ t_stat sim_set_idle (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { t_stat r; uint32 v; if (cptr && *cptr) { v = (uint32) get_uint (cptr, 10, SIM_IDLE_STMAX, &r); if ((r != SCPE_OK) || (v < SIM_IDLE_STMIN)) return sim_messagef (SCPE_ARG, "Invalid Stability value: %s. Valid values range from %d to %d.\n", cptr, SIM_IDLE_STMIN, SIM_IDLE_STMAX); sim_idle_stable = v; } sim_idle_enab = TRUE; if (sim_throt_type != SIM_THROT_NONE) { sim_set_throt (0, NULL); sim_printf ("Throttling disabled\n"); } return SCPE_OK; } /* Clear idling */ t_stat sim_clr_idle (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { sim_idle_enab = FALSE; return SCPE_OK; } /* Show idling */ t_stat sim_show_idle (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { if (sim_idle_enab) fprintf (st, "idle enabled"); else fprintf (st, "idle disabled"); if (sim_switches & SWMASK ('D')) fprintf (st, ", stability wait = %ds, minimum sleep resolution = %dms", sim_idle_stable, sim_os_sleep_min_ms); return SCPE_OK; } /* Throttling package */ t_stat sim_set_throt (int32 arg, CONST char *cptr) { CONST char *tptr; char c; t_value val, val2 = 0; if (arg == 0) { if ((cptr != NULL) && (*cptr != 0)) return sim_messagef (SCPE_ARG, "Unexpected NOTHROTTLE argument: %s\n", cptr); sim_throt_type = SIM_THROT_NONE; sim_throt_cancel (); } else if (sim_idle_rate_ms == 0) { return sim_messagef (SCPE_NOFNC, "Throttling is not available, Minimum OS sleep time is %dms\n", sim_os_sleep_min_ms); } else { if (*cptr == '\0') return sim_messagef (SCPE_ARG, "Missing throttle mode specification\n"); val = strtotv (cptr, &tptr, 10); if (cptr == tptr) return sim_messagef (SCPE_ARG, "Invalid throttle specification: %s\n", cptr); sim_throt_sleep_time = sim_idle_rate_ms; c = (char)toupper (*tptr++); if (c == '/') { val2 = strtotv (tptr, &tptr, 10); if ((*tptr != '\0') || (val == 0)) return sim_messagef (SCPE_ARG, "Invalid throttle delay specifier: %s\n", cptr); } if (c == 'M') sim_throt_type = SIM_THROT_MCYC; else if (c == 'K') sim_throt_type = SIM_THROT_KCYC; else if ((c == '%') && (val > 0) && (val < 100)) sim_throt_type = SIM_THROT_PCT; else if ((c == '/') && (val2 != 0)) sim_throt_type = SIM_THROT_SPC; else return sim_messagef (SCPE_ARG, "Invalid throttle specification: %s\n", cptr); if (sim_idle_enab) { sim_printf ("Idling disabled\n"); sim_clr_idle (NULL, 0, NULL, NULL); } sim_throt_val = (uint32) val; if (sim_throt_type == SIM_THROT_SPC) { if (val2 >= sim_idle_rate_ms) sim_throt_sleep_time = (uint32) val2; else { if ((sim_idle_rate_ms % val2) == 0) { sim_throt_sleep_time = sim_idle_rate_ms; sim_throt_val = (uint32) (val * (sim_idle_rate_ms / val2)); } else { sim_throt_sleep_time = sim_idle_rate_ms; sim_throt_val = (uint32) (val * (1 + (sim_idle_rate_ms / val2))); } } } } sim_register_internal_device (&sim_throttle_dev); /* Register Throttle Device */ sim_throt_cps = SIM_INITIAL_IPS; /* Initial value while correct one is determined */ return SCPE_OK; } t_stat sim_show_throt (FILE *st, DEVICE *dnotused, UNIT *unotused, int32 flag, CONST char *cptr) { if (sim_idle_rate_ms == 0) fprintf (st, "Throttling: Not Available\n"); else { switch (sim_throt_type) { case SIM_THROT_MCYC: fprintf (st, "Throttle: %d megacycles\n", sim_throt_val); if (sim_throt_wait) fprintf (st, "Throttling by sleeping for: %d ms every %d cycles\n", sim_throt_sleep_time, sim_throt_wait); break; case SIM_THROT_KCYC: fprintf (st, "Throttle: %d kilocycles\n", sim_throt_val); if (sim_throt_wait) fprintf (st, "Throttling by sleeping for: %d ms every %d cycles\n", sim_throt_sleep_time, sim_throt_wait); break; case SIM_THROT_PCT: fprintf (st, "Throttle: %d%%\n", sim_throt_val); if (sim_throt_wait) fprintf (st, "Throttling by sleeping for: %d ms every %d cycles\n", sim_throt_sleep_time, sim_throt_wait); break; case SIM_THROT_SPC: fprintf (st, "Throttle: sleep %d ms every %d cycles\n", sim_throt_sleep_time, sim_throt_val); break; default: fprintf (st, "Throttling: Disabled\n"); break; } if (sim_throt_type != SIM_THROT_NONE) { if (sim_throt_state != SIM_THROT_STATE_THROTTLE) fprintf (st, "Throttle State: %s - wait: %d\n", (sim_throt_state == SIM_THROT_STATE_INIT) ? "Waiting for Init" : "Timing", sim_throt_wait); } } return SCPE_OK; } void sim_throt_sched (void) { sim_throt_state = SIM_THROT_STATE_INIT; if (sim_throt_type) sim_activate (&sim_throttle_unit, SIM_THROT_WINIT); } void sim_throt_cancel (void) { sim_cancel (&sim_throttle_unit); } /* Throttle service Throttle service has three distinct states used while dynamically determining a throttling interval: SIM_THROT_STATE_INIT take initial measurement SIM_THROT_STATE_TIME take final measurement, calculate wait values SIM_THROT_STATE_THROTTLE periodic waits to slow down the CPU */ t_stat sim_throt_svc (UNIT *uptr) { int32 tmr; uint32 delta_ms; double a_cps, d_cps; if (sim_throt_type == SIM_THROT_SPC) { /* Non dynamic? */ sim_throt_state = SIM_THROT_STATE_THROTTLE; /* force state */ sim_throt_wait = sim_throt_val; } switch (sim_throt_state) { case SIM_THROT_STATE_INIT: /* take initial reading */ sim_idle_ms_sleep (sim_idle_rate_ms); /* start on a tick boundart to calibrate */ sim_throt_ms_start = sim_os_msec (); sim_throt_inst_start = sim_gtime(); sim_throt_wait = SIM_THROT_WST; sim_throt_state = SIM_THROT_STATE_TIME; /* next state */ sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc(INIT) Starting. Values wait = %d\n", sim_throt_wait); break; /* reschedule */ case SIM_THROT_STATE_TIME: /* take final reading */ sim_throt_ms_stop = sim_os_msec (); delta_ms = sim_throt_ms_stop - sim_throt_ms_start; if (delta_ms < SIM_THROT_MSMIN) { /* not enough time? */ if (sim_throt_wait >= 100000000) { /* too many inst? */ sim_throt_state = SIM_THROT_STATE_INIT; /* fails in 32b! */ sim_printf ("Can't throttle. Host CPU is too fast with a minimum sleep time of %d ms\n", sim_idle_rate_ms); sim_set_throt (0, NULL); /* disable throttling */ return SCPE_OK; } sim_idle_ms_sleep (sim_idle_rate_ms); /* start on a tick boundart to calibrate */ sim_throt_wait = sim_throt_wait * SIM_THROT_WMUL; sim_throt_ms_start = sim_os_msec (); sim_throt_inst_start = sim_gtime(); } else { /* long enough */ a_cps = ((double) sim_throt_wait) * 1000.0 / (double) delta_ms; if (sim_throt_type == SIM_THROT_MCYC) /* calc desired cps */ d_cps = (double) sim_throt_val * 1000000.0; else if (sim_throt_type == SIM_THROT_KCYC) d_cps = (double) sim_throt_val * 1000.0; else d_cps = (a_cps * ((double) sim_throt_val)) / 100.0; if (d_cps >= a_cps) { sim_throt_state = SIM_THROT_STATE_INIT; sim_printf ("Host CPU is too slow to simulate %s instructions per second\n", sim_fmt_numeric(d_cps)); sim_printf ("Throttling disabled.\n"); sim_set_throt (0, NULL); return SCPE_OK; } while (1) { sim_throt_wait = (int32) /* time between waits */ ((a_cps * d_cps * ((double) sim_throt_sleep_time)) / (1000.0 * (a_cps - d_cps))); if (sim_throt_wait >= SIM_THROT_WMIN) /* long enough? */ break; sim_throt_sleep_time += sim_os_sleep_inc_ms; sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Wait too small, increasing sleep time to %d ms. Values a_cps = %f, d_cps = %f, wait = %d\n", sim_throt_sleep_time, a_cps, d_cps, sim_throt_wait); } sim_throt_ms_start = sim_throt_ms_stop; sim_throt_inst_start = sim_gtime(); sim_throt_state = SIM_THROT_STATE_THROTTLE; sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Throttle values a_cps = %f, d_cps = %f, wait = %d, sleep = %d ms\n", a_cps, d_cps, sim_throt_wait, sim_throt_sleep_time); sim_throt_cps = d_cps; /* save the desired rate */ /* Run through all timers and adjust the calibration for each */ /* one that is running to reflect the throttle rate */ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) if (rtc_hz[tmr]) { /* running? */ rtc_gtime[tmr] = sim_gtime(); /* save instruction time */ rtc_currd[tmr] = (int32)(sim_throt_cps / rtc_hz[tmr]);/* use throttle calibration */ } } break; case SIM_THROT_STATE_THROTTLE: /* throttling */ sim_idle_ms_sleep (sim_throt_sleep_time); delta_ms = sim_os_msec () - sim_throt_ms_start; if (sim_throt_type != SIM_THROT_SPC) { /* when not dynamic throttling */ if (delta_ms >= 10000) { /* recompute every 10 sec */ double delta_insts = sim_gtime() - sim_throt_inst_start; a_cps = (delta_insts * 1000.0) / (double) delta_ms; if (sim_throt_type == SIM_THROT_MCYC) /* calc desired cps */ d_cps = (double) sim_throt_val * 1000000.0; else if (sim_throt_type == SIM_THROT_KCYC) d_cps = (double) sim_throt_val * 1000.0; else d_cps = (a_cps * ((double) sim_throt_val)) / 100.0; if (fabs(100.0 * (d_cps - a_cps) / a_cps) > (double)SIM_THROT_DRIFT_PCT) { sim_throt_wait = sim_throt_val; sim_throt_state = SIM_THROT_STATE_TIME;/* next state to recalibrate */ sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Recalibrating throttle based on values a_cps = %f, d_cps = %f\n", a_cps, d_cps); } sim_throt_ms_start = sim_os_msec (); sim_throt_inst_start = sim_gtime(); } } else /* record instruction rate */ sim_throt_cps = (int32)((1000.0 * sim_throt_val) / (double)delta_ms); break; } sim_activate (uptr, sim_throt_wait); /* reschedule */ return SCPE_OK; } /* Clock assist activites */ t_stat sim_timer_tick_svc (UNIT *uptr) { int32 tmr = (int32)(uptr-sim_timer_units); t_stat stat; rtc_clock_ticks[tmr] += 1; rtc_calib_tick_time[tmr] += rtc_clock_tick_size[tmr]; /* * Some devices may depend on executing during the same instruction or * immediately after the clock tick event. To satisfy this, we directly * run the clock event here and if it completes successfully, schedule any * currently coschedule units to run now. Ticks should never return a * non-success status, while co-schedule activities might, so they are * queued to run from sim_process_event */ sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_tick_svc(tmr=%d) - scheduling %s - cosched interval: %d\n", tmr, sim_uname (sim_clock_unit[tmr]), sim_cosched_interval[tmr]); if (sim_clock_unit[tmr]->action == NULL) return SCPE_IERR; stat = sim_clock_unit[tmr]->action (sim_clock_unit[tmr]); --sim_cosched_interval[tmr]; /* Countdown ticks */ if (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) sim_clock_cosched_queue[tmr]->time = sim_cosched_interval[tmr]; if ((stat == SCPE_OK) && (sim_cosched_interval[tmr] <= 0) && (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END)) { if (rtc_clock_catchup_eligible[tmr]) { /* calibration started? */ struct timespec now; double skew; clock_gettime(CLOCK_REALTIME, &now); skew = (_timespec_to_double(&now) - (rtc_calib_tick_time[tmr]+rtc_clock_catchup_base_time[tmr])); if (fabs(skew) > fabs(rtc_clock_skew_max[tmr])) rtc_clock_skew_max[tmr] = skew; } do { UNIT *cptr = sim_clock_cosched_queue[tmr]; sim_clock_cosched_queue[tmr] = cptr->next; cptr->next = NULL; cptr->cancel = NULL; cptr->time = 0; if (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) { sim_clock_cosched_queue[tmr]->time += sim_cosched_interval[tmr]; sim_cosched_interval[tmr] = sim_clock_cosched_queue[tmr]->time; } else sim_cosched_interval[tmr] = 0; cptr->time = 0; sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_tick_svc(tmr=%d) - coactivating %s", tmr, sim_uname (cptr)); if (cptr->usecs_remaining) { sim_debug (DBG_QUE, &sim_timer_dev, " remnant: %.0f - next %s after cosched interval: %d ticks\n", cptr->usecs_remaining, (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) ? sim_uname (sim_clock_cosched_queue[tmr]) : "", sim_cosched_interval[tmr]); sim_timer_activate_after (cptr, cptr->usecs_remaining); } else { sim_debug (DBG_QUE, &sim_timer_dev, " - next %s after cosched interval: %d ticks\n", (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) ? sim_uname (sim_clock_cosched_queue[tmr]) : "", sim_cosched_interval[tmr]); _sim_activate (cptr, 0); } } while ((sim_cosched_interval[tmr] <= 0) && (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END)); } return stat; } void sim_rtcn_get_time (struct timespec *now, int tmr) { sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_get_time(tmr=%d)\n", tmr); clock_gettime (CLOCK_REALTIME, now); } /* * If the host system has a relatively large clock tick (as compared to * the desired simulated hz) ticks will naturally be scheduled late and * these delays will accumulate. The net result will be unreasonably * slow ticks being delivered to the simulated system. * Additionally, when a simulator is idling and/or throttling, it will * deliberately call sim_os_ms_sleep and those sleep operations will be * variable and subject to the host system's minimum sleep resolution * which can exceed the desired sleep interval and add to the concept * of slow tick delivery to the simulated system. * We accomodate these problems and make up for lost ticks by injecting * catch-up ticks to the simulator. * * When necessary, catch-up ticks are scheduled to run under one * of two conditions: * 1) after indicated number of instructions in a call by the simulator * to sim_rtcn_tick_ack. sim_rtcn_tick_ack exists to provide a * mechanism to inform the simh timer facilities when the simulated * system has accepted the most recent clock tick interrupt. * 2) immediately when the simulator calls sim_idle * * catchup ticks are only scheduled (eligible to happen) under these * conditions after at least one tick has been acknowledged. */ /* _rtcn_tick_catchup_check - idle simulator until next event or for specified interval Inputs: tmr = calibrated timer to check/schedule time = instruction delay for next tick Returns TRUE if a catchup tick has been scheduled */ static t_bool _rtcn_tick_catchup_check (int32 tmr, int32 time) { if ((!sim_catchup_ticks) || ((tmr < 0) || (tmr >= SIM_NTIMERS))) return FALSE; if ((rtc_hz[tmr] > sim_os_tick_hz) && /* faster than host tick */ (!rtc_clock_catchup_eligible[tmr]) && /* not eligible yet? */ (time != -1)) { /* called from ack? */ rtc_clock_catchup_base_time[tmr] = sim_timenow_double(); rtc_clock_ticks_tot[tmr] += rtc_clock_ticks[tmr]; rtc_clock_ticks[tmr] = 0; rtc_calib_tick_time_tot[tmr] += rtc_calib_tick_time[tmr]; rtc_calib_tick_time[tmr] = 0.0; rtc_clock_catchup_ticks_tot[tmr] += rtc_clock_catchup_ticks[tmr]; rtc_clock_catchup_ticks[tmr] = 0; rtc_calib_ticks_acked_tot[tmr] += rtc_calib_ticks_acked[tmr]; rtc_calib_ticks_acked[tmr] = 0; rtc_clock_catchup_eligible[tmr] = TRUE; sim_debug (DBG_QUE, &sim_timer_dev, "_rtcn_tick_catchup_check() - Enabling catchup ticks for %s\n", sim_uname (sim_clock_unit[tmr])); return TRUE; } if (rtc_clock_catchup_eligible[tmr]) { double tnow = sim_timenow_double(); if (tnow > (rtc_clock_catchup_base_time[tmr] + (rtc_calib_tick_time[tmr] + rtc_clock_tick_size[tmr]))) { sim_debug (DBG_QUE, &sim_timer_dev, "_rtcn_tick_catchup_check(%d) - scheduling catchup tick for %s which is behind %s\n", time, sim_uname (sim_clock_unit[tmr]), sim_fmt_secs (tnow > (rtc_clock_catchup_base_time[tmr] + (rtc_calib_tick_time[tmr] + rtc_clock_tick_size[tmr])))); rtc_clock_catchup_pending[tmr] = TRUE; sim_activate_abs (&sim_timer_units[tmr], (time < 0) ? 0 : time); return TRUE; } } return FALSE; } t_stat sim_rtcn_tick_ack (uint32 time, int32 tmr) { if ((tmr < 0) || (tmr >= SIM_NTIMERS)) return SCPE_TIMER; sim_debug (DBG_ACK, &sim_timer_dev, "sim_rtcn_tick_ack - for %s\n", sim_uname (sim_clock_unit[tmr])); _rtcn_tick_catchup_check (tmr, (int32)time); ++rtc_calib_ticks_acked[tmr]; return SCPE_OK; } static double _timespec_to_double (struct timespec *time) { return ((double)time->tv_sec)+(double)(time->tv_nsec)/1000000000.0; } static void _double_to_timespec (struct timespec *time, double dtime) { time->tv_sec = (time_t)floor(dtime); time->tv_nsec = (long)((dtime-floor(dtime))*1000000000.0); } double sim_timenow_double (void) { struct timespec now; clock_gettime (CLOCK_REALTIME, &now); return _timespec_to_double (&now); } #if defined(SIM_ASYNCH_CLOCKS) pthread_t sim_timer_thread; /* Wall Clock Timing Thread Id */ pthread_cond_t sim_timer_startup_cond; t_bool sim_timer_thread_running = FALSE; static void * _timer_thread(void *arg) { int sched_policy; struct sched_param sched_priority; /* Boost Priority for this I/O thread vs the CPU instruction execution thread which, in general, won't be readily yielding the processor when this thread needs to run */ pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority); ++sched_priority.sched_priority; pthread_setschedparam (pthread_self(), sched_policy, &sched_priority); sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - starting\n"); pthread_mutex_lock (&sim_timer_lock); pthread_cond_signal (&sim_timer_startup_cond); /* Signal we're ready to go */ while (sim_asynch_timer && sim_is_running) { struct timespec start_time, stop_time; struct timespec due_time; double wait_usec; int32 inst_delay; double inst_per_sec; UNIT *uptr, *cptr, *prvptr; if (sim_wallclock_entry) { /* something to insert in queue? */ sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - timing %s for %s\n", sim_uname(sim_wallclock_entry), sim_fmt_secs (sim_wallclock_entry->a_usec_delay/1000000.0)); uptr = sim_wallclock_entry; sim_wallclock_entry = NULL; prvptr = NULL; for (cptr = sim_wallclock_queue; cptr != QUEUE_LIST_END; cptr = cptr->a_next) { if (uptr->a_due_time < cptr->a_due_time) break; prvptr = cptr; } if (prvptr == NULL) { /* insert at head */ cptr = uptr->a_next = sim_wallclock_queue; sim_wallclock_queue = uptr; } else { cptr = uptr->a_next = prvptr->a_next; /* insert at prvptr */ prvptr->a_next = uptr; } } /* determine wait time */ if (sim_wallclock_queue != QUEUE_LIST_END) { /* due time adjusted by 1/2 a minimal sleep interval */ /* the goal being to let the last fractional part of the due time */ /* be done by counting instructions */ _double_to_timespec (&due_time, sim_wallclock_queue->a_due_time-(((double)sim_idle_rate_ms)*0.0005)); } else { due_time.tv_sec = 0x7FFFFFFF; /* Sometime when 32 bit time_t wraps */ due_time.tv_nsec = 0; } clock_gettime(CLOCK_REALTIME, &start_time); wait_usec = floor(1000000.0*(_timespec_to_double (&due_time) - _timespec_to_double (&start_time))); if (sim_wallclock_queue == QUEUE_LIST_END) sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - waiting forever\n"); else sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - waiting for %.0f usecs until %.6f for %s\n", wait_usec, sim_wallclock_queue->a_due_time, sim_uname(sim_wallclock_queue)); if ((wait_usec <= 0.0) || (0 != pthread_cond_timedwait (&sim_timer_wake, &sim_timer_lock, &due_time))) { if (sim_wallclock_queue == QUEUE_LIST_END) /* queue empty? */ continue; /* wait again */ inst_per_sec = sim_timer_inst_per_sec (); uptr = sim_wallclock_queue; sim_wallclock_queue = uptr->a_next; uptr->a_next = NULL; /* hygiene */ clock_gettime(CLOCK_REALTIME, &stop_time); if (1 != sim_timespec_compare (&due_time, &stop_time)) inst_delay = 0; else inst_delay = (int32)(inst_per_sec*(_timespec_to_double(&due_time)-_timespec_to_double(&stop_time))); sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - slept %.0fms - activating(%s,%d)\n", 1000.0*(_timespec_to_double (&stop_time)-_timespec_to_double (&start_time)), sim_uname(uptr), inst_delay); sim_activate (uptr, inst_delay); } else {/* Something wants to adjust the queue since the wait condition was signaled */ } } pthread_mutex_unlock (&sim_timer_lock); sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - exiting\n"); return NULL; } #endif /* defined(SIM_ASYNCH_CLOCKS) */ /* In the event that there are no active clock devices, no instruction rate calibration will be performed. This is more likely on simpler simulators which don't have a full spectrum of standard devices or possibly when a clock device exists but its use is optional. Additonally, when a host system has a natural clock tick (or minimal sleep time) which is greater than the tick size that a simulator wants to run a clock at, we run this clock at the rate implied by the host system's minimal sleep time or 50Hz. To solve this we merely run an internal clock at 10Hz. */ #define CLK_TPS 10 #define CLK_INIT (SIM_INITIAL_IPS/CLK_TPS) static int32 sim_int_clk_tps; static t_stat sim_timer_clock_tick_svc (UNIT *uptr) { sim_rtcn_calb (sim_int_clk_tps, SIM_INTERNAL_CLK); sim_activate_after (uptr, 1000000/sim_int_clk_tps); /* reactivate unit */ return SCPE_OK; } /* This routine exists to assure that there is a single reliably calibrated clock properly counting instruction execution relative to time. The best way to assure reliable calibration is to use a clock which ticks no faster than the host system's clock. This is optimal so that accurate time measurements are taken. If the simulated system doesn't have a clock with an appropriate tick rate, an internal clock is run that meets this requirement, */ static void _rtcn_configure_calibrated_clock (int32 newtmr) { int32 tmr; /* Look for a timer running slower than the host system clock */ sim_int_clk_tps = MIN(CLK_TPS, sim_os_tick_hz); for (tmr=0; tmr<SIM_NTIMERS; tmr++) { if ((rtc_hz[tmr]) && (rtc_hz[tmr] <= (uint32)sim_os_tick_hz) && (sim_clock_unit[tmr])) break; } if (tmr == SIM_NTIMERS) { /* None found? */ if ((tmr != newtmr) && (!sim_is_active (&SIM_INTERNAL_UNIT))) { if ((sim_calb_tmr != SIM_NTIMERS) &&/* not internal timer? */ (sim_calb_tmr != -1) && /* previously active? */ (!rtc_hz[sim_calb_tmr])) { /* now stopped? */ sim_debug (DBG_CAL, &sim_timer_dev, "_rtcn_configure_calibrated_clock(newtmr=%d) - Cleaning up stopped timer %s support\n", newtmr, sim_uname(sim_clock_unit[sim_calb_tmr])); /* Migrate any coscheduled devices to the standard queue */ /* with appropriate usecs_remaining reflecting their currently */ /* scheduled firing time. sim_process_event() will coschedule */ /* appropriately. */ /* temporarily restore prior hz to get correct remaining time */ rtc_hz[sim_calb_tmr] = rtc_last_hz[sim_calb_tmr]; while (sim_clock_cosched_queue[sim_calb_tmr] != QUEUE_LIST_END) { UNIT *uptr = sim_clock_cosched_queue[sim_calb_tmr]; double usecs_remaining = sim_timer_activate_time_usecs (uptr) - 1; _sim_coschedule_cancel (uptr); _sim_activate (uptr, 1); uptr->usecs_remaining = usecs_remaining; } rtc_hz[sim_calb_tmr] = 0; /* back to 0 */ if (sim_clock_unit[sim_calb_tmr]) sim_cancel (sim_clock_unit[sim_calb_tmr]); sim_cancel (&sim_timer_units[sim_calb_tmr]); } /* Start the internal timer */ sim_calb_tmr = SIM_NTIMERS; sim_debug (DBG_CAL, &sim_timer_dev, "_rtcn_configure_calibrated_clock(newtmr=%d) - Starting Internal Calibrated Timer at %dHz\n", newtmr, sim_int_clk_tps); SIM_INTERNAL_UNIT.action = &sim_timer_clock_tick_svc; SIM_INTERNAL_UNIT.flags = UNIT_IDLE; sim_register_internal_device (&sim_int_timer_dev); /* Register Internal timer device */ sim_rtcn_init_unit (&SIM_INTERNAL_UNIT, (CLK_INIT*CLK_TPS)/sim_int_clk_tps, SIM_INTERNAL_CLK); SIM_INTERNAL_UNIT.action (&SIM_INTERNAL_UNIT); /* Force tick to activate timer */ } return; } if ((tmr == newtmr) && (sim_calb_tmr == newtmr)) /* already set? */ return; if (sim_calb_tmr == SIM_NTIMERS) { /* was old the internal timer? */ sim_debug (DBG_CAL, &sim_timer_dev, "_rtcn_configure_calibrated_clock(newtmr=%d) - Stopping Internal Calibrated Timer, New Timer = %d (%dHz)\n", newtmr, tmr, rtc_hz[tmr]); rtc_initd[SIM_NTIMERS] = 0; rtc_hz[SIM_NTIMERS] = 0; sim_register_clock_unit_tmr (NULL, SIM_INTERNAL_CLK); sim_cancel (&SIM_INTERNAL_UNIT); sim_cancel (&sim_timer_units[SIM_NTIMERS]); } else { if ((sim_calb_tmr != -1) && (rtc_hz[sim_calb_tmr] == 0)) { /* Migrate any coscheduled devices to the standard queue */ /* with appropriate usecs_remaining reflecting their currently */ /* scheduled firing time. sim_process_event() will coschedule */ /* appropriately. */ /* temporarily restore prior hz to get correct remaining time */ rtc_hz[sim_calb_tmr] = rtc_last_hz[sim_calb_tmr]; while (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) { UNIT *uptr = sim_clock_cosched_queue[tmr]; double usecs_remaining = sim_timer_activate_time_usecs (uptr) - 1; _sim_coschedule_cancel (uptr); _sim_activate (uptr, 1); uptr->usecs_remaining = usecs_remaining; } rtc_hz[sim_calb_tmr] = 0; /* back to 0 */ } sim_debug (DBG_CAL, &sim_timer_dev, "_rtcn_configure_calibrated_clock(newtmr=%d) - Changing Calibrated Timer from %d (%dHz) to %d (%dHz)\n", newtmr, sim_calb_tmr, rtc_hz[sim_calb_tmr], tmr, rtc_hz[tmr]); sim_calb_tmr = tmr; } sim_calb_tmr = tmr; } static t_stat sim_timer_clock_reset (DEVICE *dptr) { sim_debug (DBG_TRC, &sim_timer_dev, "sim_timer_clock_reset()\n"); _rtcn_configure_calibrated_clock (sim_calb_tmr); sim_timer_dev.description = &sim_timer_description; sim_throttle_dev.description = &sim_throttle_description; sim_int_timer_dev.description = &sim_int_timer_description; if (sim_switches & SWMASK ('P')) { sim_cancel (&SIM_INTERNAL_UNIT); sim_calb_tmr = -1; } return SCPE_OK; } void sim_start_timer_services (void) { sim_debug (DBG_TRC, &sim_timer_dev, "sim_start_timer_services()\n"); _rtcn_configure_calibrated_clock (sim_calb_tmr); #if defined(SIM_ASYNCH_CLOCKS) pthread_mutex_lock (&sim_timer_lock); if (sim_asynch_timer) { pthread_attr_t attr; sim_debug (DBG_TRC, &sim_timer_dev, "sim_start_timer_services() - starting\n"); pthread_cond_init (&sim_timer_startup_cond, NULL); pthread_attr_init (&attr); pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); pthread_create (&sim_timer_thread, &attr, _timer_thread, NULL); pthread_attr_destroy( &attr); pthread_cond_wait (&sim_timer_startup_cond, &sim_timer_lock); /* Wait for thread to stabilize */ pthread_cond_destroy (&sim_timer_startup_cond); sim_timer_thread_running = TRUE; } pthread_mutex_unlock (&sim_timer_lock); #endif } void sim_stop_timer_services (void) { int tmr; sim_debug (DBG_TRC, &sim_timer_dev, "sim_stop_timer_services()\n"); for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { int32 accum; if (sim_clock_unit[tmr]) { int32 clock_time = _sim_activate_time (&sim_timer_units[tmr]); if (clock_time < 0) clock_time = 0; /* Stop clock assist unit and make sure the clock unit has a tick queued */ sim_cancel (&sim_timer_units[tmr]); if (rtc_hz[tmr]) { sim_debug (DBG_QUE, &sim_timer_dev, "sim_stop_timer_services() - tmr=%d scheduling %s after %d\n", tmr, sim_uname (sim_clock_unit[tmr]), clock_time); _sim_activate (sim_clock_unit[tmr], clock_time); } /* Move coscheduled units to the standard event queue */ accum = 0; while (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) { UNIT *cptr = sim_clock_cosched_queue[tmr]; double usecs_remaining = cptr->usecs_remaining; cptr->usecs_remaining = 0; sim_clock_cosched_queue[tmr] = cptr->next; cptr->next = NULL; cptr->cancel = NULL; accum += cptr->time; sim_debug (DBG_QUE, &sim_timer_dev, "sim_stop_timer_services() - tmr=%d scheduling %s after %d\n", tmr, sim_uname (cptr), clock_time + accum*rtc_currd[tmr]); _sim_activate (cptr, clock_time + accum*rtc_currd[tmr]); cptr->usecs_remaining = usecs_remaining; } sim_cosched_interval[tmr] = 0; } } sim_cancel (&SIM_INTERNAL_UNIT); /* Make sure Internal Timer is stopped */ sim_cancel (&sim_timer_units[SIM_NTIMERS]); sim_calb_tmr_last = sim_calb_tmr; /* Save calibrated timer value for display */ sim_inst_per_sec_last = sim_timer_inst_per_sec (); /* Save execution rate for display */ sim_calb_tmr = -1; #if defined(SIM_ASYNCH_CLOCKS) pthread_mutex_lock (&sim_timer_lock); if (sim_timer_thread_running) { sim_debug (DBG_TRC, &sim_timer_dev, "sim_stop_timer_services() - stopping\n"); pthread_cond_signal (&sim_timer_wake); pthread_mutex_unlock (&sim_timer_lock); pthread_join (sim_timer_thread, NULL); sim_timer_thread_running = FALSE; /* Any wallclock queued events are now migrated to the normal event queue */ while (sim_wallclock_queue != QUEUE_LIST_END) { UNIT *uptr = sim_wallclock_queue; double inst_delay_d = uptr->a_due_gtime - sim_gtime (); int32 inst_delay; uptr->cancel (uptr); if (inst_delay_d < 0.0) inst_delay_d = 0.0; /* Bound delay to avoid overflow. */ /* Long delays are usually canceled before they expire */ if (inst_delay_d > (double)0x7FFFFFFF) inst_delay_d = (double)0x7FFFFFFF; inst_delay = (int32)inst_delay_d; if ((inst_delay == 0) && (inst_delay_d != 0.0)) inst_delay = 1; /* Minimum non-zero delay is 1 instruction */ _sim_activate (uptr, inst_delay); /* queue it now */ } } else pthread_mutex_unlock (&sim_timer_lock); #endif } t_stat sim_timer_change_asynch (void) { #if defined(SIM_ASYNCH_CLOCKS) if (sim_asynch_enabled && sim_asynch_timer) sim_start_timer_services (); else sim_stop_timer_services (); #endif return SCPE_OK; } /* Instruction Execution rate. */ /* returns a double since it is mostly used in double expressions and to avoid overflow if/when strange timing delays might produce unexpected results */ double sim_timer_inst_per_sec (void) { double inst_per_sec = sim_inst_per_sec_last; if (sim_calb_tmr == -1) return inst_per_sec; inst_per_sec = ((double)rtc_currd[sim_calb_tmr])*rtc_hz[sim_calb_tmr]; if (0 == inst_per_sec) inst_per_sec = ((double)rtc_currd[sim_calb_tmr])*sim_int_clk_tps; return inst_per_sec; } t_stat sim_timer_activate (UNIT *uptr, int32 interval) { AIO_VALIDATE; return sim_timer_activate_after (uptr, (double)((interval * 1000000.0) / sim_timer_inst_per_sec ())); } t_stat sim_timer_activate_after (UNIT *uptr, double usec_delay) { UNIT *ouptr = uptr; int inst_delay, tmr; double inst_delay_d, inst_per_usec; t_stat stat; AIO_VALIDATE; /* If this is a clock unit, we need to schedule the related timer unit instead */ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) if (sim_clock_unit[tmr] == uptr) { uptr = &sim_timer_units[tmr]; break; } if (sim_is_active (uptr)) /* already active? */ return SCPE_OK; uptr->usecs_remaining = 0; if (usec_delay <= 0.0) { sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - invalid usec value\n", sim_uname(uptr), usec_delay); return SCPE_ARG; } /* * Handle long delays by aligning with the calibrated timer's calibration * activities. Delays which would expire prior to the next calibration * are specifically scheduled directly based on the the current instruction * execution rate. Longer delays are coscheduled to fire on the first tick * after the next calibration and at that time are either scheduled directly * or re-coscheduled for the next calibration time, repeating until the total * desired time has elapsed. */ inst_per_usec = sim_timer_inst_per_sec () / 1000000.0; inst_delay_d = floor(inst_per_usec * usec_delay); inst_delay = (int32)inst_delay_d; if ((inst_delay == 0) && (usec_delay != 0)) inst_delay_d = inst_delay = 1; /* Minimum non-zero delay is 1 instruction */ if ((sim_calb_tmr != -1) && (rtc_hz[sim_calb_tmr])) { /* Calibrated Timer available? */ int32 inst_til_tick = sim_activate_time (&sim_timer_units[sim_calb_tmr]) - 1; int32 ticks_til_calib = rtc_hz[sim_calb_tmr] - rtc_ticks[sim_calb_tmr]; int32 inst_til_calib = inst_til_tick + ((ticks_til_calib - 1) * rtc_currd[sim_calb_tmr]); uint32 usecs_til_calib = (uint32)ceil(inst_til_calib / inst_per_usec); if (uptr != &sim_timer_units[sim_calb_tmr]) { /* Not scheduling calibrated timer? */ if (inst_delay_d >= (double)inst_til_calib) { /* long wait? */ stat = sim_clock_coschedule_tmr (uptr, sim_calb_tmr, ticks_til_calib - 1); uptr->usecs_remaining = (stat == SCPE_OK) ? usec_delay - usecs_til_calib : 0.0; sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - coscheduling with with calibrated timer(%d), ticks=%d, usecs_remaining=%.0f usecs, inst_til_tick=%d\n", sim_uname(uptr), usec_delay, sim_calb_tmr, ticks_til_calib, uptr->usecs_remaining, inst_til_tick); sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n", sim_uname(uptr), usec_delay, sim_timer_activate_time_usecs (ouptr), sim_timer_activate_time_usecs (uptr)); return stat; } } } /* * We're here to schedule if: * No Calibrated Timer, OR * Scheduling the Calibrated Timer OR * Short delay */ /* * Bound delay to avoid overflow. * Long delays are usually canceled before they expire, however bounding the * delay will cause sim_activate_time to return inconsistent results when * truncation has happened. */ if (inst_delay_d > (double)0x7fffffff) inst_delay_d = (double)0x7fffffff; /* Bound delay to avoid overflow. */ inst_delay = (int32)inst_delay_d; #if defined(SIM_ASYNCH_CLOCKS) if ((sim_asynch_timer) && (usec_delay > sim_idle_rate_ms*1000.0)) { double d_now = sim_timenow_double (); UNIT *cptr, *prvptr; uptr->a_usec_delay = usec_delay; uptr->a_due_time = d_now + (usec_delay / 1000000.0); uptr->a_due_gtime = sim_gtime () + (sim_timer_inst_per_sec () * (usec_delay / 1000000.0)); uptr->cancel = &_sim_wallclock_cancel; /* bind cleanup method */ uptr->a_is_active = &_sim_wallclock_is_active; if (tmr <= SIM_NTIMERS) { /* Timer Unit? */ sim_clock_unit[tmr]->cancel = &_sim_wallclock_cancel; sim_clock_unit[tmr]->a_is_active = &_sim_wallclock_is_active; } sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queueing wallclock addition at %.6f\n", sim_uname(uptr), usec_delay, uptr->a_due_time); pthread_mutex_lock (&sim_timer_lock); for (cptr = sim_wallclock_queue, prvptr = NULL; cptr != QUEUE_LIST_END; cptr = cptr->a_next) { if (uptr->a_due_time < cptr->a_due_time) break; prvptr = cptr; } if (prvptr == NULL) { /* inserting at head */ uptr->a_next = QUEUE_LIST_END; /* Temporarily mark as active */ while (sim_wallclock_entry) { /* wait for any prior entry has been digested */ sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queue insert entry %s busy waiting for 1ms\n", sim_uname(uptr), usec_delay, sim_uname(sim_wallclock_entry)); pthread_mutex_unlock (&sim_timer_lock); sim_os_ms_sleep (1); pthread_mutex_lock (&sim_timer_lock); } sim_wallclock_entry = uptr; pthread_mutex_unlock (&sim_timer_lock); pthread_cond_signal (&sim_timer_wake); /* wake the timer thread to deal with it */ return SCPE_OK; } else { /* inserting at prvptr */ uptr->a_next = prvptr->a_next; prvptr->a_next = uptr; pthread_mutex_unlock (&sim_timer_lock); return SCPE_OK; } } #endif stat = _sim_activate (uptr, inst_delay); /* queue it now */ uptr->usecs_remaining = ((stat == SCPE_OK) && (0.0 < (usec_delay - ceil(inst_delay / inst_per_usec) ))) ? usec_delay - floor(inst_delay / inst_per_usec) : 0.0; sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queue addition at %d - remnant: %.0f\n", sim_uname(uptr), usec_delay, inst_delay, uptr->usecs_remaining); sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n", sim_uname(uptr), usec_delay, sim_timer_activate_time_usecs (ouptr), sim_timer_activate_time_usecs (uptr)); return stat; } /* Clock coscheduling routines */ t_stat sim_register_clock_unit_tmr (UNIT *uptr, int32 tmr) { if (tmr == SIM_INTERNAL_CLK) tmr = SIM_NTIMERS; else { if ((tmr < 0) || (tmr > SIM_NTIMERS)) return SCPE_IERR; } if (NULL == uptr) { /* deregistering? */ /* Migrate any coscheduled devices to the standard queue */ /* they will fire and subsequently requeue themselves */ while (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) { UNIT *uptr = sim_clock_cosched_queue[tmr]; double usecs_remaining = sim_timer_activate_time_usecs (uptr); _sim_coschedule_cancel (uptr); _sim_activate (uptr, 1); uptr->usecs_remaining = usecs_remaining; } if (sim_clock_unit[tmr]) { sim_cancel (sim_clock_unit[tmr]); sim_clock_unit[tmr]->dynflags &= ~UNIT_TMR_UNIT; } sim_clock_unit[tmr] = NULL; sim_cancel (&sim_timer_units[tmr]); return SCPE_OK; } if (NULL == sim_clock_unit[tmr]) sim_clock_cosched_queue[tmr] = QUEUE_LIST_END; sim_clock_unit[tmr] = uptr; uptr->dynflags |= UNIT_TMR_UNIT; sim_timer_units[tmr].flags = ((tmr == SIM_NTIMERS) ? 0 : UNIT_DIS) | (sim_clock_unit[tmr] ? UNIT_IDLE : 0); return SCPE_OK; } /* Default timer is 0, otherwise use a calibrated one if it exists */ int32 sim_rtcn_calibrated_tmr (void) { return ((rtc_currd[0] && rtc_hz[0]) ? 0 : ((sim_calb_tmr != -1) ? sim_calb_tmr : 0)); } int32 sim_rtcn_tick_size (int32 tmr) { return (rtc_currd[tmr]) ? rtc_currd[tmr] : 10000; } t_stat sim_register_clock_unit (UNIT *uptr) { return sim_register_clock_unit_tmr (uptr, 0); } t_stat sim_clock_coschedule (UNIT *uptr, int32 interval) { int32 tmr = sim_rtcn_calibrated_tmr (); int32 ticks = (interval + (sim_rtcn_tick_size (tmr)/2))/sim_rtcn_tick_size (tmr);/* Convert to ticks */ sim_debug (DBG_QUE, &sim_timer_dev, "sim_clock_coschedule(%s, interval=%d, ticks=%d)\n", sim_uname(uptr), interval, ticks); return sim_clock_coschedule_tmr (uptr, tmr, ticks); } t_stat sim_clock_coschedule_abs (UNIT *uptr, int32 interval) { sim_debug (DBG_QUE, &sim_timer_dev, "sim_clock_coschedule_abs(%s, interval=%d)\n", sim_uname(uptr), interval); sim_cancel (uptr); return sim_clock_coschedule (uptr, interval); } /* ticks - 0 means on the next tick, 1 means the second tick, etc. */ t_stat sim_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 ticks) { if (ticks < 0) return SCPE_ARG; if (sim_is_active (uptr)) { sim_debug (DBG_TIM, &sim_timer_dev, "sim_clock_coschedule_tmr(%s, tmr=%d, ticks=%d) - already active\n", sim_uname (uptr), tmr, ticks); return SCPE_OK; } if (tmr == SIM_INTERNAL_CLK) tmr = SIM_NTIMERS; else { if ((tmr < 0) || (tmr > SIM_NTIMERS)) return sim_activate (uptr, MAX(1, ticks) * 10000); } if ((NULL == sim_clock_unit[tmr]) || (rtc_hz[tmr] == 0)) { sim_debug (DBG_TIM, &sim_timer_dev, "sim_clock_coschedule_tmr(%s, tmr=%d, ticks=%d) - no clock activating after %d instructions\n", sim_uname (uptr), tmr, ticks, ticks * (rtc_currd[tmr] ? rtc_currd[tmr] : rtc_currd[sim_rtcn_calibrated_tmr ()])); return sim_activate (uptr, ticks * (rtc_currd[tmr] ? rtc_currd[tmr] : rtc_currd[sim_rtcn_calibrated_tmr ()])); } else { UNIT *cptr, *prvptr; int32 accum; if (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) sim_clock_cosched_queue[tmr]->time = sim_cosched_interval[tmr]; prvptr = NULL; accum = 0; for (cptr = sim_clock_cosched_queue[tmr]; cptr != QUEUE_LIST_END; cptr = cptr->next) { if (ticks < (accum + cptr->time)) break; accum += cptr->time; prvptr = cptr; } if (prvptr == NULL) { cptr = uptr->next = sim_clock_cosched_queue[tmr]; sim_clock_cosched_queue[tmr] = uptr; } else { cptr = uptr->next = prvptr->next; prvptr->next = uptr; } uptr->time = ticks - accum; if (cptr != QUEUE_LIST_END) cptr->time = cptr->time - uptr->time; uptr->cancel = &_sim_coschedule_cancel; /* bind cleanup method */ if (uptr == sim_clock_cosched_queue[tmr]) sim_cosched_interval[tmr] = sim_clock_cosched_queue[tmr]->time; sim_debug (DBG_QUE, &sim_timer_dev, "sim_clock_coschedule_tmr(%s, tmr=%d, ticks=%d, hz=%d) - queueing for clock co-schedule, interval now: %d\n", sim_uname (uptr), tmr, ticks, rtc_hz[tmr], sim_cosched_interval[tmr]); } return SCPE_OK; } t_stat sim_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 ticks) { sim_cancel (uptr); return sim_clock_coschedule_tmr (uptr, tmr, ticks); } /* Cancel a unit on the coschedule queue */ static t_bool _sim_coschedule_cancel (UNIT *uptr) { AIO_UPDATE_QUEUE; if (uptr->next) { /* On a queue? */ int tmr; UNIT *nptr; for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { if (sim_clock_unit[tmr]) { if (uptr == sim_clock_cosched_queue[tmr]) { nptr = sim_clock_cosched_queue[tmr] = uptr->next; uptr->next = NULL; } else { UNIT *cptr; for (cptr = sim_clock_cosched_queue[tmr]; (cptr != QUEUE_LIST_END); cptr = cptr->next) { if (cptr->next == uptr) { nptr = cptr->next = (uptr)->next; uptr->next = NULL; break; } } } if (uptr->next == NULL) { /* found? */ uptr->cancel = NULL; uptr->usecs_remaining = 0; if (nptr != QUEUE_LIST_END) nptr->time += uptr->time; sim_debug (DBG_QUE, &sim_timer_dev, "Canceled Clock Coscheduled Event for %s\n", sim_uname(uptr)); return TRUE; } } } } return FALSE; } t_bool sim_timer_is_active (UNIT *uptr) { int32 tmr; if (!(uptr->dynflags & UNIT_TMR_UNIT)) return FALSE; for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { if (sim_clock_unit[tmr] == uptr) return sim_is_active (&sim_timer_units[tmr]); } return FALSE; } t_bool sim_timer_cancel (UNIT *uptr) { int32 tmr; if (!(uptr->dynflags & UNIT_TMR_UNIT)) return SCPE_IERR; for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { if (sim_clock_unit[tmr] == uptr) return sim_cancel (&sim_timer_units[tmr]); } return SCPE_IERR; } #if defined(SIM_ASYNCH_CLOCKS) static t_bool _sim_wallclock_cancel (UNIT *uptr) { int32 tmr; t_bool b_return = FALSE; AIO_UPDATE_QUEUE; pthread_mutex_lock (&sim_timer_lock); /* If this is a clock unit, we need to cancel both this and the related timer unit */ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) if (sim_clock_unit[tmr] == uptr) { uptr = &sim_timer_units[tmr]; break; } if (uptr->a_next) { UNIT *cptr; if (uptr == sim_wallclock_entry) { /* Pending on the queue? */ sim_wallclock_entry = NULL; uptr->a_next = NULL; } else { if (uptr == sim_wallclock_queue) { sim_wallclock_queue = uptr->a_next; uptr->a_next = NULL; sim_debug (DBG_QUE, &sim_timer_dev, "Canceling Timer Event for %s\n", sim_uname(uptr)); pthread_cond_signal (&sim_timer_wake); } else { for (cptr = sim_wallclock_queue; (cptr != QUEUE_LIST_END); cptr = cptr->a_next) { if (cptr->a_next == (uptr)) { cptr->a_next = (uptr)->a_next; uptr->a_next = NULL; sim_debug (DBG_QUE, &sim_timer_dev, "Canceled Timer Event for %s\n", sim_uname(uptr)); break; } } } } if (uptr->a_next == NULL) { uptr->a_due_time = uptr->a_due_gtime = uptr->a_usec_delay = 0; uptr->cancel = NULL; uptr->a_is_active = NULL; if (tmr <= SIM_NTIMERS) { /* Timer Unit? */ sim_clock_unit[tmr]->cancel = NULL; sim_clock_unit[tmr]->a_is_active = NULL; } b_return = TRUE; } } pthread_mutex_unlock (&sim_timer_lock); return b_return; } static t_bool _sim_wallclock_is_active (UNIT *uptr) { int32 tmr; if (uptr->a_next) return TRUE; /* If this is a clock unit, we need to examine the related timer unit instead */ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) if (sim_clock_unit[tmr] == uptr) return (sim_timer_units[tmr].a_next != NULL); return FALSE; } #endif /* defined(SIM_ASYNCH_CLOCKS) */ int32 _sim_timer_activate_time (UNIT *uptr) { UNIT *cptr; int32 tmr; #if defined(SIM_ASYNCH_CLOCKS) if (uptr->a_is_active == &_sim_wallclock_is_active) { double d_result; pthread_mutex_lock (&sim_timer_lock); if (uptr == sim_wallclock_entry) { d_result = uptr->a_due_gtime - sim_gtime (); if (d_result < 0.0) d_result = 0.0; if (d_result > (double)0x7FFFFFFE) d_result = (double)0x7FFFFFFE; pthread_mutex_unlock (&sim_timer_lock); return ((int32)d_result) + 1; } for (cptr = sim_wallclock_queue; cptr != QUEUE_LIST_END; cptr = cptr->a_next) if (uptr == cptr) { d_result = uptr->a_due_gtime - sim_gtime (); if (d_result < 0.0) d_result = 0.0; if (d_result > (double)0x7FFFFFFE) d_result = (double)0x7FFFFFFE; pthread_mutex_unlock (&sim_timer_lock); return ((int32)d_result) + 1; } pthread_mutex_unlock (&sim_timer_lock); } if (uptr->a_next) return uptr->a_event_time + 1; #endif /* defined(SIM_ASYNCH_CLOCKS) */ if (uptr->cancel == &_sim_coschedule_cancel) { for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { int32 accum = 0; for (cptr = sim_clock_cosched_queue[tmr]; cptr != QUEUE_LIST_END; cptr = cptr->next) { if (cptr == sim_clock_cosched_queue[tmr]) { if (sim_cosched_interval[tmr] > 0) accum += sim_cosched_interval[tmr]; } else accum += cptr->time; if (cptr == uptr) return (rtc_currd[tmr] * accum) + sim_activate_time (&sim_timer_units[tmr]); } } } for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { if ((uptr == &sim_timer_units[tmr]) && (uptr->next)){ return _sim_activate_time (&sim_timer_units[tmr]); } } return -1; /* Not found. */ } double sim_timer_activate_time_usecs (UNIT *uptr) { UNIT *cptr; int32 tmr; double result = -1.0; /* If this is a clock unit, we need to return the related clock assist unit instead */ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { if (sim_clock_unit[tmr] == uptr) { uptr = &sim_timer_units[tmr]; break; } } if (!sim_is_active (uptr)) { sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) - not active\n", sim_uname (uptr)); return result; } #if defined(SIM_ASYNCH_CLOCKS) if (uptr->a_is_active == &_sim_wallclock_is_active) { pthread_mutex_lock (&sim_timer_lock); if (uptr == sim_wallclock_entry) { result = uptr->a_due_gtime - sim_gtime (); if (result < 0.0) result = 0.0; pthread_mutex_unlock (&sim_timer_lock); result = uptr->usecs_remaining + (1000000.0 * (result / sim_timer_inst_per_sec ())) + 1; sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) wallclock_entry - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ()); return result; } for (cptr = sim_wallclock_queue; cptr != QUEUE_LIST_END; cptr = cptr->a_next) if (uptr == cptr) { result = uptr->a_due_gtime - sim_gtime (); if (result < 0.0) result = 0.0; pthread_mutex_unlock (&sim_timer_lock); result = uptr->usecs_remaining + (1000000.0 * (result / sim_timer_inst_per_sec ())) + 1; sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) wallclock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ()); return result; } pthread_mutex_unlock (&sim_timer_lock); } if (uptr->a_next) { result = uptr->usecs_remaining + (1000000.0 * (uptr->a_event_time / sim_timer_inst_per_sec ())) + 1; sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) asynch - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ()); return result; } #endif /* defined(SIM_ASYNCH_CLOCKS) */ if (uptr->cancel == &_sim_coschedule_cancel) { for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { int32 accum = 0; for (cptr = sim_clock_cosched_queue[tmr]; cptr != QUEUE_LIST_END; cptr = cptr->next) { if (cptr == sim_clock_cosched_queue[tmr]) { if (sim_cosched_interval[tmr] > 0) accum += sim_cosched_interval[tmr]; } else accum += cptr->time; if (cptr == uptr) { result = uptr->usecs_remaining + ceil(1000000.0 * ((rtc_currd[tmr] * accum) + sim_activate_time (&sim_timer_units[tmr]) - 1) / sim_timer_inst_per_sec ()); sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) coscheduled - %.0f usecs, inst_per_sec=%.0f, tmr=%d, ticksize=%d, ticks=%d, inst_til_tick=%d\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), tmr, rtc_currd[tmr], accum, sim_activate_time (&sim_timer_units[tmr]) - 1); return result; } } } } for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { if ((uptr == sim_clock_unit[tmr]) && (uptr->next)) { result = sim_clock_unit[tmr]->usecs_remaining + (1000000.0 * (sim_activate_time (&sim_timer_units[tmr]) - 1)) / sim_timer_inst_per_sec (); sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ()); return result; } if ((uptr == &sim_timer_units[tmr]) && (uptr->next)){ result = uptr->usecs_remaining + (1000000.0 * (sim_activate_time (uptr) - 1)) / sim_timer_inst_per_sec (); sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ()); return result; } } result = uptr->usecs_remaining + (1000000.0 * (sim_activate_time (uptr) - 1)) / sim_timer_inst_per_sec (); sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ()); return result; /* Not found. */ } /* read only memory delayed support Some simulation activities need a 'regulated' memory access time to meet timing assumptions in the code being executed. The default calibration determines a way to limit activities to 1Mhz for each call to sim_rom_read_with_delay(). If a simulator needs a different delay factor, the 1 Mhz initial value can be queried with sim_get_rom_delay_factor() and the result can be adjusted as nessary and the operating delay can be set with sim_set_rom_delay_factor(). */ SIM_NOINLINE static int32 _rom_swapb(int32 val) { return ((val << 24) & 0xff000000) | (( val << 8) & 0xff0000) | ((val >> 8) & 0xff00) | ((val >> 24) & 0xff); } static volatile int32 rom_loopval = 0; SIM_NOINLINE int32 sim_rom_read_with_delay (int32 val) { uint32 i, l = sim_rom_delay; for (i = 0; i < l; i++) rom_loopval |= (rom_loopval + val) ^ _rom_swapb (_rom_swapb (rom_loopval + val)); return val + rom_loopval; } SIM_NOINLINE uint32 sim_get_rom_delay_factor (void) { /* Calibrate the loop delay factor at startup. Do this 4 times and use the largest value computed. The goal here is to come up with a delay factor which will throttle a 6 byte delay loop running from ROM address space to execute 1 instruction per usec */ if (sim_rom_delay == 0) { uint32 i, ts, te, c = 10000, samples = 0; while (1) { c = c * 2; te = sim_os_msec(); while (te == (ts = sim_os_msec ())); /* align on ms tick */ /* This is merely a busy wait with some "work" that won't get optimized away by a good compiler. loopval always is zero. To avoid smart compilers, the loopval variable is referenced in the function arguments so that the function expression is not loop invariant. It also must be referenced by subsequent code to avoid the whole computation being eliminated. */ for (i = 0; i < c; i++) rom_loopval |= (rom_loopval + ts) ^ _rom_swapb (_rom_swapb (rom_loopval + ts)); te = sim_os_msec (); if ((te - ts) < 50) /* sample big enough? */ continue; if (sim_rom_delay < (rom_loopval + (c / (te - ts) / 1000) + 1)) sim_rom_delay = rom_loopval + (c / (te - ts) / 1000) + 1; if (++samples >= 4) break; c = c / 2; } if (sim_rom_delay < 5) sim_rom_delay = 5; } return sim_rom_delay; } void sim_set_rom_delay_factor (uint32 delay) { sim_rom_delay = delay; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | /* sim_timer.h: simulator timer library headers Copyright (c) 1993-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. 28-Apr-07 RMS Added sim_rtc_init_all 17-Oct-06 RMS Added idle support 02-Jan-04 RMS Split out from SCP */ #ifndef SIM_TIMER_H_ #define SIM_TIMER_H_ 0 #ifdef __cplusplus extern "C" { #endif /* Pick up a struct timespec definition if it is available */ #include <time.h> #if defined(__struct_timespec_defined) #define _TIMESPEC_DEFINED #endif #if defined(SIM_ASYNCH_IO) || defined(USE_READER_THREAD) #include <pthread.h> #endif #if defined (__APPLE__) #define HAVE_STRUCT_TIMESPEC 1 /* OSX defined the structure but doesn't tell us */ #endif /* on HP-UX, CLOCK_REALTIME is enum, not preprocessor define */ #if !defined(CLOCK_REALTIME) && !defined(__hpux) #define CLOCK_REALTIME 1 #define NEED_CLOCK_GETTIME 1 #if defined(_MSC_VER) /* Visual Studio/Visual C++ */ #if _MSC_VER >= 1900 /* Visual Studio Community (2015) */ #define HAVE_STRUCT_TIMESPEC 1 #define _TIMESPEC_DEFINED 1 #endif /* _MSC_VER >= 1900 */ #endif /* defined(_MSC_VER) */ #if !defined(HAVE_STRUCT_TIMESPEC) #define HAVE_STRUCT_TIMESPEC 1 #if !defined(_TIMESPEC_DEFINED) #define _TIMESPEC_DEFINED struct timespec { time_t tv_sec; long tv_nsec; }; #endif /* !defined(_TIMESPEC_DEFINED) */ #endif /* !defined(HAVE_STRUCT_TIMESPEC) */ int clock_gettime(int clock_id, struct timespec *tp); #endif #define SIM_NTIMERS 8 /* # timers */ #define SIM_TMAX 500 /* max timer makeup */ #define SIM_INITIAL_IPS 500000 /* uncalibrated assumption */ /* about instructions per second */ #define SIM_IDLE_CAL 10 /* ms to calibrate */ #define SIM_IDLE_STMIN 2 /* min sec for stability */ #define SIM_IDLE_STDFLT 20 /* dft sec for stability */ #define SIM_IDLE_STMAX 600 /* max sec for stability */ #define SIM_THROT_WINIT 1000 /* cycles to skip */ #define SIM_THROT_WST 10000 /* initial wait */ #define SIM_THROT_WMUL 4 /* multiplier */ #define SIM_THROT_WMIN 50 /* min wait */ #define SIM_THROT_DRIFT_PCT 5 /* drift percentage for recalibrate */ #define SIM_THROT_MSMIN 10 /* min for measurement */ #define SIM_THROT_NONE 0 /* throttle parameters */ #define SIM_THROT_MCYC 1 /* MegaCycles Per Sec */ #define SIM_THROT_KCYC 2 /* KiloCycles Per Sec */ #define SIM_THROT_PCT 3 /* Max Percent of host CPU */ #define SIM_THROT_SPC 4 /* Specific periodic Delay */ #define SIM_THROT_STATE_INIT 0 /* Starting */ #define SIM_THROT_STATE_TIME 1 /* Checking Time */ #define SIM_THROT_STATE_THROTTLE 2 /* Throttling */ #define TIMER_DBG_IDLE 0x001 /* Debug Flag for Idle Debugging */ #define TIMER_DBG_QUEUE 0x002 /* Debug Flag for Asynch Queue Debugging */ #define TIMER_DBG_MUX 0x004 /* Debug Flag for Asynch Queue Debugging */ t_bool sim_timer_init (void); void sim_timespec_diff (struct timespec *diff, struct timespec *min, struct timespec *sub); double sim_timenow_double (void); int32 sim_rtcn_init (int32 time, int32 tmr); int32 sim_rtcn_init_unit (UNIT *uptr, int32 time, int32 tmr); void sim_rtcn_get_time (struct timespec *now, int tmr); t_stat sim_rtcn_tick_ack (uint32 time, int32 tmr); void sim_rtcn_init_all (void); int32 sim_rtcn_calb (int32 ticksper, int32 tmr); int32 sim_rtc_init (int32 time); int32 sim_rtc_calb (int32 ticksper); t_stat sim_set_timers (int32 arg, CONST char *cptr); t_stat sim_show_timers (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc); t_stat sim_show_clock_queues (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_bool sim_idle (uint32 tmr, int sin_cyc); t_stat sim_set_throt (int32 arg, CONST char *cptr); t_stat sim_show_throt (FILE *st, DEVICE *dnotused, UNIT *unotused, int32 flag, CONST char *cptr); t_stat sim_set_idle (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_clr_idle (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_show_idle (FILE *st, UNIT *uptr, int32 val, CONST void *desc); void sim_throt_sched (void); void sim_throt_cancel (void); uint32 sim_os_msec (void); void sim_os_sleep (unsigned int sec); uint32 sim_os_ms_sleep (unsigned int msec); uint32 sim_os_ms_sleep_init (void); void sim_start_timer_services (void); void sim_stop_timer_services (void); t_stat sim_timer_change_asynch (void); t_stat sim_timer_activate (UNIT *uptr, int32 interval); t_stat sim_timer_activate_after (UNIT *uptr, double usec_delay); int32 _sim_timer_activate_time (UNIT *uptr); double sim_timer_activate_time_usecs (UNIT *uptr); t_bool sim_timer_is_active (UNIT *uptr); t_bool sim_timer_cancel (UNIT *uptr); t_stat sim_register_clock_unit (UNIT *uptr); t_stat sim_register_clock_unit_tmr (UNIT *uptr, int32 tmr); t_stat sim_clock_coschedule (UNIT *uptr, int32 interval); t_stat sim_clock_coschedule_abs (UNIT *uptr, int32 interval); t_stat sim_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 ticks); t_stat sim_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 ticks); double sim_timer_inst_per_sec (void); int32 sim_rtcn_tick_size (int32 tmr); int32 sim_rtcn_calibrated_tmr (void); t_bool sim_timer_idle_capable (uint32 *host_ms_sleep_1, uint32 *host_tick_ms); #define PRIORITY_BELOW_NORMAL -1 #define PRIORITY_NORMAL 0 #define PRIORITY_ABOVE_NORMAL 1 t_stat sim_os_set_thread_priority (int below_normal_above); uint32 sim_get_rom_delay_factor (void); void sim_set_rom_delay_factor (uint32 delay); int32 sim_rom_read_with_delay (int32 val); extern t_bool sim_idle_enab; /* idle enabled flag */ extern volatile t_bool sim_idle_wait; /* idle waiting flag */ extern t_bool sim_asynch_timer; extern DEVICE sim_timer_dev; extern UNIT * volatile sim_clock_cosched_queue[SIM_NTIMERS+1]; extern const t_bool rtc_avail; #ifdef __cplusplus } #endif #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 | /* sim_tmxr.c: Telnet terminal multiplexer library Copyright (c) 2001-2011, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. Based on the original DZ11 simulator by Thord Nilson, as updated by Arthur Krewat. 12-Oct-12 MP Revised serial port support to not require changes to any code in TMXR library using code. Added support for per line listener ports and outgoing tcp connections. 02-Jun-11 MP Fixed telnet option negotiation loop with some clients Added Option Negotiation and Debugging Support 17-Jan-11 MP Added Buffered line capabilities 16-Jan-11 MP Made option negotiation more reliable 20-Nov-08 RMS Added three new standardized SHOW routines 05-Nov-08 JDB Moved logging call after connection check in tmxr_putc_ln 03-Nov-08 JDB Added TMXR null check to tmxr_find_ldsc 07-Oct-08 JDB Added initial serial port support 30-Sep-08 JDB Reverted tmxr_find_ldsc to original implementation 27-May-08 JDB Added line connection order to tmxr_poll_conn, added tmxr_set_lnorder and tmxr_show_lnorder 14-May-08 JDB Print device and line to which connection was made 11-Apr-07 JDB Worked around Telnet negotiation problem with QCTerm 16-Aug-05 RMS Fixed C++ declaration and cast problems 29-Jun-05 RMS Extended tmxr_dscln to support unit array devices Fixed bug in SET LOG/NOLOG 04-Jan-04 RMS Changed TMXR ldsc to be pointer to linedesc array Added tmxr_linemsg, circular output pointers, logging (from Mark Pizzolato) 29-Dec-03 RMS Added output stall support 01-Nov-03 RMS Cleaned up attach routine 09-Mar-03 RMS Fixed bug in SHOW CONN 22-Dec-02 RMS Fixed bugs in IAC+IAC receive and transmit sequences Added support for received break (all from by Mark Pizzolato) Fixed bug in attach 31-Oct-02 RMS Fixed bug in 8b (binary) support 22-Aug-02 RMS Added tmxr_open_master, tmxr_close_master 30-Dec-01 RMS Added tmxr_fstats, tmxr_dscln, renamed tmxr_fstatus 03-Dec-01 RMS Changed tmxr_fconns for extended SET/SHOW 20-Oct-01 RMS Fixed bugs in read logic (found by Thord Nilson). Added tmxr_rqln, tmxr_tqln This library includes: tmxr_poll_conn - poll for connection tmxr_reset_ln - reset line (drops Telnet/tcp and serial connections) tmxr_detach_ln - reset line and close per line listener and outgoing destination tmxr_getc_ln - get character for line tmxr_get_packet_ln - get packet from line tmxr_get_packet_ln_ex - get packet from line with separater byte tmxr_poll_rx - poll receive tmxr_putc_ln - put character for line tmxr_put_packet_ln - put packet on line tmxr_put_packet_ln_ex - put packet on line with separator byte tmxr_poll_tx - poll transmit tmxr_send_buffered_data - transmit buffered data tmxr_set_modem_control_passthru - enable modem control on a multiplexer tmxr_clear_modem_control_passthru - disable modem control on a multiplexer tmxr_set_get_modem_bits - set and/or get a line modem bits tmxr_set_line_loopback - enable or disable loopback mode on a line tmxr_get_line_loopback - returns the current loopback status of a line tmxr_set_line_halfduplex - enable or disable halfduplex mode on a line tmxr_get_line_halfduplex - returns the current halfduplex status of a line tmxr_set_config_line - set port speed, character size, parity and stop bits tmxr_open_master - open master connection tmxr_close_master - close master connection tmxr_attach - attach terminal multiplexor to listening port tmxr_detach - detach terminal multiplexor to listening port tmxr_attach_help - help routine for attaching multiplexer devices tmxr_set_line_unit - set the unit which polls for input for a given line tmxr_ex - (null) examine tmxr_dep - (null) deposit tmxr_msg - send message to socket tmxr_linemsg - send message to line tmxr_linemsgf - send formatted message to line tmxr_fconns - output connection status tmxr_fstats - output connection statistics tmxr_set_log - enable logging for line tmxr_set_nolog - disable logging for line tmxr_show_log - show logging status for line tmxr_dscln - disconnect line (SET routine) tmxr_rqln - number of available characters for line tmxr_tqln - number of buffered characters for line tmxr_tpqln - number of buffered packet characters for line tmxr_tpbusyln - transmit packet busy status for line tmxr_set_lnorder - set line connection order tmxr_show_lnorder - show line connection order tmxr_show_summ - show connection summary tmxr_show_cstat - show line connections or status tmxr_show_lines - show number of lines tmxr_show_open_devices - show info about all open tmxr devices All routines are OS-independent. This library supports the simulation of multiple-line terminal multiplexers. It may also be used to create single-line "multiplexers" to provide additional terminals beyond the simulation console. It may also be used to create single-line or multi-line simulated synchronous (BiSync) devices. Multiplexer lines may be connected to terminal emulators supporting the Telnet protocol via sockets, or to hardware terminals via host serial ports. Concurrent Telnet and serial connections may be mixed on a given multiplexer. When connecting via sockets, the simulated multiplexer is attached to a listening port on the host system: sim> attach MUX 23 Listening on port 23 Once attached, the listening port must be polled for incoming connections. When a connection attempt is received, it will be associated with the next multiplexer line in the user-specified line order, or with the next line in sequence if no order has been specified. Individual lines may be connected to serial ports or remote systems via TCP (telnet or not as desired), OR they may have separate listening TCP ports. Logging of Multiplexer Line output: The traffic going out multiplexer lines can be logged to files. A single line multiplexer can log it's traffic with the following command: sim> atta MUX 23,Log=LogFileName sim> atta MUX Connect=ser0,Log=LogFileName Specifying a Log value for a multi-line multiplexer is specifying a template filename. The actual file name used for each line will be the indicated filename with _n appended (n being the line number). Buffered Multiplexer Line: A Multiplexer Line Buffering has been implemented. A Buffered Line will have a copy of the last 'buffer size' bytes of output retained in a line specific buffer. The contents of this buffer will be transmitted out any new connection on that line when a new telnet session is established. This capability is most useful for the Console Telnet session. When a Console Telnet session is Buffered, a simulator will start (via BOOT CPU or whatever is appropriate for a particular simulator) without needing to have an active telnet connection. When a Telnet connection comes along for the telnet port, the contents of the saved buffer (which wraps on overflow) are presented on the telnet session as output before session traffic. This allows the connecting telnet client to see what happened before he connected since the likely reason he might be connecting to the console of a background simulator is to troubleshoot unusual behavior, the details of which may have already been sent to the console. Serial Port support: Serial ports may be specified as an operating system specific device names or using simh generic serial names. simh generic names are of the form serN, where N is from 0 thru one less than the maximum number of serial ports on the local system. The mapping of simh generic port names to OS specific names can be displayed using the following command: sim> show serial Serial devices: ser0 COM1 (\Device\Serial0) ser1 COM3 (Winachcf0) sim> attach MUX Line=2,Connect=ser0 or equivalently sim> attach MUX Line=2,Connect=COM1 An optional configuration string may be present after the port name. If present, it must be separated from the port name with a semicolon and has this form: <rate>-<charsize><parity><stopbits> where: rate = communication rate in bits per second charsize = character size in bits (5-8, including optional parity) parity = parity designator (N/E/O/M/S for no/even/odd/mark/space parity) stopbits = number of stop bits (1, 1.5, or 2) As an example: 9600-8n1 The supported rates, sizes, and parity options are host-specific. If a configuration string is not supplied, then the default of 9600-8N1 is used. An attachment to a serial port with the '-V' switch will cause a connection message to be output to the connected serial port. This will help to confirm the correct port has been connected and that the port settings are reasonable for the connected device. This would be done as: sim> attach -V MUX Connect=SerN Line specific tcp listening ports are supported. These are configured using commands of the form: sim> attach MUX Line=2,port{;notelnet} Direct computer to computer connections (Virutal Null Modem cables) may be established using the telnet protocol or via raw tcp sockets. sim> attach MUX Line=2,Connect=host:port{;notelnet} Computer to computer virtual connections can be one way (as illustrated above) or symmetric. A symmetric connection is configured by combining a one way connection with a tcp listening port on the same line: sim> attach MUX Line=2,Connect=host:port,listenport When symmetric virtual connections are configured, incoming connections on the specified listening port are checked to assure that they actually come from the specified connection destination host system. The command syntax for a single line device (MX) is: sim> attach MX port{;notelnet} sim> attach MX Connect=serN{;config} sim> attach MX Connect=COM9{;config} sim> attach MX Connect=host:port{;notelnet} The command syntax for ANY multi-line device is: sim> attach MX port{;notelnet} ; Defines the master listening port for the mux and optionally allows non-telnet (i.e. raw socket) operation for all lines. sim> attach MX Line=n,port{;notelnet} ; Defines a line specific listen port for a particular line. Each line can have a separate listen port and the mux can have its own as well. Optionally disable telnet wire protocol (i.e. raw socket) sim> attach MX Line=n,Connect=serN{;config} ; Connects line n to simh generic serial port N (port list visible with the sim> SHOW SERIAL command), the optional ";config" data specifies the speed, parity and stop bits for the connection ; DTR (and RTS) will be raised at attach time and will drop at detach/disconnect time sim> attach MX Line=n,Connect=host:port{;notelnet} ; Causes a connection to be established to the designated host:port. The actual connection will happen in a non-blocking fashion and will be completed and/or re-established by the normal tmxr_poll_conn activities All connections configured for any multiplexer device are unconfigured by: sim> detach MX ; detaches ALL connections/ports/sessions on the MUX. Console serial connections are achieved by: sim> set console serial=serN{;config} or sim> set console serial=COM2{;config} A line specific listening port (12366) can be specified by the following: sim> attach MUX Line=2,12366 A line specific remote telnet (or raw tcp) destination can be specified by the following: sim> attach MUX Line=2,Connect=remotehost:port If a connection to a remotehost:port wants a raw binary data channel (instead of a telnet session) the following would be used: sim> attach MUX Line=2,Connect=remotehost:port;notelnet A single line multiplexor can indicate any of the above line options without specifying a line number: sim> attach MUX Connect=ser0;9600-8N1 sim> attach MUX 12366 sim> attach MUX Connect=remotehost:port sim> attach MUX Connect=remotehost:port;notelnet A multiplexor can disconnect all (telnet, serial and outgoing) previous attachments with: sim> detach MUX A device emulation may choose to implement a command interface to disconnect specific individual lines. This would usually be done via a Unit Modifier table entry (MTAB) which dispatches the command "SET dev DISCONNECT[=line]" to tmxr_dscln. This will cause a telnet connection to be closed, but a serial port will normally have DTR dropped for 500ms and raised again (thus hanging up a modem on that serial port). sim> set MUX disconnect=2 A line which is connected to a serial port can be manually closed by adding the -C switch to a disconnect command. sim> set -C MUX disconnect=2 Full Modem Control serial port support. This library supports devices which wish to emulate full modem control/signalling for serial ports. Any device emulation which wishes to support this functionality for attached serial ports must call "tmxr_set_modem_control_passthru" before any call to tmxr_attach. This disables automatic DTR (&RTS) manipulation by this library. Responsibility for manipulating DTR falls on the simulated operating system. Calling tmxr_set_modem_control_passthru would usually be in a device reset routine. It may also be called by a device attach routine based on user specified options. Once support for full modem control has been declared by a device emulation for a particular TMXR device, this library will make no direct effort to manipulate modem bits while connected to serial ports. The "tmxr_set_get_modem_bits" API exists to allow the device emulation layer to query and control modem signals. The "tmxr_set_config_line" API exists to allow the device emulation layer to change port settings (baud rate, parity and stop bits). A modem_control enabled line merely passes the VM's port status bits, data and settings through to and from the serial port. The "tmxr_set_get_modem_bits" and "tmxr_set_config_line" APIs will ONLY work on a modem control enabled TMXR device. */ #define NOT_MUX_USING_CODE /* sim_tmxr library define */ #include "sim_defs.h" #include "sim_serial.h" #include "sim_sock.h" #include "sim_timer.h" #include "sim_tmxr.h" #include "scp.h" #include <ctype.h> #include <math.h> /* Telnet protocol constants - negatives are for init'ing signed char data */ /* Commands */ #define TN_IAC 0xFFu /* -1 */ /* protocol delim */ #define TN_DONT 0xFEu /* -2 */ /* dont */ #define TN_DO 0xFDu /* -3 */ /* do */ #define TN_WONT 0xFCu /* -4 */ /* wont */ #define TN_WILL 0xFBu /* -5 */ /* will */ #define TN_SB 0xFAu /* -6 */ /* sub-option negotiation */ #define TN_GA 0xF9u /* -7 */ /* go ahead */ #define TN_EL 0xF8u /* -8 */ /* erase line */ #define TN_EC 0xF7u /* -9 */ /* erase character */ #define TN_AYT 0xF6u /* -10 */ /* are you there */ #define TN_AO 0xF5u /* -11 */ /* abort output */ #define TN_IP 0xF4u /* -12 */ /* interrupt process */ #define TN_BRK 0xF3u /* -13 */ /* break */ #define TN_DATAMK 0xF2u /* -14 */ /* data mark */ #define TN_NOP 0xF1u /* -15 */ /* no operation */ #define TN_SE 0xF0u /* -16 */ /* end sub-option negot */ /* Options */ #define TN_BIN 0 /* bin */ #define TN_ECHO 1 /* echo */ #define TN_SGA 3 /* sga */ #define TN_STATUS 5 /* option status query */ #define TN_TIMING 6 /* Timing Mark */ #define TN_NAOCRD 10 /* Output Carriage-Return Disposition */ #define TN_NAOHTS 11 /* Output Horizontal Tab Stops */ #define TN_NAOHTD 12 /* Output Horizontal Tab Stop Disposition */ #define TN_NAOFFD 13 /* Output Forfeed Disposition */ #define TN_NAOVTS 14 /* Output Vertical Tab Stop */ #define TN_NAOVTD 15 /* Output Vertical Tab Stop Disposition */ #define TN_NAOLFD 16 /* Output Linefeed Disposition */ #define TN_EXTEND 17 /* Extended Ascii */ #define TN_LOGOUT 18 /* Logout */ #define TN_BM 19 /* Byte Macro */ #define TN_DET 20 /* Data Entry Terminal */ #define TN_SENDLO 23 /* Send Location */ #define TN_TERMTY 24 /* Terminal Type */ #define TN_ENDREC 25 /* Terminal Type */ #define TN_TUID 26 /* TACACS User Identification */ #define TN_OUTMRK 27 /* Output Marking */ #define TN_TTYLOC 28 /* Terminal Location Number */ #define TN_3270 29 /* 3270 Regime */ #define TN_X3PAD 30 /* X.3 PAD */ #define TN_NAWS 31 /* Negotiate About Window Size */ #define TN_TERMSP 32 /* Terminal Speed */ #define TN_TOGFLO 33 /* Remote Flow Control */ #define TN_LINE 34 /* line mode */ #define TN_XDISPL 35 /* X Display Location */ #define TN_ENVIRO 36 /* Environment */ #define TN_AUTH 37 /* Authentication */ #define TN_ENCRYP 38 /* Data Encryption */ #define TN_NEWENV 39 /* New Environment */ #define TN_TN3270 40 /* TN3270 Enhancements */ #define TN_CHARST 42 /* CHARSET */ #define TN_COMPRT 44 /* Com Port Control */ #define TN_KERMIT 47 /* KERMIT */ #define TN_CR 015 /* carriage return */ #define TN_LF 012 /* line feed */ #define TN_NUL 000 /* null */ /* Telnet line states */ #define TNS_NORM 000 /* normal */ #define TNS_IAC 001 /* IAC seen */ #define TNS_WILL 002 /* WILL seen */ #define TNS_WONT 003 /* WONT seen */ #define TNS_SKIP 004 /* skip next cmd */ #define TNS_CRPAD 005 /* CR padding */ #define TNS_DO 006 /* DO request pending rejection */ /* Telnet Option Sent Flags */ #define TNOS_DONT 001 /* Don't has been sent */ #define TNOS_WONT 002 /* Won't has been sent */ static BITFIELD tmxr_modem_bits[] = { BIT(DTR), /* Data Terminal Ready */ BIT(RTS), /* Request To Send */ BIT(DCD), /* Data Carrier Detect */ BIT(RNG), /* Ring Indicator */ BIT(CTS), /* Clear To Send */ BIT(DSR), /* Data Set Ready */ ENDBITS }; static u_char mantra[] = { /* Telnet Option Negotiation Mantra */ TN_IAC, TN_WILL, TN_LINE, TN_IAC, TN_WILL, TN_SGA, TN_IAC, TN_WILL, TN_ECHO, TN_IAC, TN_WILL, TN_BIN, TN_IAC, TN_DO, TN_BIN }; #define TMXR_GUARD ((int32)(lp->serport ? 1 : sizeof(mantra)))/* buffer guard */ /* Local routines */ static void tmxr_add_to_open_list (TMXR* mux); /* Initialize the line state. Reset the line state to represent an idle line. Note that we do not clear all of the line structure members, so a connected line remains connected after this call. Because a line break is represented by a flag in the "receive break status" array, we must zero that array in order to clear any pending break indications. */ static void tmxr_init_line (TMLN *lp) { lp->tsta = 0; /* init telnet state */ lp->xmte = 1; /* enable transmit */ lp->dstb = 0; /* default bin mode */ lp->rxbpr = lp->rxbpi = lp->rxcnt = lp->rxpcnt = 0; /* init receive indexes */ if (!lp->txbfd || lp->notelnet) /* if not buffered telnet */ lp->txbpr = lp->txbpi = lp->txcnt = lp->txpcnt = 0; /* init transmit indexes */ lp->txdrp = 0; tmxr_set_get_modem_bits (lp, 0, 0, NULL); if ((!lp->mp->buffered) && (!lp->txbfd)) { lp->txbfd = 0; lp->txbsz = TMXR_MAXBUF; lp->txb = (char *)realloc (lp->txb, lp->txbsz); lp->rxbsz = TMXR_MAXBUF; lp->rxb = (char *)realloc(lp->rxb, lp->rxbsz); lp->rbr = (char *)realloc(lp->rbr, lp->rxbsz); } if (lp->loopback) { lp->lpbsz = lp->rxbsz; lp->lpb = (char *)realloc(lp->lpb, lp->lpbsz); lp->lpbcnt = lp->lpbpi = lp->lpbpr = 0; } if (lp->rxpb) { lp->rxpboffset = lp->rxpbsize = 0; free (lp->rxpb); lp->rxpb = NULL; } if (lp->txpb) { lp->txpbsize = lp->txppsize = lp->txppoffset = 0; free (lp->txpb); lp->txpb = NULL; } memset (lp->rbr, 0, lp->rxbsz); /* clear break status array */ return; } /* Report a connection to a line. If the indicated line (lp) is speaking the telnet wire protocol, a notification of the form: Connected to the <sim> simulator <dev> device, line <n> is sent to the newly connected line. If the device has only one line, the "line <n>" part is omitted. If the device has not been defined, the "<dev> device" part is omitted. */ static void tmxr_report_connection (TMXR *mp, TMLN *lp) { int32 unwritten, psave; char cmsg[80]; char dmsg[80] = ""; char lmsg[80] = ""; char msgbuf[256] = ""; if ((!lp->notelnet) || (sim_switches & SWMASK ('V'))) { sprintf (cmsg, "\n\r\nConnected to the %s simulator ", sim_name); if (mp->dptr) { /* device defined? */ sprintf (dmsg, "%s device", /* report device name */ sim_dname (mp->dptr)); if (mp->lines > 1) /* more than one line? */ sprintf (lmsg, ", line %d", (int)(lp-mp->ldsc));/* report the line number */ } sprintf (msgbuf, "%s%s%s\r\n\n", cmsg, dmsg, lmsg); } if (!mp->buffered) { lp->txbpi = 0; /* init buf pointers */ lp->txbpr = (int32)(lp->txbsz - strlen (msgbuf)); lp->rxcnt = lp->txcnt = lp->txdrp = 0; /* init counters */ lp->rxpcnt = lp->txpcnt = 0; } else if (lp->txcnt > lp->txbsz) lp->txbpr = (lp->txbpi + 1) % lp->txbsz; else lp->txbpr = (int32)(lp->txbsz - strlen (msgbuf)); psave = lp->txbpi; /* save insertion pointer */ lp->txbpi = lp->txbpr; /* insert connection message */ tmxr_linemsg (lp, msgbuf); /* beginning of buffer */ lp->txbpi = psave; /* restore insertion pointer */ unwritten = tmxr_send_buffered_data (lp); /* send the message */ if (unwritten == 0) /* buffer now empty? */ lp->xmte = 1; /* reenable transmission if paused */ lp->txcnt -= (int32)strlen (msgbuf); /* adjust statistics */ return; } /* Report a disconnection to a line. A notification of the form: Disconnected from the <sim> simulator is sent to the line about to be disconnected. We do not flush the buffer here, because the disconnect routines will do that just after calling us. */ static void tmxr_report_disconnection (TMLN *lp) { if (lp->notelnet) return; tmxr_linemsgf (lp, "\r\nDisconnected from the %s simulator\r\n\n", sim_name);/* report disconnection */ return; } static int32 loop_write_ex (TMLN *lp, char *buf, int32 length, t_bool prefix_datagram) { int32 written = 0; int32 loopfree = lp->lpbsz - lp->lpbcnt; if (lp->datagram && prefix_datagram) { if ((size_t)loopfree < (size_t)(length + sizeof(length))) return written; loop_write_ex (lp, (char *)&length, sizeof(length), FALSE); } while (length) { int32 chunksize; loopfree = lp->lpbsz - lp->lpbcnt; if (loopfree == 0) break; if (loopfree < length) length = loopfree; if (lp->lpbpi >= lp->lpbpr) chunksize = lp->lpbsz - lp->lpbpi; else chunksize = lp->lpbpr - lp->lpbpi; if (chunksize > length) chunksize = length; memcpy (&lp->lpb[lp->lpbpi], buf, chunksize); buf += chunksize; length -= chunksize; written += chunksize; lp->lpbpi = (lp->lpbpi + chunksize) % lp->lpbsz; } lp->lpbcnt += written; return written; } static int32 loop_write (TMLN *lp, char *buf, int32 length) { return loop_write_ex (lp, buf, length, TRUE); } static int32 loop_read_ex (TMLN *lp, char *buf, int32 bufsize) { int32 bytesread = 0; while (bufsize > 0) { int32 chunksize; int32 loopused = lp->lpbcnt; if (loopused < bufsize) bufsize = loopused; if (loopused == 0) break; if (lp->lpbpi > lp->lpbpr) chunksize = lp->lpbpi - lp->lpbpr; else chunksize = lp->lpbsz - lp->lpbpr; if (chunksize > bufsize) chunksize = bufsize; memcpy (buf, &lp->lpb[lp->lpbpr], chunksize); buf += chunksize; bufsize -= chunksize; bytesread += chunksize; lp->lpbpr = (lp->lpbpr + chunksize) % lp->lpbsz; } lp->lpbcnt -= bytesread; return bytesread; } static int32 loop_read (TMLN *lp, char *buf, int32 bufsize) { if (lp->datagram) { int32 pktsize; if (lp->lpbcnt < (int32)sizeof(pktsize)) return 0; if ((sizeof(pktsize) != loop_read_ex (lp, (char *)&pktsize, sizeof(pktsize))) || (pktsize > bufsize)) return -1; bufsize = pktsize; } return loop_read_ex (lp, buf, bufsize); } /* Read from a line. Up to "length" characters are read into the character buffer associated with line "lp". The actual number of characters read is returned. If no characters are available, 0 is returned. If an error occurred while reading, -1 is returned. If a line break was detected on serial input, the associated receive break status flag will be set. Line break indication for Telnet connections is embedded in the Telnet protocol and must be determined externally. */ static int32 tmxr_read (TMLN *lp, int32 length) { int32 i = lp->rxbpi; if (lp->loopback) return loop_read (lp, &(lp->rxb[i]), length); if (lp->serport) /* serial port connection? */ return sim_read_serial (lp->serport, &(lp->rxb[i]), length, &(lp->rbr[i])); else /* Telnet connection */ return sim_read_sock (lp->sock, &(lp->rxb[i]), length); } /* Write to a line. Up to "length" characters are written from the character buffer associated with "lp". The actual number of characters written is returned. If an error occurred while writing, -1 is returned. */ static int32 tmxr_write (TMLN *lp, int32 length) { int32 written; int32 i = lp->txbpr; if (lp->loopback) return loop_write (lp, &(lp->txb[i]), length); if (lp->serport) { /* serial port connection? */ if (sim_gtime () < lp->txnexttime) return 0; written = sim_write_serial (lp->serport, &(lp->txb[i]), length); if (written > 0) lp->txnexttime = floor (sim_gtime () + (lp->txdelta * sim_timer_inst_per_sec ())); return written; } else { /* Telnet connection */ written = sim_write_sock (lp->sock, &(lp->txb[i]), length); if (written == SOCKET_ERROR) /* did an error occur? */ if (lp->datagram) return written; /* ignore errors on datagram sockets */ else return -1; /* return error indication */ else return written; } } /* Remove a character from the read buffer. The character at position "p" in the read buffer associated with line "lp" is removed by moving all of the following received characters down one position. The receive break status array is adjusted accordingly. */ static void tmxr_rmvrc (TMLN *lp, int32 p) { for ( ; p < lp->rxbpi; p++) { /* work from "p" through end of buffer */ lp->rxb[p] = lp->rxb[p + 1]; /* slide following character down */ lp->rbr[p] = lp->rbr[p + 1]; /* adjust break status too */ } lp->rbr[p] = 0; /* clear potential break from vacated slot */ lp->rxbpi = lp->rxbpi - 1; /* drop buffer insert index */ return; } /* Find a line descriptor indicated by unit or number. If "uptr" is NULL, then the line descriptor is determined by the line number passed in "val". If "uptr" is not NULL, then it must point to a unit associated with a line, and the line descriptor is determined by the unit number, which is derived by the position of the unit in the device's unit array. Note: This routine may be called with a UNIT that does not belong to the device indicated in the TMXR structure. That is, the multiplexer lines may belong to a device other than the one attached to the socket (the HP 2100 MUX device is one example). Therefore, we must look up the device from the unit at each call, rather than depending on the DEVICE pointer stored in the TMXR. */ static TMLN *tmxr_find_ldsc (UNIT *uptr, int32 val, const TMXR *mp) { if (mp == NULL) /* invalid multiplexer descriptor? */ return NULL; /* programming error! */ if (uptr) { /* called from SET? */ DEVICE *dptr = find_dev_from_unit (uptr); /* find device */ if (dptr == NULL) /* what?? */ return NULL; val = (int32) (uptr - dptr->units); /* implicit line # */ } if ((val < 0) || (val >= mp->lines)) /* invalid line? */ return NULL; return mp->ldsc + val; /* line descriptor */ } /* Get a line descriptor indicated by a string or unit. A pointer to the line descriptor associated with multiplexer "mp" and unit "uptr" or specified by string "cptr" is returned. If "uptr" is non-null, then the unit number within its associated device implies the line number. If "uptr" is null, then the string "cptr" is parsed for a decimal line number. If the line number is missing, malformed, or outside of the range of line numbers associated with "mp", then NULL is returned with status set to SCPE_ARG. Implementation note: 1. A return status of SCPE_IERR implies a programming error (passing an invalid pointer or an invalid unit). */ static TMLN *tmxr_get_ldsc (UNIT *uptr, const char *cptr, TMXR *mp, t_stat *status) { t_value ln; TMLN *lp = NULL; t_stat code = SCPE_OK; if (mp == NULL) /* missing mux descriptor? */ code = SCPE_IERR; /* programming error! */ else if (uptr) { /* implied line form? */ lp = tmxr_find_ldsc (uptr, mp->lines, mp); /* determine line from unit */ if (lp == NULL) /* invalid line number? */ code = SCPE_IERR; /* programming error! */ } else if (cptr == NULL) /* named line form, parameter supplied? */ code = SCPE_MISVAL; /* no, so report missing */ else { ln = get_uint (cptr, 10, mp->lines - 1, &code); /* get line number */ if (code == SCPE_OK) /* line number OK? */ lp = mp->ldsc + (int32) ln; /* use as index to determine line */ } if (status) /* return value pointer supplied? */ *status = code; /* store return status value */ return lp; /* return pointer to line descriptor */ } /* Generate the Attach string which will fully configure the multiplexer Inputs: old = pointer to the original configuration string which will be replaced *mp = pointer to multiplexer Output: a complete attach string for the current state of the multiplexer */ static char *growstring(char **string, size_t growth) { *string = (char *)realloc (*string, 1 + (*string ? strlen (*string) : 0) + growth); return *string + strlen(*string); } static char *tmxr_mux_attach_string(char *old, TMXR *mp) { char* tptr = NULL; int32 i; TMLN *lp; free (old); tptr = (char *) calloc (1, 1); if (tptr == NULL) /* no more mem? */ return tptr; if (mp->port) /* copy port */ sprintf (growstring(&tptr, 13 + strlen (mp->port)), "%s%s", mp->port, mp->notelnet ? ";notelnet" : ""); if (mp->logfiletmpl[0]) /* logfile info */ sprintf (growstring(&tptr, 7 + strlen (mp->logfiletmpl)), ",Log=%s", mp->logfiletmpl); while ((*tptr == ',') || (*tptr == ' ')) memmove (tptr, tptr+1, strlen(tptr+1)+1); for (i=0; i<mp->lines; ++i) { char *lptr; lp = mp->ldsc + i; lptr = tmxr_line_attach_string(lp); if (lptr) { sprintf (growstring(&tptr, 10+strlen(lptr)), "%s%s", *tptr ? "," : "", lptr); free (lptr); } } if (mp->lines == 1) while ((*tptr == ',') || (*tptr == ' ')) memmove (tptr, tptr+1, strlen(tptr+1)+1); if (*tptr == '\0') { free (tptr); tptr = NULL; } return tptr; } /* Global routines */ /* Return the Line specific attach setup currently configured for a given line Inputs: *lp = pointer to terminal line descriptor Outputs: a string which can be used to reconfigure the line, NULL if the line isn't configured Note: The returned string is dynamically allocated memory and must be freed when it is no longer needed by calling free */ char *tmxr_line_attach_string(TMLN *lp) { char* tptr = NULL; tptr = (char *) calloc (1, 1); if (tptr == NULL) /* no more mem? */ return tptr; if (lp->destination || lp->port || lp->txlogname) { if ((lp->mp->lines > 1) || (lp->port)) sprintf (growstring(&tptr, 32), "Line=%d", (int)(lp-lp->mp->ldsc)); if (lp->modem_control != lp->mp->modem_control) sprintf (growstring(&tptr, 32), ",%s", lp->modem_control ? "Modem" : "NoModem"); if (lp->txbfd && (lp->txbsz != lp->mp->buffered)) sprintf (growstring(&tptr, 32), ",Buffered=%d", lp->txbsz); if (!lp->txbfd && (lp->mp->buffered > 0)) sprintf (growstring(&tptr, 32), ",UnBuffered"); if (lp->mp->datagram != lp->datagram) sprintf (growstring(&tptr, 8), ",%s", lp->datagram ? "UDP" : "TCP"); if (lp->mp->packet != lp->packet) sprintf (growstring(&tptr, 8), ",Packet"); if (lp->port) sprintf (growstring(&tptr, 12 + strlen (lp->port)), ",%s%s", lp->port, ((lp->mp->notelnet != lp->notelnet) && (!lp->datagram)) ? (lp->notelnet ? ";notelnet" : ";telnet") : ""); if (lp->destination) { if (lp->serport) { char portname[CBUFSIZE]; get_glyph_nc (lp->destination, portname, ';'); sprintf (growstring(&tptr, 25 + strlen (lp->destination)), ",Connect=%s%s%s", portname, strcmp("9600-8N1", lp->serconfig) ? ";" : "", strcmp("9600-8N1", lp->serconfig) ? lp->serconfig : ""); } else sprintf (growstring(&tptr, 25 + strlen (lp->destination)), ",Connect=%s%s", lp->destination, ((lp->mp->notelnet != lp->notelnet) && (!lp->datagram)) ? (lp->notelnet ? ";notelnet" : ";telnet") : ""); } if (lp->txlogname) sprintf (growstring(&tptr, 12 + strlen (lp->txlogname)), ",Log=%s", lp->txlogname); if (lp->loopback) sprintf (growstring(&tptr, 12 ), ",Loopback"); } if (*tptr == '\0') { free (tptr); tptr = NULL; } return tptr; } /* Set the connection polling interval */ t_stat tmxr_connection_poll_interval (TMXR *mp, uint32 seconds) { if (0 == seconds) return SCPE_ARG; mp->poll_interval = seconds; return SCPE_OK; } /* Poll for new connection Called from unit service routine to test for new connection Inputs: *mp = pointer to terminal multiplexer descriptor Outputs: line number activated, -1 if none If a connection order is defined for the descriptor, and the first value is not -1 (indicating default order), then the order array is used to find an open line. Otherwise, a search is made of all lines in numerical sequence. */ int32 tmxr_poll_conn (TMXR *mp) { SOCKET newsock; TMLN *lp; int32 *op; int32 i, j; char *address; char msg[512]; uint32 poll_time = sim_os_msec (); if (mp->last_poll_time == 0) { /* first poll initializations */ UNIT *uptr = mp->uptr; if (!uptr) /* Attached ? */ return -1; /* No connections are possinle! */ if (mp->poll_interval == 0) /* Assure reasonable polling interval */ mp->poll_interval = TMXR_DEFAULT_CONNECT_POLL_INTERVAL; if (!(uptr->dynflags & TMUF_NOASYNCH)) { /* if asynch not disabled */ uptr->dynflags |= UNIT_TM_POLL; /* tag as polling unit */ sim_cancel (uptr); } for (i=0; i < mp->lines; i++) { uptr = mp->ldsc[i].uptr ? mp->ldsc[i].uptr : mp->uptr; if (!(mp->uptr->dynflags & TMUF_NOASYNCH)) { /* if asynch not disabled */ uptr->dynflags |= UNIT_TM_POLL; /* tag as polling unit */ sim_cancel (uptr); } } } if ((poll_time - mp->last_poll_time) < mp->poll_interval*1000) return -1; /* too soon to try */ srand((unsigned int)poll_time); tmxr_debug_trace (mp, "tmxr_poll_conn()"); mp->last_poll_time = poll_time; /* Check for a pending Telnet/tcp connection */ if (mp->master) { if (mp->ring_sock != INVALID_SOCKET) { /* Use currently 'ringing' socket if one is active */ newsock = mp->ring_sock; mp->ring_sock = INVALID_SOCKET; address = mp->ring_ipad; mp->ring_ipad = NULL; } else newsock = sim_accept_conn_ex (mp->master, &address, (mp->packet ? SIM_SOCK_OPT_NODELAY : 0));/* poll connect */ if (newsock != INVALID_SOCKET) { /* got a live one? */ sprintf (msg, "tmxr_poll_conn() - Connection from %s", address); tmxr_debug_connect (mp, msg); op = mp->lnorder; /* get line connection order list pointer */ i = mp->lines; /* play it safe in case lines == 0 */ ++mp->sessions; /* count the new session */ for (j = 0; j < mp->lines; j++, i++) { /* find next avail line */ if (op && (*op >= 0) && (*op < mp->lines)) /* order list present and valid? */ i = *op++; /* get next line in list to try */ else /* no list or not used or range error */ i = j; /* get next sequential line */ lp = mp->ldsc + i; /* get pointer to line descriptor */ if ((lp->conn == FALSE) && /* is the line available? */ (lp->destination == NULL) && (lp->master == 0) && (lp->ser_connect_pending == FALSE) && (lp->modem_control ? ((lp->modembits & TMXR_MDM_DTR) != 0) : TRUE)) break; /* yes, so stop search */ } if (i >= mp->lines) { /* all busy? */ int32 ringable_count = 0; for (j = 0; j < mp->lines; j++, i++) { /* find next avail line */ lp = mp->ldsc + j; /* get pointer to line descriptor */ if ((lp->conn == FALSE) && /* is the line available? */ (lp->destination == NULL) && (lp->master == 0) && (lp->ser_connect_pending == FALSE) && ((lp->modembits & TMXR_MDM_DTR) == 0)) { ++ringable_count; tmxr_set_get_modem_bits (lp, TMXR_MDM_RNG, 0, NULL); tmxr_debug_connect_line (lp, "tmxr_poll_conn() - Ringing line"); } } if (ringable_count > 0) { if (mp->ring_start_time == 0) { mp->ring_start_time = poll_time; mp->ring_sock = newsock; mp->ring_ipad = address; } else { if ((poll_time - mp->ring_start_time) < TMXR_MODEM_RING_TIME*1000) { mp->ring_sock = newsock; mp->ring_ipad = address; } else { /* Timeout waiting for DTR */ int ln; /* turn off pending ring signals */ for (ln = 0; ln < lp->mp->lines; ln++) { TMLN *tlp = lp->mp->ldsc + ln; if (((tlp->destination == NULL) && (tlp->master == 0)) && (tlp->modembits & TMXR_MDM_RNG) && (tlp->conn == FALSE)) tlp->modembits &= ~TMXR_MDM_RNG; } mp->ring_start_time = 0; tmxr_msg (newsock, "No answer on any connection\r\n"); tmxr_debug_connect (mp, "tmxr_poll_conn() - No Answer - All connections busy"); sim_close_sock (newsock); free (address); } } } else { tmxr_msg (newsock, "All connections busy\r\n"); tmxr_debug_connect (mp, "tmxr_poll_conn() - All connections busy"); sim_close_sock (newsock); free (address); } } else { lp = mp->ldsc + i; /* get line desc */ lp->conn = TRUE; /* record connection */ lp->sock = newsock; /* save socket */ lp->ipad = address; /* ip address */ tmxr_init_line (lp); /* init line */ lp->notelnet = mp->notelnet; /* apply mux default telnet setting */ if (!lp->notelnet) { sim_write_sock (newsock, (char *)mantra, sizeof(mantra)); tmxr_debug (TMXR_DBG_XMT, lp, "Sending", (char *)mantra, sizeof(mantra)); lp->telnet_sent_opts = (uint8 *)realloc (lp->telnet_sent_opts, 256); memset (lp->telnet_sent_opts, 0, 256); } tmxr_report_connection (mp, lp); lp->cnms = sim_os_msec (); /* time of connection */ return i; } } /* end if newsock */ } /* Look for per line listeners or outbound connecting sockets */ for (i = 0; i < mp->lines; i++) { /* check each line in sequence */ int j, r = rand(); lp = mp->ldsc + i; /* get pointer to line descriptor */ /* Check for pending serial port connection notification */ if (lp->ser_connect_pending) { lp->ser_connect_pending = FALSE; lp->conn = TRUE; return i; } /* Don't service network connections for loopbacked lines */ if (lp->loopback) continue; /* If two simulators are configured with symmetric virtual null modem cables pointing at each other, there may be a problem establishing a connection if both systems happen to be checking for the success of their connections in the exact same order. They can each observe success in their respective outgoing connections, which haven't actually been 'accept'ed on the peer end of the connection. We address this issue by checking for the success of an outgoing connection and the arrival of an incoming one in a random order. */ for (j=0; j<2; j++) switch ((j+r)&1) { case 0: if (lp->connecting) { /* connecting? */ char *sockname, *peername; switch (sim_check_conn(lp->connecting, FALSE)) { case 1: /* successful connection */ lp->conn = TRUE; /* record connection */ lp->sock = lp->connecting; /* it now looks normal */ lp->connecting = 0; lp->ipad = (char *)realloc (lp->ipad, 1+strlen (lp->destination)); strcpy (lp->ipad, lp->destination); lp->cnms = sim_os_msec (); sim_getnames_sock (lp->sock, &sockname, &peername); sprintf (msg, "tmxr_poll_conn() - Outgoing Line Connection to %s (%s->%s) established", lp->destination, sockname, peername); tmxr_debug_connect_line (lp, msg); free (sockname); free (peername); return i; case -1: /* failed connection */ sprintf (msg, "tmxr_poll_conn() - Outgoing Line Connection to %s failed", lp->destination); tmxr_debug_connect_line (lp, msg); tmxr_reset_ln (lp); /* retry */ break; } } break; case 1: if (lp->master) { /* Check for a pending Telnet/tcp connection */ while (INVALID_SOCKET != (newsock = sim_accept_conn_ex (lp->master, &address, (lp->packet ? SIM_SOCK_OPT_NODELAY : 0)))) {/* got a live one? */ char *sockname, *peername; sim_getnames_sock (newsock, &sockname, &peername); sprintf (msg, "tmxr_poll_conn() - Incoming Line Connection from %s (%s->%s)", address, peername, sockname); tmxr_debug_connect_line (lp, msg); free (sockname); free (peername); ++mp->sessions; /* count the new session */ if (lp->destination) { /* Virtual Null Modem Cable? */ char host[CBUFSIZE]; if (sim_parse_addr (lp->destination, host, sizeof(host), NULL, NULL, 0, NULL, address)) { tmxr_msg (newsock, "Rejecting connection from unexpected source\r\n"); sprintf (msg, "tmxr_poll_conn() - Rejecting line connection from: %s, Expected: %s", address, host); tmxr_debug_connect_line (lp, msg); sim_close_sock (newsock); free (address); continue; /* Try for another connection */ } if (lp->connecting) { sprintf (msg, "tmxr_poll_conn() - aborting outgoing line connection attempt to: %s", lp->destination); tmxr_debug_connect_line (lp, msg); sim_close_sock (lp->connecting); /* abort our as yet unconnnected socket */ lp->connecting = 0; } } if (lp->conn == FALSE) { /* is the line available? */ if ((!lp->modem_control) || (lp->modembits & TMXR_MDM_DTR)) { lp->conn = TRUE; /* record connection */ lp->sock = newsock; /* save socket */ lp->ipad = address; /* ip address */ tmxr_init_line (lp); /* init line */ if (!lp->notelnet) { sim_write_sock (newsock, (char *)mantra, sizeof(mantra)); tmxr_debug (TMXR_DBG_XMT, lp, "Sending", (char *)mantra, sizeof(mantra)); lp->telnet_sent_opts = (uint8 *)realloc (lp->telnet_sent_opts, 256); memset (lp->telnet_sent_opts, 0, 256); } tmxr_report_connection (mp, lp); lp->cnms = sim_os_msec (); /* time of connection */ return i; } else { tmxr_msg (newsock, "Line connection not available\r\n"); tmxr_debug_connect_line (lp, "tmxr_poll_conn() - Line connection not available"); sim_close_sock (newsock); free (address); } } else { tmxr_msg (newsock, "Line connection busy\r\n"); tmxr_debug_connect_line (lp, "tmxr_poll_conn() - Line connection busy"); sim_close_sock (newsock); free (address); } } } break; } /* Check for needed outgoing connection initiation */ if (lp->destination && (!lp->sock) && (!lp->connecting) && (!lp->serport) && (!lp->modem_control || (lp->modembits & TMXR_MDM_DTR))) { sprintf (msg, "tmxr_poll_conn() - establishing outgoing connection to: %s", lp->destination); tmxr_debug_connect_line (lp, msg); lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (lp->mp->packet ? SIM_SOCK_OPT_NODELAY : 0)); } } return -1; /* no new connections made */ } /* Reset a line. The telnet/tcp or serial session associated with multiplexer descriptor "mp" and line descriptor "lp" is disconnected. An associated tcp socket is closed; a serial port is closed if the closeserial parameter is true, otherwise for non modem control serial lines DTR is dropped and raised again after 500ms to signal the attached serial device. */ static t_stat tmxr_reset_ln_ex (TMLN *lp, t_bool closeserial) { char msg[512]; tmxr_debug_trace_line (lp, "tmxr_reset_ln_ex()"); if (lp->txlog) fflush (lp->txlog); /* flush log */ tmxr_send_buffered_data (lp); /* send any buffered data */ sprintf (msg, "tmxr_reset_ln_ex(%s)", closeserial ? "TRUE" : "FALSE"); tmxr_debug_connect_line (lp, msg); if (lp->serport) { if (closeserial) { sim_close_serial (lp->serport); lp->serport = 0; lp->ser_connect_pending = FALSE; free (lp->destination); lp->destination = NULL; free (lp->serconfig); lp->serconfig = NULL; lp->cnms = 0; lp->xmte = 1; } else if (!lp->modem_control) { /* serial connection? */ sim_control_serial (lp->serport, 0, TMXR_MDM_DTR|TMXR_MDM_RTS, NULL);/* drop DTR and RTS */ sim_os_ms_sleep (TMXR_DTR_DROP_TIME); sim_control_serial (lp->serport, TMXR_MDM_DTR|TMXR_MDM_RTS, 0, NULL);/* raise DTR and RTS */ } } else /* Telnet connection */ if (lp->sock) { sim_close_sock (lp->sock); /* close socket */ free (lp->telnet_sent_opts); lp->telnet_sent_opts = NULL; lp->sock = 0; lp->conn = FALSE; lp->cnms = 0; lp->xmte = 1; } free(lp->ipad); lp->ipad = NULL; if ((lp->destination) && (!lp->serport)) { if (lp->connecting) { sim_close_sock (lp->connecting); lp->connecting = 0; } if ((!lp->modem_control) || (lp->modembits & TMXR_MDM_DTR)) { sprintf (msg, "tmxr_reset_ln_ex() - connecting to %s", lp->destination); tmxr_debug_connect_line (lp, msg); lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (lp->mp->packet ? SIM_SOCK_OPT_NODELAY : 0)); } } tmxr_init_line (lp); /* initialize line state */ return SCPE_OK; } t_stat tmxr_close_ln (TMLN *lp) { tmxr_debug_trace_line (lp, "tmxr_close_ln()"); tmxr_debug_connect_line (lp, "tmxr_close_ln()"); return tmxr_reset_ln_ex (lp, TRUE); } t_stat tmxr_reset_ln (TMLN *lp) { tmxr_debug_trace_line (lp, "tmxr_reset_ln()"); return tmxr_reset_ln_ex (lp, FALSE); } /* Enable modem control pass thru Inputs: none Output: none Implementation note: 1 Calling this API disables any actions on the part of this library to directly manipulate DTR (&RTS) on serial ports. 2 Calling this API enables the tmxr_set_get_modem_bits and tmxr_set_config_line APIs. */ static t_stat tmxr_clear_modem_control_passthru_state (TMXR *mp, t_bool state) { int i; if (mp->modem_control == state) return SCPE_OK; if (mp->master) return SCPE_ALATT; for (i=0; i<mp->lines; ++i) { TMLN *lp; lp = mp->ldsc + i; if ((lp->master) || (lp->sock) || (lp->connecting) || (lp->serport)) return SCPE_ALATT; } mp->modem_control = state; for (i=0; i<mp->lines; ++i) mp->ldsc[i].modem_control = state; return SCPE_OK; } t_stat tmxr_set_modem_control_passthru (TMXR *mp) { return tmxr_clear_modem_control_passthru_state (mp, TRUE); } /* Disable modem control pass thru Inputs: none Output: none Implementation note: 1 Calling this API enables this library's direct manipulation of DTR (&RTS) on serial ports. 2 Calling this API disables the tmxr_set_get_modem_bits and tmxr_set_config_line APIs. 3 This API will only change the state of the modem control processing of this library if there are no listening ports, serial ports or outgoing connecctions associated with the specified multiplexer */ t_stat tmxr_clear_modem_control_passthru (TMXR *mp) { return tmxr_clear_modem_control_passthru_state (mp, FALSE); } /* Manipulate the modem control bits of a specific line Inputs: *lp = pointer to terminal line descriptor bits_to_set TMXR_MDM_DTR and/or TMXR_MDM_RTS as desired bits_to_clear TMXR_MDM_DTR and/or TMXR_MDM_RTS as desired Output: incoming_bits if non NULL, returns the current stat of DCD, RNG, CTS and DSR along with the current state of DTR and RTS Implementation note: If a line is connected to a serial port, then these values affect and reflect the state of the serial port. If the line is connected to a network socket (or could be) then the network session state is set, cleared and/or returned. */ t_stat tmxr_set_get_modem_bits (TMLN *lp, int32 bits_to_set, int32 bits_to_clear, int32 *incoming_bits) { int32 before_modem_bits, incoming_state; DEVICE *dptr; tmxr_debug_trace_line (lp, "tmxr_set_get_modem_bits()"); if ((bits_to_set & ~(TMXR_MDM_OUTGOING)) || /* Assure only settable bits */ (bits_to_clear & ~(TMXR_MDM_OUTGOING)) || (bits_to_set & bits_to_clear)) /* and can't set and clear the same bits */ return SCPE_ARG; before_modem_bits = lp->modembits; lp->modembits |= bits_to_set; lp->modembits &= ~(bits_to_clear | TMXR_MDM_INCOMING); if ((lp->sock) || (lp->serport) || (lp->loopback)) { if (lp->modembits & TMXR_MDM_DTR) { incoming_state = TMXR_MDM_DSR; if (lp->modembits & TMXR_MDM_RTS) incoming_state |= TMXR_MDM_CTS; if (lp->halfduplex) { if (incoming_state & TMXR_MDM_CTS) incoming_state |= TMXR_MDM_DCD; } else incoming_state |= TMXR_MDM_DCD; } else incoming_state = TMXR_MDM_DCD | TMXR_MDM_DSR | ((lp->modembits & TMXR_MDM_DTR) ? 0 : TMXR_MDM_RNG); } else { if (((before_modem_bits & TMXR_MDM_DTR) == 0) && /* Upward transition of DTR? */ ((lp->modembits & TMXR_MDM_DTR) != 0) && (lp->conn == FALSE) && /* Not connected */ (lp->modembits & TMXR_MDM_RNG)) { /* and Ring Signal Present */ if ((lp->destination == NULL) && (lp->master == 0) && (lp->mp && (lp->mp->ring_sock))) { int ln; lp->conn = TRUE; /* record connection */ lp->sock = lp->mp->ring_sock; /* save socket */ lp->mp->ring_sock = INVALID_SOCKET; lp->ipad = lp->mp->ring_ipad; /* ip address */ lp->mp->ring_ipad = NULL; lp->mp->ring_start_time = 0; tmxr_init_line (lp); /* init line */ lp->notelnet = lp->mp->notelnet; /* apply mux default telnet setting */ if (!lp->notelnet) { sim_write_sock (lp->sock, (char *)mantra, sizeof(mantra)); tmxr_debug (TMXR_DBG_XMT, lp, "Sending", (char *)mantra, sizeof(mantra)); lp->telnet_sent_opts = (uint8 *)realloc (lp->telnet_sent_opts, 256); memset (lp->telnet_sent_opts, 0, 256); } tmxr_report_connection (lp->mp, lp); lp->cnms = sim_os_msec (); /* time of connection */ lp->modembits &= ~TMXR_MDM_RNG; /* turn off ring on this line*/ /* turn off other pending ring signals */ for (ln = 0; ln < lp->mp->lines; ln++) { TMLN *tlp = lp->mp->ldsc + ln; if (((tlp->destination == NULL) && (tlp->master == 0)) && (tlp->modembits & TMXR_MDM_RNG) && (tlp->conn == FALSE)) tlp->modembits &= ~TMXR_MDM_RNG; } } } if ((lp->master) || (lp->mp && lp->mp->master) || (lp->port && lp->destination)) incoming_state = TMXR_MDM_DSR; else incoming_state = 0; } lp->modembits |= incoming_state; dptr = (lp->dptr ? lp->dptr : (lp->mp ? lp->mp->dptr : NULL)); if ((lp->modembits != before_modem_bits) && (sim_deb && lp->mp && dptr)) { sim_debug_bits (TMXR_DBG_MDM, dptr, tmxr_modem_bits, before_modem_bits, lp->modembits, FALSE); sim_debug (TMXR_DBG_MDM, dptr, " - Line %d - %p\n", (int)(lp-lp->mp->ldsc), lp->txb); } if (incoming_bits) *incoming_bits = lp->modembits; if (lp->mp && lp->modem_control) { /* This API ONLY works on modem_control enabled multiplexer lines */ if (bits_to_set | bits_to_clear) { /* Anything to do? */ if (lp->loopback) { if ((lp->modembits ^ before_modem_bits) & TMXR_MDM_DTR) { /* DTR changed? */ lp->ser_connect_pending = (lp->modembits & TMXR_MDM_DTR); lp->conn = !(lp->modembits & TMXR_MDM_DTR); } return SCPE_OK; } if (lp->serport) return sim_control_serial (lp->serport, bits_to_set, bits_to_clear, incoming_bits); if ((lp->sock) || (lp->connecting)) { if ((before_modem_bits & bits_to_clear & TMXR_MDM_DTR) != 0) { /* drop DTR? */ if (lp->sock) tmxr_report_disconnection (lp); /* report closure */ tmxr_reset_ln (lp); } } else { if ((lp->destination) && /* Virtual Null Modem Cable */ (bits_to_set & ~before_modem_bits & /* and DTR being Raised */ TMXR_MDM_DTR)) { char msg[512]; sprintf (msg, "tmxr_set_get_modem_bits() - establishing outgoing connection to: %s", lp->destination); tmxr_debug_connect_line (lp, msg); lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (lp->mp->packet ? SIM_SOCK_OPT_NODELAY : 0)); } } } return SCPE_OK; } if ((lp->sock) || (lp->connecting)) { if ((before_modem_bits & bits_to_clear & TMXR_MDM_DTR) != 0) { /* drop DTR? */ if (lp->sock) tmxr_report_disconnection (lp); /* report closure */ tmxr_reset_ln (lp); } } if ((lp->serport) && (!lp->loopback)) sim_control_serial (lp->serport, 0, 0, incoming_bits); return SCPE_INCOMP; } /* Enable or Disable loopback mode on a line Inputs: lp - the line to change enable_loopback - enable or disable flag Output: none Implementation note: 1) When enabling loopback mode, this API will disconnect any currently connected TCP or Serial session. 2) When disabling loopback mode, prior network connections and/or serial port connections will be restored. */ t_stat tmxr_set_line_loopback (TMLN *lp, t_bool enable_loopback) { if (lp->loopback == (enable_loopback != FALSE)) return SCPE_OK; /* Nothing to do */ lp->loopback = (enable_loopback != FALSE); if (lp->loopback) { lp->lpbsz = lp->rxbsz; lp->lpb = (char *)realloc(lp->lpb, lp->lpbsz); lp->lpbcnt = lp->lpbpi = lp->lpbpr = 0; if (!lp->conn) lp->ser_connect_pending = TRUE; } else { free (lp->lpb); lp->lpb = NULL; lp->lpbsz = 0; } return SCPE_OK; } t_bool tmxr_get_line_loopback (TMLN *lp) { return (lp->loopback != FALSE); } /* Enable or Disable halfduplex mode on a line Inputs: lp - the line to change enable_halfduplex - enable or disable flag Output: none When a network connected line is in halfduplex mode, DCD modem signal track with CTS. When not in halfduplex mode the DCD modem signal for network connected lines tracks with DSR. */ t_stat tmxr_set_line_halfduplex (TMLN *lp, t_bool enable_halfduplex) { if (lp->halfduplex == (enable_halfduplex != FALSE)) return SCPE_OK; /* Nothing to do */ lp->halfduplex = (enable_halfduplex != FALSE); return SCPE_OK; } t_bool tmxr_get_line_halfduplex (TMLN *lp) { return (lp->halfduplex != FALSE); } t_stat tmxr_set_config_line (TMLN *lp, CONST char *config) { t_stat r; tmxr_debug_trace_line (lp, "tmxr_set_config_line()"); if (lp->serport) r = sim_config_serial (lp->serport, config); else { lp->serconfig = (char *)realloc (lp->serconfig, 1 + strlen (config)); strcpy (lp->serconfig, config); r = tmxr_set_line_speed (lp, lp->serconfig);; if (r != SCPE_OK) { free (lp->serconfig); lp->serconfig = NULL; } } if ((r == SCPE_OK) && (lp->mp) && (lp->mp->uptr)) /* Record port state for proper restore */ lp->mp->uptr->filename = tmxr_mux_attach_string (lp->mp->uptr->filename, lp->mp); return r; } /* Get character from specific line Inputs: *lp = pointer to terminal line descriptor Output: valid + char, 0 if line Implementation note: 1. If a line break was detected coincident with the current character, the receive break status associated with the character is cleared, and SCPE_BREAK is ORed into the return value. */ int32 tmxr_input_pending_ln (TMLN *lp) { return (lp->rxbpi - lp->rxbpr); } int32 tmxr_getc_ln (TMLN *lp) { int32 j; t_stat val = 0; uint32 tmp; tmxr_debug_trace_line (lp, "tmxr_getc_ln()"); if ((lp->conn && lp->rcve) && /* conn & enb & */ ((!lp->rxbps) || /* (!rate limited || enough time passed)? */ (sim_gtime () >= lp->rxnexttime))) { if (!sim_send_poll_data (&lp->send, &val)) { /* injected input characters available? */ j = lp->rxbpi - lp->rxbpr; /* # input chrs */ if (j) { /* any? */ tmp = lp->rxb[lp->rxbpr]; /* get char */ val = TMXR_VALID | (tmp & 0377); /* valid + chr */ if (lp->rbr[lp->rxbpr]) { /* break? */ lp->rbr[lp->rxbpr] = 0; /* clear status */ val = val | SCPE_BREAK; /* indicate to caller */ } lp->rxbpr = lp->rxbpr + 1; /* adv pointer */ } } } /* end if conn */ if (lp->rxbpi == lp->rxbpr) /* empty? zero ptrs */ lp->rxbpi = lp->rxbpr = 0; if (lp->rxbps) { if (val) lp->rxnexttime = floor (sim_gtime () + ((lp->rxdelta * sim_timer_inst_per_sec ())/lp->rxbpsfactor)); } tmxr_debug_return(lp, val); return val; } /* Get packet from specific line Inputs: *lp = pointer to terminal line descriptor **pbuf = pointer to pointer of packet contents *psize = pointer to packet size frame_byte - byte which separates packets in the tcp stream (0 means no separation character) Output: SCPE_LOST link state lost SCPE_OK Packet returned OR no packet available Implementation notes: 1. If a packet is not yet available, then the pbuf address returned is NULL, but success (SCPE_OK) is returned */ t_stat tmxr_get_packet_ln (TMLN *lp, const uint8 **pbuf, size_t *psize) { return tmxr_get_packet_ln_ex (lp, pbuf, psize, 0); } t_stat tmxr_get_packet_ln_ex (TMLN *lp, const uint8 **pbuf, size_t *psize, uint8 frame_byte) { int32 c; size_t pktsize; size_t fc_size = (frame_byte ? 1 : 0); while (TMXR_VALID & (c = tmxr_getc_ln (lp))) { if (lp->rxpboffset + 3 > lp->rxpbsize) { lp->rxpbsize += 512; lp->rxpb = (uint8 *)realloc (lp->rxpb, lp->rxpbsize); } if ((lp->rxpboffset == 0) && (fc_size) && (c != frame_byte)) { tmxr_debug (TMXR_DBG_PRCV, lp, "Received Unexpected Framing Byte", (char *)&lp->rxpb[lp->rxpboffset], 1); continue; } if ((lp->datagram) && (lp->rxpboffset == fc_size)) { /* Datagram packet length is provided as a part of the natural datagram delivery, for TCP lines, we read the packet length from the data stream. So, here we stuff packet size into head of packet buffer so it looks like it was delivered by TCP and the below return logic doesn't have to worry */ lp->rxpb[lp->rxpboffset++] = (uint8)(((1 + lp->rxbpi - lp->rxbpr) >> 8) & 0xFF); lp->rxpb[lp->rxpboffset++] = (uint8)((1 + lp->rxbpi - lp->rxbpr) & 0xFF); } lp->rxpb[lp->rxpboffset++] = c & 0xFF; if (lp->rxpboffset >= (2 + fc_size)) { pktsize = (lp->rxpb[0+fc_size] << 8) | lp->rxpb[1+fc_size]; if (pktsize == (lp->rxpboffset - 2)) { ++lp->rxpcnt; *pbuf = &lp->rxpb[2+fc_size]; *psize = pktsize; lp->rxpboffset = 0; tmxr_debug (TMXR_DBG_PRCV, lp, "Received Packet", (char *)&lp->rxpb[2+fc_size], pktsize); return SCPE_OK; } } } *pbuf = NULL; *psize = 0; if (lp->conn) return SCPE_OK; return SCPE_LOST; } /* Poll for input Inputs: *mp = pointer to terminal multiplexer descriptor Outputs: none */ void tmxr_poll_rx (TMXR *mp) { int32 i, nbytes, j; TMLN *lp; tmxr_debug_trace (mp, "tmxr_poll_rx()"); for (i = 0; i < mp->lines; i++) { /* loop thru lines */ lp = mp->ldsc + i; /* get line desc */ if (!(lp->sock || lp->serport || lp->loopback) || !(lp->rcve)) /* skip if not connected */ continue; nbytes = 0; if (lp->rxbpi == 0) /* need input? */ nbytes = tmxr_read (lp, /* yes, read */ lp->rxbsz - TMXR_GUARD); /* leave spc for Telnet cruft */ else if (lp->tsta) /* in Telnet seq? */ nbytes = tmxr_read (lp, /* yes, read to end */ lp->rxbsz - lp->rxbpi); if (nbytes < 0) { /* line error? */ if (!lp->datagram) { /* ignore errors reading UDP sockets */ if (!lp->txbfd || lp->notelnet) lp->txbpi = lp->txbpr = 0; /* Drop the data we already know we can't send */ tmxr_close_ln (lp); /* disconnect line */ } } else if (nbytes > 0) { /* if data rcvd */ tmxr_debug (TMXR_DBG_RCV, lp, "Received", &(lp->rxb[lp->rxbpi]), nbytes); j = lp->rxbpi; /* start of data */ lp->rxbpi = lp->rxbpi + nbytes; /* adv pointers */ lp->rxcnt = lp->rxcnt + nbytes; /* Examine new data, remove TELNET cruft before making input available */ if (!lp->notelnet) { /* Are we looking for telnet interpretation? */ for (; j < lp->rxbpi; ) { /* loop thru char */ u_char tmp = (u_char)lp->rxb[j]; /* get char */ switch (lp->tsta) { /* case tlnt state */ case TNS_NORM: /* normal */ if (tmp == TN_IAC) { /* IAC? */ lp->tsta = TNS_IAC; /* change state */ tmxr_rmvrc (lp, j); /* remove char */ break; } if ((tmp == TN_CR) && lp->dstb) /* CR, no bin */ lp->tsta = TNS_CRPAD; /* skip pad char */ j = j + 1; /* advance j */ break; case TNS_IAC: /* IAC prev */ if (tmp == TN_IAC) { /* IAC + IAC */ lp->tsta = TNS_NORM; /* treat as normal */ j = j + 1; /* advance j */ break; /* keep IAC */ } if (tmp == TN_BRK) { /* IAC + BRK? */ lp->tsta = TNS_NORM; /* treat as normal */ lp->rxb[j] = 0; /* char is null */ lp->rbr[j] = 1; /* flag break */ j = j + 1; /* advance j */ break; } switch (tmp) { case TN_WILL: /* IAC + WILL? */ lp->tsta = TNS_WILL; break; case TN_WONT: /* IAC + WONT? */ lp->tsta = TNS_WONT; break; case TN_DO: /* IAC + DO? */ lp->tsta = TNS_DO; break; case TN_DONT: /* IAC + DONT? */ lp->tsta = TNS_SKIP; /* IAC + other */ break; case TN_GA: case TN_EL: /* IAC + other 2 byte types */ case TN_EC: case TN_AYT: case TN_AO: case TN_IP: case TN_NOP: lp->tsta = TNS_NORM; /* ignore */ break; case TN_SB: /* IAC + SB sub-opt negotiation */ case TN_DATAMK: /* IAC + data mark */ case TN_SE: /* IAC + SE sub-opt end */ lp->tsta = TNS_NORM; /* ignore */ break; } tmxr_rmvrc (lp, j); /* remove char */ break; case TNS_WILL: /* IAC+WILL prev */ if ((tmp == TN_STATUS) || (tmp == TN_TIMING) || (tmp == TN_NAOCRD) || (tmp == TN_NAOHTS) || (tmp == TN_NAOHTD) || (tmp == TN_NAOFFD) || (tmp == TN_NAOVTS) || (tmp == TN_NAOVTD) || (tmp == TN_NAOLFD) || (tmp == TN_EXTEND) || (tmp == TN_LOGOUT) || (tmp == TN_BM) || (tmp == TN_DET) || (tmp == TN_SENDLO) || (tmp == TN_TERMTY) || (tmp == TN_ENDREC) || (tmp == TN_TUID) || (tmp == TN_OUTMRK) || (tmp == TN_TTYLOC) || (tmp == TN_3270) || (tmp == TN_X3PAD) || (tmp == TN_NAWS) || (tmp == TN_TERMSP) || (tmp == TN_TOGFLO) || (tmp == TN_XDISPL) || (tmp == TN_ENVIRO) || (tmp == TN_AUTH) || (tmp == TN_ENCRYP) || (tmp == TN_NEWENV) || (tmp == TN_TN3270) || (tmp == TN_CHARST) || (tmp == TN_COMPRT) || (tmp == TN_KERMIT)) { /* Reject (DONT) these 'uninteresting' options only one time to avoid loops */ if (0 == (lp->telnet_sent_opts[tmp] & TNOS_DONT)) { lp->notelnet = TRUE; /* Temporarily disable so */ tmxr_putc_ln (lp, TN_IAC); /* IAC gets injected bare */ lp->notelnet = FALSE; tmxr_putc_ln (lp, TN_DONT); tmxr_putc_ln (lp, tmp); lp->telnet_sent_opts[tmp] |= TNOS_DONT;/* Record DONT sent */ } } case TNS_WONT: /* IAC+WILL/WONT prev */ if (tmp == TN_BIN) { /* BIN? */ if (lp->tsta == TNS_WILL) { lp->dstb = 0; } else { lp->dstb = 1; } } tmxr_rmvrc (lp, j); /* remove it */ lp->tsta = TNS_NORM; /* next normal */ break; /* Negotiation with the HP terminal emulator "QCTerm" is not working. QCTerm says "WONT BIN" but sends bare CRs. RFC 854 says: Note that "CR LF" or "CR NUL" is required in both directions (in the default ASCII mode), to preserve the symmetry of the NVT model. ...The protocol requires that a NUL be inserted following a CR not followed by a LF in the data stream. Until full negotiation is implemented, we work around the problem by checking the character following the CR in non-BIN mode and strip it only if it is LF or NUL. This should not affect conforming clients. */ case TNS_CRPAD: /* only LF or NUL should follow CR */ lp->tsta = TNS_NORM; /* next normal */ if ((tmp == TN_LF) || /* CR + LF ? */ (tmp == TN_NUL)) /* CR + NUL? */ tmxr_rmvrc (lp, j); /* remove it */ break; case TNS_DO: /* pending DO request */ if ((tmp == TN_STATUS) || (tmp == TN_TIMING) || (tmp == TN_NAOCRD) || (tmp == TN_NAOHTS) || (tmp == TN_NAOHTD) || (tmp == TN_NAOFFD) || (tmp == TN_NAOVTS) || (tmp == TN_NAOVTD) || (tmp == TN_NAOLFD) || (tmp == TN_EXTEND) || (tmp == TN_LOGOUT) || (tmp == TN_BM) || (tmp == TN_DET) || (tmp == TN_SENDLO) || (tmp == TN_TERMTY) || (tmp == TN_ENDREC) || (tmp == TN_TUID) || (tmp == TN_OUTMRK) || (tmp == TN_TTYLOC) || (tmp == TN_3270) || (tmp == TN_X3PAD) || (tmp == TN_NAWS) || (tmp == TN_TERMSP) || (tmp == TN_TOGFLO) || (tmp == TN_XDISPL) || (tmp == TN_ENVIRO) || (tmp == TN_AUTH) || (tmp == TN_ENCRYP) || (tmp == TN_NEWENV) || (tmp == TN_TN3270) || (tmp == TN_CHARST) || (tmp == TN_COMPRT) || (tmp == TN_KERMIT)) { /* Reject (WONT) these 'uninteresting' options only one time to avoid loops */ if (0 == (lp->telnet_sent_opts[tmp] & TNOS_WONT)) { lp->notelnet = TRUE; /* Temporarily disable so */ tmxr_putc_ln (lp, TN_IAC); /* IAC gets injected bare */ lp->notelnet = FALSE; tmxr_putc_ln (lp, TN_WONT); tmxr_putc_ln (lp, tmp); lp->telnet_sent_opts[tmp] |= TNOS_WONT;/* Record WONT sent */ } } case TNS_SKIP: default: /* skip char */ tmxr_rmvrc (lp, j); /* remove char */ lp->tsta = TNS_NORM; /* next normal */ break; } /* end case state */ } /* end for char */ if (nbytes != (lp->rxbpi-lp->rxbpr)) { tmxr_debug (TMXR_DBG_RCV, lp, "Remaining", &(lp->rxb[lp->rxbpr]), lp->rxbpi-lp->rxbpr); } } } /* end else nbytes */ } /* end for lines */ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ lp = mp->ldsc + i; /* get line desc */ if (lp->rxbpi == lp->rxbpr) /* if buf empty, */ lp->rxbpi = lp->rxbpr = 0; /* reset pointers */ } /* end for */ return; } /* Return count of available characters for line */ int32 tmxr_rqln_bare (const TMLN *lp, t_bool speed) { if ((speed) && (lp->rxbps)) { /* consider speed and rate limiting? */ if (sim_gtime () < lp->rxnexttime) /* too soon? */ return 0; else return (lp->rxbpi - lp->rxbpr + ((lp->rxbpi < lp->rxbpr)? lp->rxbsz : 0)) ? 1 : 0; } return (lp->rxbpi - lp->rxbpr + ((lp->rxbpi < lp->rxbpr)? lp->rxbsz: 0)); } int32 tmxr_rqln (const TMLN *lp) { return tmxr_rqln_bare (lp, TRUE); } /* Store character in line buffer Inputs: *lp = pointer to line descriptor chr = character Outputs: status = ok, connection lost, or stall Implementation note: 1. If the line is not connected, SCPE_LOST is returned. */ t_stat tmxr_putc_ln (TMLN *lp, int32 chr) { if ((lp->conn == FALSE) && /* no conn & not buffered telnet? */ (!lp->txbfd || lp->notelnet)) { ++lp->txdrp; /* lost */ return SCPE_LOST; } tmxr_debug_trace_line (lp, "tmxr_putc_ln()"); #define TXBUF_AVAIL(lp) ((lp->serport ? 2: lp->txbsz) - tmxr_tqln (lp)) #define TXBUF_CHAR(lp, c) { \ lp->txb[lp->txbpi++] = (char)(c); \ lp->txbpi %= lp->txbsz; \ if (lp->txbpi == lp->txbpr) \ lp->txbpr = (1+lp->txbpr)%lp->txbsz, ++lp->txdrp; \ } if ((lp->txbfd && !lp->notelnet) || (TXBUF_AVAIL(lp) > 1)) {/* room for char (+ IAC)? */ if ((TN_IAC == (u_char) chr) && (!lp->notelnet)) /* char == IAC in telnet session? */ TXBUF_CHAR (lp, TN_IAC); /* stuff extra IAC char */ TXBUF_CHAR (lp, chr); /* buffer char & adv pointer */ if ((!lp->txbfd) && (TXBUF_AVAIL (lp) <= TMXR_GUARD))/* near full? */ lp->xmte = 0; /* disable line */ if (lp->txlog) { /* log if available */ extern TMLN *sim_oline; /* Make sure to avoid recursion */ TMLN *save_oline = sim_oline; /* when logging to a socket */ sim_oline = NULL; /* save output socket */ fputc (chr, lp->txlog); /* log to actual file */ sim_oline = save_oline; /* resture output socket */ } sim_exp_check (&lp->expect, chr); /* process expect rules as needed */ return SCPE_OK; /* char sent */ } ++lp->txdrp; lp->xmte = 0; /* no room, dsbl line */ return SCPE_STALL; /* char not sent */ } /* Store packet in line buffer Inputs: *lp = pointer to line descriptor *buf = pointer to packet data size = size of packet frame_char = inter-packet franing character (0 means no frame character) Outputs: status = ok, connection lost, or stall Implementation notea: 1. If the line is not connected, SCPE_LOST is returned. 2. If prior packet transmission still in progress, SCPE_STALL is returned and no packet data is stored. The caller must retry later. */ t_stat tmxr_put_packet_ln (TMLN *lp, const uint8 *buf, size_t size) { return tmxr_put_packet_ln_ex (lp, buf, size, 0); } t_stat tmxr_put_packet_ln_ex (TMLN *lp, const uint8 *buf, size_t size, uint8 frame_byte) { t_stat r; size_t fc_size = (frame_byte ? 1 : 0); size_t pktlen_size = (lp->datagram ? 0 : 2); if ((!lp->conn) && (!lp->loopback)) return SCPE_LOST; if (lp->txppoffset < lp->txppsize) { tmxr_debug (TMXR_DBG_PXMT, lp, "Skipped Sending Packet - Transmit Busy", (char *)&lp->txpb[3], size); return SCPE_STALL; } if (lp->txpbsize < size + pktlen_size + fc_size) { lp->txpbsize = size + pktlen_size + fc_size; lp->txpb = (uint8 *)realloc (lp->txpb, lp->txpbsize); } lp->txpb[0] = frame_byte; if (!lp->datagram) { lp->txpb[0+fc_size] = (size >> 8) & 0xFF; lp->txpb[1+fc_size] = size & 0xFF; } memcpy (lp->txpb + pktlen_size + fc_size, buf, size); lp->txppsize = size + pktlen_size + fc_size; lp->txppoffset = 0; tmxr_debug (TMXR_DBG_PXMT, lp, "Sending Packet", (char *)&lp->txpb[pktlen_size+fc_size], size); ++lp->txpcnt; while ((lp->txppoffset < lp->txppsize) && (SCPE_OK == (r = tmxr_putc_ln (lp, lp->txpb[lp->txppoffset])))) ++lp->txppoffset; tmxr_send_buffered_data (lp); return (lp->conn || lp->loopback) ? SCPE_OK : SCPE_LOST; } /* Poll for output Inputs: *mp = pointer to terminal multiplexer descriptor Outputs: none */ void tmxr_poll_tx (TMXR *mp) { int32 i, nbytes; TMLN *lp; tmxr_debug_trace (mp, "tmxr_poll_tx()"); for (i = 0; i < mp->lines; i++) { /* loop thru lines */ lp = mp->ldsc + i; /* get line desc */ if (!lp->conn) /* skip if !conn */ continue; nbytes = tmxr_send_buffered_data (lp); /* buffered bytes */ if (nbytes == 0) { /* buf empty? enab line */ #if defined(SIM_ASYNCH_MUX) UNIT *ruptr = lp->uptr ? lp->uptr : lp->mp->uptr; if ((ruptr->dynflags & UNIT_TM_POLL) && sim_asynch_enabled && tmxr_rqln (lp)) _sim_activate (ruptr, 0); #endif lp->xmte = 1; /* enable line transmit */ } } /* end for */ return; } /* Send buffered data across network Inputs: *lp = pointer to line descriptor Outputs: returns number of bytes still buffered */ int32 tmxr_send_buffered_data (TMLN *lp) { int32 nbytes, sbytes; t_stat r; tmxr_debug_trace_line (lp, "tmxr_send_buffered_data()"); nbytes = tmxr_tqln(lp); /* avail bytes */ if (nbytes) { /* >0? write */ if (lp->txbpr < lp->txbpi) /* no wrap? */ sbytes = tmxr_write (lp, nbytes); /* write all data */ else sbytes = tmxr_write (lp, lp->txbsz - lp->txbpr);/* write to end buf */ if (sbytes >= 0) { /* ok? */ tmxr_debug (TMXR_DBG_XMT, lp, "Sent", &(lp->txb[lp->txbpr]), sbytes); lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */ if (lp->txbpr >= lp->txbsz) /* wrap? */ lp->txbpr = 0; lp->txcnt = lp->txcnt + sbytes; /* update counts */ nbytes = nbytes - sbytes; if ((nbytes == 0) && (lp->datagram)) /* if Empty buffer on datagram line */ lp->txbpi = lp->txbpr = 0; /* Start next packet at beginning of buffer */ } if (sbytes < 0) { /* I/O Error? */ lp->txbpi = lp->txbpr = 0; /* Drop the data we already know we can't send */ lp->rxpboffset = lp->txppoffset = lp->txppsize = 0;/* Drop the data we already know we can't send */ tmxr_close_ln (lp); /* close line/port on error */ return nbytes; /* done now. */ } if (nbytes && (lp->txbpr == 0)) { /* more data and wrap? */ sbytes = tmxr_write (lp, nbytes); if (sbytes > 0) { /* ok */ tmxr_debug (TMXR_DBG_XMT, lp, "Sent", lp->txb, sbytes); lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */ if (lp->txbpr >= lp->txbsz) /* wrap? */ lp->txbpr = 0; lp->txcnt = lp->txcnt + sbytes; /* update counts */ nbytes = nbytes - sbytes; } } } /* end if nbytes */ while ((lp->txppoffset < lp->txppsize) && /* buffered packet data? */ (lp->txbsz > nbytes) && /* and room in xmt buffer */ (SCPE_OK == (r = tmxr_putc_ln (lp, lp->txpb[lp->txppoffset])))) ++lp->txppoffset; if ((nbytes == 0) && (tmxr_tqln(lp) > 0)) return tmxr_send_buffered_data (lp); return tmxr_tqln(lp) + tmxr_tpqln(lp); } /* Return count of buffered characters for line */ int32 tmxr_tqln (const TMLN *lp) { return (lp->txbpi - lp->txbpr + ((lp->txbpi < lp->txbpr)? lp->txbsz: 0)); } /* Return count of buffered packet characters for line */ int32 tmxr_tpqln (const TMLN *lp) { return (lp->txppsize - lp->txppoffset); } /* Return transmit packet busy status for line */ t_bool tmxr_tpbusyln (const TMLN *lp) { return (0 != (lp->txppsize - lp->txppoffset)); } static void _mux_detach_line (TMLN *lp, t_bool close_listener, t_bool close_connecting) { if (close_listener && lp->master) { sim_close_sock (lp->master); lp->master = 0; free (lp->port); lp->port = NULL; } if (lp->sock) { /* if existing tcp, drop it */ tmxr_report_disconnection (lp); /* report disconnection */ tmxr_reset_ln (lp); } if (close_connecting) { free (lp->destination); lp->destination = NULL; if (lp->connecting) { /* if existing outgoing tcp, drop it */ lp->sock = lp->connecting; lp->connecting = 0; tmxr_reset_ln (lp); } } if (lp->serport) { /* close current serial connection */ tmxr_reset_ln (lp); sim_control_serial (lp->serport, 0, TMXR_MDM_DTR|TMXR_MDM_RTS, NULL);/* drop DTR and RTS */ sim_close_serial (lp->serport); lp->serport = 0; free (lp->serconfig); lp->serconfig = NULL; free (lp->destination); lp->destination = NULL; } tmxr_set_line_loopback (lp, FALSE); } t_stat tmxr_detach_ln (TMLN *lp) { UNIT *uptr = NULL; tmxr_debug_trace_line (lp, "tmxr_detach_ln()"); _mux_detach_line (lp, TRUE, TRUE); if (lp->mp) { if (lp->uptr) uptr = lp->uptr; else uptr = lp->mp->uptr; } if (uptr && uptr->filename) { /* Revise the unit's connect string to reflect the current attachments */ uptr->filename = tmxr_mux_attach_string (uptr->filename, lp->mp); /* No connections or listeners exist, then we're equivalent to being fully detached. We should reflect that */ if (uptr->filename == NULL) tmxr_detach (lp->mp, uptr); } return SCPE_OK; } static int32 _tmln_speed_delta (CONST char *cptr) { struct { const char *bps; int32 delta; } *spd, speeds[] = { {"50", TMLN_SPD_50_BPS}, {"75", TMLN_SPD_75_BPS}, {"110", TMLN_SPD_110_BPS}, {"134", TMLN_SPD_134_BPS}, {"150", TMLN_SPD_150_BPS}, {"300", TMLN_SPD_300_BPS}, {"600", TMLN_SPD_600_BPS}, {"1200", TMLN_SPD_1200_BPS}, {"1800", TMLN_SPD_1800_BPS}, {"2000", TMLN_SPD_2000_BPS}, {"2400", TMLN_SPD_2400_BPS}, {"3600", TMLN_SPD_3600_BPS}, {"4800", TMLN_SPD_4800_BPS}, {"7200", TMLN_SPD_7200_BPS}, {"9600", TMLN_SPD_9600_BPS}, {"19200", TMLN_SPD_19200_BPS}, {"38400", TMLN_SPD_38400_BPS}, {"57600", TMLN_SPD_57600_BPS}, {"76800", TMLN_SPD_76800_BPS}, {"115200", TMLN_SPD_115200_BPS}, {"0", 0}}; /* End of List, last valid value */ int nspeed; char speed[24]; nspeed = (uint32)strtotv (cptr, &cptr, 10); if ((*cptr != '\0') && (*cptr != '-') && (*cptr != '*')) return -1; sprintf (speed, "%d", nspeed); spd = speeds; while (1) { if (0 == strcmp(spd->bps, speed)) return spd->delta; if (spd->delta == 0) break; ++spd; } return -1; } t_stat tmxr_set_line_speed (TMLN *lp, CONST char *speed) { UNIT *uptr; CONST char *cptr; t_stat r; if (!speed || !*speed) return SCPE_2FARG; if (_tmln_speed_delta (speed) < 0) return SCPE_ARG; lp->rxbps = (uint32)strtotv (speed, &cptr, 10); if (*cptr == '*') { uint32 rxbpsfactor = (uint32) get_uint (cptr+1, 10, 32, &r); if (r != SCPE_OK) return r; lp->rxbpsfactor = TMXR_RX_BPS_UNIT_SCALE * rxbpsfactor; } lp->rxdelta = _tmln_speed_delta (speed); lp->rxnexttime = 0.0; uptr = lp->uptr; if ((!uptr) && (lp->mp)) uptr = lp->mp->uptr; if (uptr) uptr->wait = lp->rxdelta; if (lp->rxbpsfactor == 0.0) lp->rxbpsfactor = TMXR_RX_BPS_UNIT_SCALE; lp->txbps = lp->rxbps; lp->txdelta = lp->rxdelta; lp->txnexttime = lp->rxnexttime; return SCPE_OK; } /* Open a master listening socket (and all of the other variances of connections). A listening socket for the port number described by "cptr" is opened for the multiplexer associated with descriptor "mp". If the open is successful, all lines not currently otherwise connected (via serial, outgoing or direct listener) are initialized for Telnet connections. Initialization for all connection styles (MUX wide listener, per line serial, listener, outgoing, logging, buffering) are handled by this routine. */ t_stat tmxr_open_master (TMXR *mp, CONST char *cptr) { int32 i, line, nextline = -1; char tbuf[CBUFSIZE], listen[CBUFSIZE], destination[CBUFSIZE], logfiletmpl[CBUFSIZE], buffered[CBUFSIZE], hostport[CBUFSIZE], port[CBUFSIZE], option[CBUFSIZE], speed[CBUFSIZE]; SOCKET sock; SERHANDLE serport; CONST char *tptr = cptr; t_bool nolog, notelnet, listennotelnet, modem_control, loopback, datagram, packet; TMLN *lp; t_stat r = SCPE_OK; t_bool not_quiet = (!sim_quiet) && (0 == (sim_switches & SWMASK ('Q'))); if (*tptr == '\0') return SCPE_ARG; for (i = 0; i < mp->lines; i++) { /* initialize lines */ lp = mp->ldsc + i; lp->mp = mp; /* set the back pointer */ lp->modem_control = mp->modem_control; if (lp->rxbpsfactor == 0.0) lp->rxbpsfactor = TMXR_RX_BPS_UNIT_SCALE; } mp->ring_sock = INVALID_SOCKET; free (mp->ring_ipad); mp->ring_ipad = NULL; mp->ring_start_time = 0; tmxr_debug_trace (mp, "tmxr_open_master()"); while (*tptr) { line = nextline; memset(logfiletmpl, '\0', sizeof(logfiletmpl)); memset(listen, '\0', sizeof(listen)); memset(destination, '\0', sizeof(destination)); memset(buffered, '\0', sizeof(buffered)); memset(port, '\0', sizeof(port)); memset(option, '\0', sizeof(option)); memset(speed, '\0', sizeof(speed)); nolog = notelnet = listennotelnet = loopback = FALSE; datagram = mp->datagram; packet = mp->packet; if (mp->buffered) sprintf(buffered, "%d", mp->buffered); if (line != -1) notelnet = listennotelnet = mp->notelnet; modem_control = mp->modem_control; while (*tptr) { tptr = get_glyph_nc (tptr, tbuf, ','); if (!tbuf[0]) break; cptr = tbuf; if (!isdigit(*cptr)) { char gbuf[CBUFSIZE]; CONST char *init_cptr = cptr; cptr = get_glyph (cptr, gbuf, '='); if (0 == MATCH_CMD (gbuf, "LINE")) { if ((NULL == cptr) || ('\0' == *cptr)) return sim_messagef (SCPE_2FARG, "Missing Line Specifier\n"); nextline = (int32) get_uint (cptr, 10, mp->lines-1, &r); if (r) return sim_messagef (SCPE_ARG, "Invalid Line Specifier: %s\n", cptr); break; } if (0 == MATCH_CMD (gbuf, "LOG")) { if ((NULL == cptr) || ('\0' == *cptr)) return sim_messagef (SCPE_2FARG, "Missing Log Specifier\n"); strncpy(logfiletmpl, cptr, sizeof(logfiletmpl)-1); continue; } if (0 == MATCH_CMD (gbuf, "LOOPBACK")) { if ((NULL != cptr) && ('\0' != *cptr)) return sim_messagef (SCPE_2MARG, "Unexpected Loopback Specifier: %s\n", cptr); loopback = TRUE; continue; } if ((0 == MATCH_CMD (gbuf, "NOBUFFERED")) || (0 == MATCH_CMD (gbuf, "UNBUFFERED"))) { if ((NULL != cptr) && ('\0' != *cptr)) return sim_messagef (SCPE_2MARG, "Unexpected Unbuffered Specifier: %s\n", cptr); buffered[0] = '\0'; continue; } if (0 == MATCH_CMD (gbuf, "BUFFERED")) { if ((NULL == cptr) || ('\0' == *cptr)) strcpy (buffered, "32768"); else { i = (int32) get_uint (cptr, 10, 1024*1024, &r); if (r || (i == 0)) return sim_messagef (SCPE_ARG, "Invalid Buffered Specifier: %s\n", cptr); sprintf(buffered, "%d", i); } continue; } if (0 == MATCH_CMD (gbuf, "NOLOG")) { if ((NULL != cptr) && ('\0' != *cptr)) return sim_messagef (SCPE_2MARG, "Unexpected NoLog Specifier: %s\n", cptr); nolog = TRUE; continue; } if (0 == MATCH_CMD (gbuf, "NOMODEM")) { if ((NULL != cptr) && ('\0' != *cptr)) return sim_messagef (SCPE_2MARG, "Unexpected NoModem Specifier: %s\n", cptr); modem_control = FALSE; continue; } if (0 == MATCH_CMD (gbuf, "MODEM")) { if ((NULL != cptr) && ('\0' != *cptr)) return sim_messagef (SCPE_2MARG, "Unexpected Modem Specifier: %s\n", cptr); modem_control = TRUE; continue; } if ((0 == MATCH_CMD (gbuf, "DATAGRAM")) || (0 == MATCH_CMD (gbuf, "UDP"))) { if ((NULL != cptr) && ('\0' != *cptr)) return sim_messagef (SCPE_2MARG, "Unexpected Datagram Specifier: %s\n", cptr); notelnet = datagram = TRUE; continue; } if (0 == MATCH_CMD (gbuf, "PACKET")) { if ((NULL != cptr) && ('\0' != *cptr)) return sim_messagef (SCPE_2MARG, "Unexpected Packet Specifier: %s\n", cptr); packet = TRUE; continue; } if ((0 == MATCH_CMD (gbuf, "STREAM")) || (0 == MATCH_CMD (gbuf, "TCP"))) { if ((NULL != cptr) && ('\0' != *cptr)) return sim_messagef (SCPE_2MARG, "Unexpected Stream Specifier: %s\n", cptr); datagram = FALSE; continue; } if (0 == MATCH_CMD (gbuf, "CONNECT")) { if ((NULL == cptr) || ('\0' == *cptr)) return sim_messagef (SCPE_2FARG, "Missing Connect Specifier\n"); strncpy (destination, cptr, sizeof(destination)-1); continue; } if (0 == MATCH_CMD (gbuf, "SPEED")) { if ((NULL == cptr) || ('\0' == *cptr) || (_tmln_speed_delta (cptr) < 0)) return sim_messagef (SCPE_ARG, "Invalid Speed Specifier: %s\n", (cptr ? cptr : "")); strncpy (speed, cptr, sizeof(speed)-1); continue; } cptr = get_glyph (gbuf, port, ';'); if (sim_parse_addr (port, NULL, 0, NULL, NULL, 0, NULL, NULL)) return sim_messagef (SCPE_ARG, "Invalid Port Specifier: %s\n", port); if (cptr) { char *tptr = gbuf + (cptr - gbuf); get_glyph (cptr, tptr, 0); /* upcase this string */ if (0 == MATCH_CMD (cptr, "NOTELNET")) listennotelnet = TRUE; else if (0 == MATCH_CMD (cptr, "TELNET")) listennotelnet = FALSE; else return sim_messagef (SCPE_ARG, "Invalid Specifier: %s\n", tptr); } cptr = init_cptr; } cptr = get_glyph_nc (cptr, port, ';'); sock = sim_master_sock (port, &r); /* make master socket to validate port */ if (r) return sim_messagef (SCPE_ARG, "Invalid Port Specifier: %s\n", port); if (sock == INVALID_SOCKET) /* open error */ return sim_messagef (SCPE_OPENERR, "Can't open network port: %s\n", port); sim_close_sock (sock); sim_os_ms_sleep (2); /* let the close finish (required on some platforms) */ strcpy (listen, port); cptr = get_glyph (cptr, option, ';'); if (option[0]) { if (0 == MATCH_CMD (option, "NOTELNET")) listennotelnet = TRUE; else if (0 == MATCH_CMD (option, "TELNET")) listennotelnet = FALSE; else return sim_messagef (SCPE_ARG, "Invalid Specifier: %s\n", option); } } if (destination[0]) { /* Validate destination */ serport = sim_open_serial (destination, NULL, &r); if (serport != INVALID_HANDLE) { sim_close_serial (serport); if (strchr (destination, ';') && mp->modem_control && !(sim_switches & SIM_SW_REST)) return sim_messagef (SCPE_ARG, "Serial line parameters must be set within simulated OS: %s\n", 1 + strchr (destination, ';')); } else { char *eptr; memset (hostport, '\0', sizeof(hostport)); strncpy (hostport, destination, sizeof(hostport)-1); if ((eptr = strchr (hostport, ';'))) *(eptr++) = '\0'; if (eptr) { get_glyph (eptr, eptr, 0); /* upcase this string */ if (0 == MATCH_CMD (eptr, "NOTELNET")) notelnet = TRUE; else if (0 == MATCH_CMD (eptr, "TELNET")) if (datagram) return sim_messagef (SCPE_ARG, "Telnet invalid on Datagram socket\n"); else notelnet = FALSE; else return sim_messagef (SCPE_ARG, "Unexpected specifier: %s\n", eptr); } sock = sim_connect_sock_ex (NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (packet ? SIM_SOCK_OPT_NODELAY : 0)); if (sock != INVALID_SOCKET) sim_close_sock (sock); else return sim_messagef (SCPE_ARG, "Invalid destination: %s\n", hostport); } } if (line == -1) { if (modem_control != mp->modem_control) return SCPE_ARG; if (logfiletmpl[0]) { strncpy(mp->logfiletmpl, logfiletmpl, sizeof(mp->logfiletmpl)-1); for (i = 0; i < mp->lines; i++) { lp = mp->ldsc + i; sim_close_logfile (&lp->txlogref); lp->txlog = NULL; lp->txlogname = (char *)realloc(lp->txlogname, CBUFSIZE); if (mp->lines > 1) sprintf(lp->txlogname, "%s_%d", mp->logfiletmpl, i); else strcpy (lp->txlogname, mp->logfiletmpl); r = sim_open_logfile (lp->txlogname, TRUE, &lp->txlog, &lp->txlogref); if (r != SCPE_OK) { free (lp->txlogname); lp->txlogname = NULL; break; } } } mp->buffered = atoi(buffered); for (i = 0; i < mp->lines; i++) { /* initialize line buffers */ lp = mp->ldsc + i; if (mp->buffered) { lp->txbsz = mp->buffered; lp->txbfd = 1; lp->rxbsz = mp->buffered; } else { lp->txbsz = TMXR_MAXBUF; lp->txbfd = 0; lp->rxbsz = TMXR_MAXBUF; } lp->txbpi = lp->txbpr = 0; lp->txb = (char *)realloc(lp->txb, lp->txbsz); lp->rxb = (char *)realloc(lp->rxb, lp->rxbsz); lp->rbr = (char *)realloc(lp->rbr, lp->rxbsz); } if (nolog) { mp->logfiletmpl[0] = '\0'; for (i = 0; i < mp->lines; i++) { /* close line logs */ lp = mp->ldsc + i; free(lp->txlogname); lp->txlogname = NULL; if (lp->txlog) { sim_close_logfile (&lp->txlogref); lp->txlog = NULL; } } } if ((listen[0]) && (!datagram)) { sock = sim_master_sock (listen, &r); /* make master socket */ if (r) return sim_messagef (SCPE_ARG, "Invalid network listen port: %s\n", listen); if (sock == INVALID_SOCKET) /* open error */ return sim_messagef (SCPE_OPENERR, "Can't open network socket for listen port: %s\n", listen); if (mp->port) { /* close prior listener */ sim_close_sock (mp->master); mp->master = 0; free (mp->port); mp->port = NULL; } if (not_quiet) sim_printf ("Listening on port %s\n", listen); mp->port = (char *)realloc (mp->port, 1 + strlen (listen)); strcpy (mp->port, listen); /* save port */ mp->master = sock; /* save master socket */ mp->ring_sock = INVALID_SOCKET; free (mp->ring_ipad); mp->ring_ipad = NULL; mp->ring_start_time = 0; mp->notelnet = listennotelnet; /* save desired telnet behavior flag */ for (i = 0; i < mp->lines; i++) { /* initialize lines */ lp = mp->ldsc + i; lp->mp = mp; /* set the back pointer */ lp->packet = mp->packet; if (lp->serport) { /* serial port attached? */ tmxr_reset_ln (lp); /* close current serial connection */ sim_control_serial (lp->serport, 0, TMXR_MDM_DTR|TMXR_MDM_RTS, NULL);/* drop DTR and RTS */ sim_close_serial (lp->serport); lp->serport = 0; free (lp->serconfig); lp->serconfig = NULL; } else { if (speed[0]) tmxr_set_line_speed (lp, speed); } tmxr_init_line (lp); /* initialize line state */ lp->sock = 0; /* clear the socket */ } } if (loopback) { if (mp->lines > 1) return sim_messagef (SCPE_ARG, "Ambiguous Loopback specification\n"); if (not_quiet) sim_printf ("Operating in loopback mode\n"); for (i = 0; i < mp->lines; i++) { lp = mp->ldsc + i; tmxr_set_line_loopback (lp, loopback); if (speed[0]) tmxr_set_line_speed (lp, speed); } } if (destination[0]) { if (mp->lines > 1) return sim_messagef (SCPE_ARG, "Ambiguous Destination specification\n"); lp = &mp->ldsc[0]; serport = sim_open_serial (destination, lp, &r); if (serport != INVALID_HANDLE) { _mux_detach_line (lp, TRUE, TRUE); if (lp->mp && lp->mp->master) { /* if existing listener, close it */ sim_close_sock (lp->mp->master); lp->mp->master = 0; free (lp->mp->port); lp->mp->port = NULL; } lp->destination = (char *)malloc(1+strlen(destination)); strcpy (lp->destination, destination); lp->mp = mp; lp->serport = serport; lp->ser_connect_pending = TRUE; lp->notelnet = TRUE; tmxr_init_line (lp); /* init the line state */ if (!lp->mp->modem_control) /* raise DTR and RTS for non modem control lines */ sim_control_serial (lp->serport, TMXR_MDM_DTR|TMXR_MDM_RTS, 0, NULL); lp->cnms = sim_os_msec (); /* record time of connection */ if (sim_switches & SWMASK ('V')) { /* -V flag reports connection on port */ sim_os_ms_sleep (TMXR_DTR_DROP_TIME); tmxr_report_connection (mp, lp); /* report the connection to the line */ } } else { lp->datagram = datagram; if (datagram) { if (listen[0]) { lp->port = (char *)realloc (lp->port, 1 + strlen (listen)); strcpy (lp->port, listen); /* save port */ } else return sim_messagef (SCPE_ARG, "Missing listen port for Datagram socket\n"); } lp->packet = packet; sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (packet ? SIM_SOCK_OPT_NODELAY : 0)); if (sock != INVALID_SOCKET) { _mux_detach_line (lp, FALSE, TRUE); lp->destination = (char *)malloc(1+strlen(hostport)); strcpy (lp->destination, hostport); lp->mp = mp; if (!lp->modem_control || (lp->modembits & TMXR_MDM_DTR)) { lp->connecting = sock; lp->ipad = (char *)malloc (1 + strlen (lp->destination)); strcpy (lp->ipad, lp->destination); } else sim_close_sock (sock); lp->notelnet = notelnet; tmxr_init_line (lp); /* init the line state */ if (speed[0] && (!datagram)) tmxr_set_line_speed (lp, speed); return SCPE_OK; } else return sim_messagef (SCPE_ARG, "Can't open %s socket on %s%s%s\n", datagram ? "Datagram" : "Stream", datagram ? listen : "", datagram ? "<->" : "", hostport); } } } else { /* line specific attach */ lp = &mp->ldsc[line]; lp->mp = mp; if (logfiletmpl[0]) { sim_close_logfile (&lp->txlogref); lp->txlog = NULL; lp->txlogname = (char *)realloc (lp->txlogname, 1 + strlen (logfiletmpl)); strcpy (lp->txlogname, logfiletmpl); r = sim_open_logfile (lp->txlogname, TRUE, &lp->txlog, &lp->txlogref); if (r == SCPE_OK) setvbuf(lp->txlog, NULL, _IOFBF, 65536); else { free (lp->txlogname); lp->txlogname = NULL; return sim_messagef (r, "Can't open log file: %s\n", logfiletmpl); } } if (buffered[0] == '\0') { lp->rxbsz = lp->txbsz = TMXR_MAXBUF; lp->txbfd = 0; } else { lp->rxbsz = lp->txbsz = atoi(buffered); lp->txbfd = 1; } lp->txbpi = lp->txbpr = 0; lp->txb = (char *)realloc (lp->txb, lp->txbsz); lp->rxb = (char *)realloc(lp->rxb, lp->rxbsz); lp->rbr = (char *)realloc(lp->rbr, lp->rxbsz); lp->packet = packet; if (nolog) { free(lp->txlogname); lp->txlogname = NULL; if (lp->txlog) { sim_close_logfile (&lp->txlogref); lp->txlog = NULL; } } if ((listen[0]) && (!datagram)) { if ((mp->lines == 1) && (mp->master)) return sim_messagef (SCPE_ARG, "Single Line MUX can have either line specific OR MUS listener but NOT both\n"); sock = sim_master_sock (listen, &r); /* make master socket */ if (r) return sim_messagef (SCPE_ARG, "Invalid Listen Specification: %s\n", listen); if (sock == INVALID_SOCKET) /* open error */ return sim_messagef (SCPE_OPENERR, "Can't listen on port: %s\n", listen); _mux_detach_line (lp, TRUE, FALSE); if (not_quiet) sim_printf ("Line %d Listening on port %s\n", line, listen); lp->port = (char *)realloc (lp->port, 1 + strlen (listen)); strcpy (lp->port, listen); /* save port */ lp->master = sock; /* save master socket */ if (listennotelnet != mp->notelnet) lp->notelnet = listennotelnet; else lp->notelnet = mp->notelnet; } if (destination[0]) { serport = sim_open_serial (destination, lp, &r); if (serport != INVALID_HANDLE) { _mux_detach_line (lp, TRUE, TRUE); lp->destination = (char *)malloc(1+strlen(destination)); strcpy (lp->destination, destination); lp->serport = serport; lp->ser_connect_pending = TRUE; lp->notelnet = TRUE; tmxr_init_line (lp); /* init the line state */ if (!lp->mp->modem_control) /* raise DTR and RTS for non modem control lines */ sim_control_serial (lp->serport, TMXR_MDM_DTR|TMXR_MDM_RTS, 0, NULL); lp->cnms = sim_os_msec (); /* record time of connection */ if (sim_switches & SWMASK ('V')) { /* -V flag reports connection on port */ sim_os_ms_sleep (TMXR_DTR_DROP_TIME); tmxr_report_connection (mp, lp); /* report the connection to the line */ } } else { lp->datagram = datagram; if (datagram) { if (listen[0]) { lp->port = (char *)realloc (lp->port, 1 + strlen (listen)); strcpy (lp->port, listen); /* save port */ } else return sim_messagef (SCPE_ARG, "Missing listen port for Datagram socket\n"); } sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (packet ? SIM_SOCK_OPT_NODELAY : 0)); if (sock != INVALID_SOCKET) { _mux_detach_line (lp, FALSE, TRUE); lp->destination = (char *)malloc(1+strlen(hostport)); strcpy (lp->destination, hostport); if (!lp->modem_control || (lp->modembits & TMXR_MDM_DTR)) { lp->connecting = sock; lp->ipad = (char *)malloc (1 + strlen (lp->destination)); strcpy (lp->ipad, lp->destination); } else sim_close_sock (sock); lp->notelnet = notelnet; tmxr_init_line (lp); /* init the line state */ } else return sim_messagef (SCPE_ARG, "Can't open %s socket on %s%s%s\n", datagram ? "Datagram" : "Stream", datagram ? listen : "", datagram ? "<->" : "", hostport); } } if (loopback) { tmxr_set_line_loopback (lp, loopback); if (not_quiet) sim_printf ("Line %d operating in loopback mode\n", line); } lp->modem_control = modem_control; if (speed[0] && (!datagram) && (!lp->serport)) tmxr_set_line_speed (lp, speed); r = SCPE_OK; } } if (r == SCPE_OK) tmxr_add_to_open_list (mp); return r; } /* Declare which unit polls for input Inputs: *mp = the mux line = the line number *uptr_poll = the unit which polls Outputs: none Implementation note: Only devices which poll on a unit different from the unit provided at MUX attach time need call this function. Calling this API is necessary for asynchronous multiplexer support and unnecessary otherwise. */ t_stat tmxr_set_line_unit (TMXR *mp, int line, UNIT *uptr_poll) { if ((line < 0) || (line >= mp->lines)) return SCPE_ARG; mp->ldsc[line].uptr = uptr_poll; return SCPE_OK; } /* Declare which unit polls for output Inputs: *mp = the mux line = the line number *uptr_poll = the unit which polls for output Outputs: none Implementation note: Only devices which poll on a unit different from the unit provided at MUX attach time need call this function ABD different from the unit which polls for input. Calling this API is necessary for asynchronous multiplexer support and unnecessary otherwise. */ t_stat tmxr_set_line_output_unit (TMXR *mp, int line, UNIT *uptr_poll) { if ((line < 0) || (line >= mp->lines)) return SCPE_ARG; mp->ldsc[line].o_uptr = uptr_poll; return SCPE_OK; } /* Declare which units are the console input and out devices Inputs: *rxuptr = the console input unit *txuptr = the console output unit Outputs: none Implementation note: This routine is exported by the tmxr library so that it gets defined to code which uses it by including sim_tmxr.h. Including sim_tmxr.h is necessary so that sim_activate is properly defined in the caller's code to actually call tmxr_activate. */ t_stat tmxr_set_console_units (UNIT *rxuptr, UNIT *txuptr) { extern TMXR sim_con_tmxr; tmxr_set_line_unit (&sim_con_tmxr, 0, rxuptr); tmxr_set_line_output_unit (&sim_con_tmxr, 0, txuptr); return SCPE_OK; } static TMXR **tmxr_open_devices = NULL; static int tmxr_open_device_count = 0; #if defined(SIM_ASYNCH_MUX) pthread_t sim_tmxr_poll_thread; /* Polling Thread Id */ #if defined(_WIN32) || defined(VMS) pthread_t sim_tmxr_serial_poll_thread; /* Serial Polling Thread Id */ pthread_cond_t sim_tmxr_serial_startup_cond; #endif pthread_mutex_t sim_tmxr_poll_lock; pthread_cond_t sim_tmxr_poll_cond; pthread_cond_t sim_tmxr_startup_cond; int32 sim_tmxr_poll_count = 0; t_bool sim_tmxr_poll_running = FALSE; static void * _tmxr_poll(void *arg) { struct timeval timeout; int timeout_usec; DEVICE *dptr = tmxr_open_devices[0]->dptr; UNIT **units = NULL; UNIT **activated = NULL; SOCKET *sockets = NULL; int wait_count = 0; /* Boost Priority for this I/O thread vs the CPU instruction execution thread which, in general, won't be readily yielding the processor when this thread needs to run */ sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - starting\n"); units = (UNIT **)calloc(FD_SETSIZE, sizeof(*units)); activated = (UNIT **)calloc(FD_SETSIZE, sizeof(*activated)); sockets = (SOCKET *)calloc(FD_SETSIZE, sizeof(*sockets)); timeout_usec = 1000000; pthread_mutex_lock (&sim_tmxr_poll_lock); pthread_cond_signal (&sim_tmxr_startup_cond); /* Signal we're ready to go */ while (sim_asynch_enabled) { int i, j, status, select_errno; fd_set readfds, errorfds; int socket_count; SOCKET max_socket_fd; TMXR *mp; DEVICE *d; if ((tmxr_open_device_count == 0) || (!sim_is_running)) { for (j=0; j<wait_count; ++j) { d = find_dev_from_unit(activated[j]); sim_debug (TMXR_DBG_ASY, d, "_tmxr_poll() - Removing interest in %s. Other interest: %d\n", sim_uname(activated[j]), activated[j]->a_poll_waiter_count); --activated[j]->a_poll_waiter_count; --sim_tmxr_poll_count; } break; } /* If we started something we should wait for, let it finish before polling again */ if (wait_count) { sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - waiting for %d units\n", wait_count); pthread_cond_wait (&sim_tmxr_poll_cond, &sim_tmxr_poll_lock); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - continuing with timeout of %dms\n", timeout_usec/1000); } FD_ZERO (&readfds); FD_ZERO (&errorfds); for (i=max_socket_fd=socket_count=0; i<tmxr_open_device_count; ++i) { mp = tmxr_open_devices[i]; if ((mp->master) && (mp->uptr->dynflags&UNIT_TM_POLL)) { units[socket_count] = mp->uptr; sockets[socket_count] = mp->master; FD_SET (mp->master, &readfds); FD_SET (mp->master, &errorfds); if (mp->master > max_socket_fd) max_socket_fd = mp->master; ++socket_count; } for (j=0; j<mp->lines; ++j) { if (mp->ldsc[j].sock) { units[socket_count] = mp->ldsc[j].uptr; if (units[socket_count] == NULL) units[socket_count] = mp->uptr; sockets[socket_count] = mp->ldsc[j].sock; FD_SET (mp->ldsc[j].sock, &readfds); FD_SET (mp->ldsc[j].sock, &errorfds); if (mp->ldsc[j].sock > max_socket_fd) max_socket_fd = mp->ldsc[j].sock; ++socket_count; } #if !defined(_WIN32) && !defined(VMS) if (mp->ldsc[j].serport) { units[socket_count] = mp->ldsc[j].uptr; if (units[socket_count] == NULL) units[socket_count] = mp->uptr; sockets[socket_count] = mp->ldsc[j].serport; FD_SET (mp->ldsc[j].serport, &readfds); FD_SET (mp->ldsc[j].serport, &errorfds); if (mp->ldsc[j].serport > max_socket_fd) max_socket_fd = mp->ldsc[j].serport; ++socket_count; } #endif if (mp->ldsc[j].connecting) { units[socket_count] = mp->uptr; sockets[socket_count] = mp->ldsc[j].connecting; FD_SET (mp->ldsc[j].connecting, &readfds); FD_SET (mp->ldsc[j].connecting, &errorfds); if (mp->ldsc[j].connecting > max_socket_fd) max_socket_fd = mp->ldsc[j].connecting; ++socket_count; } if (mp->ldsc[j].master) { units[socket_count] = mp->uptr; sockets[socket_count] = mp->ldsc[j].master; FD_SET (mp->ldsc[j].master, &readfds); FD_SET (mp->ldsc[j].master, &errorfds); if (mp->ldsc[j].master > max_socket_fd) max_socket_fd = mp->ldsc[j].master; ++socket_count; } } } pthread_mutex_unlock (&sim_tmxr_poll_lock); if (timeout_usec > 1000000) timeout_usec = 1000000; timeout.tv_sec = timeout_usec/1000000; timeout.tv_usec = timeout_usec%1000000; select_errno = 0; if (socket_count == 0) { sim_os_ms_sleep (timeout_usec/1000); status = 0; } else status = select (1+(int)max_socket_fd, &readfds, NULL, &errorfds, &timeout); select_errno = errno; wait_count=0; pthread_mutex_lock (&sim_tmxr_poll_lock); switch (status) { case 0: /* timeout */ for (i=max_socket_fd=socket_count=0; i<tmxr_open_device_count; ++i) { mp = tmxr_open_devices[i]; if (mp->master) { if (!mp->uptr->a_polling_now) { mp->uptr->a_polling_now = TRUE; mp->uptr->a_poll_waiter_count = 0; d = find_dev_from_unit(mp->uptr); sim_debug (TMXR_DBG_ASY, d, "_tmxr_poll() - Activating %s to poll connect\n", sim_uname(mp->uptr)); pthread_mutex_unlock (&sim_tmxr_poll_lock); _sim_activate (mp->uptr, 0); pthread_mutex_lock (&sim_tmxr_poll_lock); } if (mp->txcount) { timeout_usec = 10000; /* Wait 10ms next time (this gets doubled below) */ mp->txcount = 0; } } for (j=0; j<mp->lines; ++j) { if ((mp->ldsc[j].conn) && (mp->ldsc[j].uptr)) { if (tmxr_tqln(&mp->ldsc[j]) || tmxr_rqln (&mp->ldsc[j])) { timeout_usec = 10000; /* Wait 10ms next time (this gets doubled below) */ /* More than one socket can be associated with the same unit. Make sure to only activate it one time */ if (!mp->ldsc[j].uptr->a_polling_now) { mp->ldsc[j].uptr->a_polling_now = TRUE; mp->ldsc[j].uptr->a_poll_waiter_count = 0; d = find_dev_from_unit(mp->ldsc[j].uptr); sim_debug (TMXR_DBG_ASY, d, "_tmxr_poll() - Line %d Activating %s to poll data: %d/%d\n", j, sim_uname(mp->ldsc[j].uptr), tmxr_tqln(&mp->ldsc[j]), tmxr_rqln (&mp->ldsc[j])); pthread_mutex_unlock (&sim_tmxr_poll_lock); _sim_activate (mp->ldsc[j].uptr, 0); pthread_mutex_lock (&sim_tmxr_poll_lock); } } } } } sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - Poll Timeout - %dms\n", timeout_usec/1000); timeout_usec *= 2; /* Double timeout time */ break; case SOCKET_ERROR: wait_count = 0; if (select_errno == EINTR) break; sim_printf ("select() returned -1, errno=%d - %s\r\n", select_errno, strerror(select_errno)); abort(); break; default: wait_count = 0; for (i=0; i<socket_count; ++i) { if (FD_ISSET(sockets[i], &readfds) || FD_ISSET(sockets[i], &errorfds)) { /* More than one socket can be associated with the same unit. Only activate one time */ for (j=0; j<wait_count; ++j) if (activated[j] == units[i]) break; if (j == wait_count) { activated[j] = units[i]; ++wait_count; if (!activated[j]->a_polling_now) { activated[j]->a_polling_now = TRUE; activated[j]->a_poll_waiter_count = 1; d = find_dev_from_unit(activated[j]); sim_debug (TMXR_DBG_ASY, d, "_tmxr_poll() - Activating for data %s\n", sim_uname(activated[j])); pthread_mutex_unlock (&sim_tmxr_poll_lock); _sim_activate (activated[j], 0); pthread_mutex_lock (&sim_tmxr_poll_lock); } else { d = find_dev_from_unit(activated[j]); sim_debug (TMXR_DBG_ASY, d, "_tmxr_poll() - Already Activated %s%d %d times\n", sim_uname(activated[j]), activated[j]->a_poll_waiter_count); ++activated[j]->a_poll_waiter_count; } } } } if (wait_count) timeout_usec = 10000; /* Wait 10ms next time */ break; } sim_tmxr_poll_count += wait_count; } pthread_mutex_unlock (&sim_tmxr_poll_lock); free(units); free(activated); free(sockets); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - exiting\n"); return NULL; } #if defined(_WIN32) static void * _tmxr_serial_poll(void *arg) { int timeout_usec; DEVICE *dptr = tmxr_open_devices[0]->dptr; UNIT **units = NULL; UNIT **activated = NULL; SERHANDLE *serports = NULL; int wait_count = 0; /* Boost Priority for this I/O thread vs the CPU instruction execution thread which, in general, won't be readily yielding the processor when this thread needs to run */ sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - starting\n"); units = (UNIT **)calloc(MAXIMUM_WAIT_OBJECTS, sizeof(*units)); activated = (UNIT **)calloc(MAXIMUM_WAIT_OBJECTS, sizeof(*activated)); serports = (SERHANDLE *)calloc(MAXIMUM_WAIT_OBJECTS, sizeof(*serports)); timeout_usec = 1000000; pthread_mutex_lock (&sim_tmxr_poll_lock); pthread_cond_signal (&sim_tmxr_serial_startup_cond); /* Signal we're ready to go */ while (sim_asynch_enabled) { int i, j; DWORD status; int serport_count; TMXR *mp; DEVICE *d; if ((tmxr_open_device_count == 0) || (!sim_is_running)) { for (j=0; j<wait_count; ++j) { d = find_dev_from_unit(activated[j]); sim_debug (TMXR_DBG_ASY, d, "_tmxr_serial_poll() - Removing interest in %s. Other interest: %d\n", sim_uname(activated[j]), activated[j]->a_poll_waiter_count); --activated[j]->a_poll_waiter_count; --sim_tmxr_poll_count; } break; } /* If we started something we should wait for, let it finish before polling again */ if (wait_count) { sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - waiting for %d units\n", wait_count); pthread_cond_wait (&sim_tmxr_poll_cond, &sim_tmxr_poll_lock); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - continuing with timeout of %dms\n", timeout_usec/1000); } for (i=serport_count=0; i<tmxr_open_device_count; ++i) { mp = tmxr_open_devices[i]; for (j=0; j<mp->lines; ++j) { if (mp->ldsc[j].serport) { units[serport_count] = mp->ldsc[j].uptr; if (units[serport_count] == NULL) units[serport_count] = mp->uptr; serports[serport_count] = mp->ldsc[j].serport; ++serport_count; } } } if (serport_count == 0) /* No open serial ports? */ break; /* We're done */ pthread_mutex_unlock (&sim_tmxr_poll_lock); if (timeout_usec > 1000000) timeout_usec = 1000000; status = WaitForMultipleObjects (serport_count, serports, FALSE, timeout_usec/1000); wait_count=0; pthread_mutex_lock (&sim_tmxr_poll_lock); switch (status) { case WAIT_FAILED: sim_printf ("WaitForMultipleObjects() Failed, LastError=%d\r\n", GetLastError()); abort(); break; case WAIT_TIMEOUT: sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - Poll Timeout - %dms\n", timeout_usec/1000); timeout_usec *= 2; /* Double timeout time */ break; default: i = status - WAIT_OBJECT_0; wait_count = 0; j = wait_count; activated[j] = units[i]; ++wait_count; if (!activated[j]->a_polling_now) { activated[j]->a_polling_now = TRUE; activated[j]->a_poll_waiter_count = 1; d = find_dev_from_unit(activated[j]); sim_debug (TMXR_DBG_ASY, d, "_tmxr_serial_poll() - Activating for data %s\n", sim_uname(activated[j])); pthread_mutex_unlock (&sim_tmxr_poll_lock); _sim_activate (activated[j], 0); pthread_mutex_lock (&sim_tmxr_poll_lock); } else { d = find_dev_from_unit(activated[j]); sim_debug (TMXR_DBG_ASY, d, "_tmxr_serial_poll() - Already Activated %s%d %d times\n", sim_uname(activated[j]), activated[j]->a_poll_waiter_count); ++activated[j]->a_poll_waiter_count; } if (wait_count) timeout_usec = 10000; /* Wait 10ms next time */ break; } sim_tmxr_poll_count += wait_count; } pthread_mutex_unlock (&sim_tmxr_poll_lock); free(units); free(activated); free(serports); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - exiting\n"); return NULL; } #endif /* _WIN32 */ #if defined(VMS) #include <descrip.h> #include <ttdef.h> #include <tt2def.h> #include <iodef.h> #include <ssdef.h> #include <starlet.h> #include <unistd.h> typedef struct { unsigned short status; unsigned short count; unsigned int dev_status; } IOSB; #define MAXIMUM_WAIT_OBJECTS 64 /* Number of possible concurrently opened serial ports */ pthread_cond_t sim_serial_line_startup_cond; static void * _tmxr_serial_line_poll(void *arg) { TMLN *lp = (TMLN *)arg; DEVICE *dptr = tmxr_open_devices[0]->dptr; UNIT *uptr = (lp->uptr ? lp->uptr : lp->mp->uptr); DEVICE *d = find_dev_from_unit(uptr); int wait_count = 0; /* Boost Priority for this I/O thread vs the CPU instruction execution thread which, in general, won't be readily yielding the processor when this thread needs to run */ sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_line_poll() - starting\n"); pthread_mutex_lock (&sim_tmxr_poll_lock); pthread_cond_signal (&sim_serial_line_startup_cond); /* Signal we're ready to go */ while (sim_asynch_enabled) { int i, j; int serport_count; TMXR *mp = lp->mp; unsigned int status, term[2]; unsigned char buf[4]; IOSB iosb; if ((tmxr_open_device_count == 0) || (!sim_is_running)) { if (wait_count) { sim_debug (TMXR_DBG_ASY, d, "_tmxr_serial_line_poll() - Removing interest in %s. Other interest: %d\n", sim_uname(uptr), uptr->a_poll_waiter_count); --uptr->a_poll_waiter_count; --sim_tmxr_poll_count; } break; } /* If we started something we should wait for, let it finish before polling again */ if (wait_count) { sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_line_poll() - waiting for %d units\n", wait_count); pthread_cond_wait (&sim_tmxr_poll_cond, &sim_tmxr_poll_lock); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_line_poll() - continuing with timeout of 1 sec\n"); } lp->a_active = TRUE; pthread_mutex_unlock (&sim_tmxr_poll_lock); term[0] = term[1] = 0; status = sys$qiow (0, lp->serport, IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED | IO$M_TRMNOECHO, &iosb, 0, 0, buf, 1, 1, term, 0, 0); if (status != SS$_NORMAL) { sim_printf ("_tmxr_serial_line_poll() - QIO Failed, Status=%d\r\n", status); abort(); } wait_count = 0; sys$synch (0, &iosb); pthread_mutex_lock (&sim_tmxr_poll_lock); lp->a_active = FALSE; if (iosb.count == 1) { lp->a_buffered_character = buf[0] | SCPE_KFLAG; wait_count = 1; if (!uptr->a_polling_now) { uptr->a_polling_now = TRUE; uptr->a_poll_waiter_count = 1; sim_debug (TMXR_DBG_ASY, d, "_tmxr_serial_line_poll() - Activating for data %s\n", sim_uname(uptr)); pthread_mutex_unlock (&sim_tmxr_poll_lock); _sim_activate (uptr, 0); pthread_mutex_lock (&sim_tmxr_poll_lock); } else { sim_debug (TMXR_DBG_ASY, d, "_tmxr_serial_line_poll() - Already Activated %s%d %d times\n", sim_uname(uptr), uptr->a_poll_waiter_count); ++uptr->a_poll_waiter_count; } } sim_tmxr_poll_count += wait_count; } pthread_mutex_unlock (&sim_tmxr_poll_lock); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_line_poll() - exiting\n"); return NULL; } static void * _tmxr_serial_poll(void *arg) { int timeout_usec; DEVICE *dptr = tmxr_open_devices[0]->dptr; TMLN **lines = NULL; pthread_t *threads = NULL; /* Boost Priority for this I/O thread vs the CPU instruction execution thread which, in general, won't be readily yielding the processor when this thread needs to run */ sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - starting\n"); lines = (TMLN **)calloc(MAXIMUM_WAIT_OBJECTS, sizeof(*lines)); threads = (pthread_t *)calloc(MAXIMUM_WAIT_OBJECTS, sizeof(*threads)); pthread_mutex_lock (&sim_tmxr_poll_lock); pthread_cond_signal (&sim_tmxr_serial_startup_cond); /* Signal we're ready to go */ pthread_cond_init (&sim_serial_line_startup_cond, NULL); while (sim_asynch_enabled) { pthread_attr_t attr; int i, j; int serport_count; TMXR *mp; DEVICE *d; if ((tmxr_open_device_count == 0) || (!sim_is_running)) break; pthread_attr_init (&attr); pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); for (i=serport_count=0; i<tmxr_open_device_count; ++i) { mp = tmxr_open_devices[i]; for (j=0; j<mp->lines; ++j) { if (mp->ldsc[j].serport) { lines[serport_count] = &mp->ldsc[j]; pthread_create (&threads[serport_count], &attr, _tmxr_serial_line_poll, (void *)&mp->ldsc[j]); pthread_cond_wait (&sim_serial_line_startup_cond, &sim_tmxr_poll_lock); /* Wait for thread to stabilize */ ++serport_count; } } } pthread_attr_destroy( &attr); if (serport_count == 0) /* No open serial ports? */ break; /* We're done */ pthread_mutex_unlock (&sim_tmxr_poll_lock); for (i=0; i<serport_count; i++) pthread_join (threads[i], NULL); pthread_mutex_lock (&sim_tmxr_poll_lock); } pthread_mutex_unlock (&sim_tmxr_poll_lock); pthread_cond_destroy (&sim_serial_line_startup_cond); free(lines); free(threads); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - exiting\n"); return NULL; } #endif /* VMS */ #endif /* defined(SIM_ASYNCH_MUX) */ t_stat tmxr_start_poll (void) { #if defined(SIM_ASYNCH_MUX) pthread_mutex_lock (&sim_tmxr_poll_lock); if ((tmxr_open_device_count > 0) && sim_asynch_enabled && sim_is_running && !sim_tmxr_poll_running) { pthread_attr_t attr; pthread_cond_init (&sim_tmxr_startup_cond, NULL); pthread_attr_init (&attr); pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); pthread_create (&sim_tmxr_poll_thread, &attr, _tmxr_poll, NULL); pthread_attr_destroy( &attr); pthread_cond_wait (&sim_tmxr_startup_cond, &sim_tmxr_poll_lock); /* Wait for thread to stabilize */ pthread_cond_destroy (&sim_tmxr_startup_cond); sim_tmxr_poll_running = TRUE; } pthread_mutex_unlock (&sim_tmxr_poll_lock); #endif return SCPE_OK; } t_stat tmxr_stop_poll (void) { #if defined(SIM_ASYNCH_MUX) pthread_mutex_lock (&sim_tmxr_poll_lock); if (sim_tmxr_poll_running) { pthread_cond_signal (&sim_tmxr_poll_cond); pthread_mutex_unlock (&sim_tmxr_poll_lock); pthread_join (sim_tmxr_poll_thread, NULL); sim_tmxr_poll_running = FALSE; /* Transitioning from asynch mode so kick all polling units onto the event queue */ if (tmxr_open_device_count) { int i, j; for (i=0; i<tmxr_open_device_count; ++i) { TMXR *mp = tmxr_open_devices[i]; if (mp->uptr) _sim_activate (mp->uptr, 0); for (j = 0; j < mp->lines; ++j) if (mp->ldsc[j].uptr) _sim_activate (mp->ldsc[j].uptr, 0); } } } else pthread_mutex_unlock (&sim_tmxr_poll_lock); #endif return SCPE_OK; } static void tmxr_add_to_open_list (TMXR* mux) { int i; t_bool found = FALSE; #if defined(SIM_ASYNCH_MUX) pthread_mutex_lock (&sim_tmxr_poll_lock); #endif for (i=0; i<tmxr_open_device_count; ++i) if (tmxr_open_devices[i] == mux) { found = TRUE; break; } if (!found) { tmxr_open_devices = (TMXR **)realloc(tmxr_open_devices, (tmxr_open_device_count+1)*sizeof(*tmxr_open_devices)); tmxr_open_devices[tmxr_open_device_count++] = mux; for (i=0; i<mux->lines; i++) if (0 == mux->ldsc[i].send.delay) mux->ldsc[i].send.delay = SEND_DEFAULT_DELAY; } #if defined(SIM_ASYNCH_MUX) pthread_mutex_unlock (&sim_tmxr_poll_lock); if ((tmxr_open_device_count == 1) && (sim_asynch_enabled)) tmxr_start_poll (); #endif } static void _tmxr_remove_from_open_list (TMXR* mux) { int i, j; #if defined(SIM_ASYNCH_MUX) tmxr_stop_poll (); pthread_mutex_lock (&sim_tmxr_poll_lock); #endif for (i=0; i<tmxr_open_device_count; ++i) if (tmxr_open_devices[i] == mux) { for (j=i+1; j<tmxr_open_device_count; ++j) tmxr_open_devices[j-1] = tmxr_open_devices[j]; --tmxr_open_device_count; break; } #if defined(SIM_ASYNCH_MUX) pthread_mutex_unlock (&sim_tmxr_poll_lock); #endif } static t_stat _tmxr_locate_line_send_expect (const char *cptr, SEND **snd, EXPECT **exp) { char gbuf[CBUFSIZE]; DEVICE *dptr; int i; t_stat r; if (snd) *snd = NULL; if (exp) *exp = NULL; cptr = get_glyph(cptr, gbuf, ':'); dptr = find_dev (gbuf); /* device match? */ if (!dptr) return SCPE_ARG; for (i=0; i<tmxr_open_device_count; ++i) if (tmxr_open_devices[i]->dptr == dptr) { int line = (int)get_uint (cptr, 10, tmxr_open_devices[i]->lines, &r); if (r != SCPE_OK) return r; if (snd) *snd = &tmxr_open_devices[i]->ldsc[line].send; if (exp) *exp = &tmxr_open_devices[i]->ldsc[line].expect; return SCPE_OK; } return SCPE_ARG; } t_stat tmxr_locate_line_send (const char *cptr, SEND **snd) { return _tmxr_locate_line_send_expect (cptr, snd, NULL); } t_stat tmxr_locate_line_expect (const char *cptr, EXPECT **exp) { return _tmxr_locate_line_send_expect (cptr, NULL, exp); } t_stat tmxr_change_async (void) { #if defined(SIM_ASYNCH_IO) if (sim_asynch_enabled) tmxr_start_poll (); else tmxr_stop_poll (); #endif return SCPE_OK; } /* Attach unit to master socket */ t_stat tmxr_attach_ex (TMXR *mp, UNIT *uptr, CONST char *cptr, t_bool async) { t_stat r; int32 i; r = tmxr_open_master (mp, cptr); /* open master socket */ if (r != SCPE_OK) /* error? */ return r; mp->uptr = uptr; /* save unit for polling */ uptr->filename = tmxr_mux_attach_string (uptr->filename, mp);/* save */ uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */ uptr->tmxr = (void *)mp; if ((mp->lines > 1) || ((mp->master == 0) && (mp->ldsc[0].connecting == 0) && (mp->ldsc[0].serport == 0))) uptr->dynflags = uptr->dynflags | UNIT_ATTMULT; /* allow multiple attach commands */ #if defined(SIM_ASYNCH_MUX) if (!async || (uptr->flags & TMUF_NOASYNCH)) /* if asynch disabled */ uptr->dynflags |= TMUF_NOASYNCH; /* tag as no asynch */ #else uptr->dynflags |= TMUF_NOASYNCH; /* tag as no asynch */ #endif if (mp->dptr == NULL) /* has device been set? */ mp->dptr = find_dev_from_unit (uptr); /* no, so set device now */ if (mp->dptr) { for (i=0; i<mp->lines; i++) { mp->ldsc[i].expect.dptr = mp->dptr; mp->ldsc[i].expect.dbit = TMXR_DBG_EXP; mp->ldsc[i].send.dptr = mp->dptr; mp->ldsc[i].send.dbit = TMXR_DBG_SEND; } } tmxr_add_to_open_list (mp); return SCPE_OK; } t_stat tmxr_startup (void) { return SCPE_OK; } t_stat tmxr_shutdown (void) { if (tmxr_open_device_count) return SCPE_IERR; return SCPE_OK; } t_stat tmxr_show_open_devices (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc) { int i, j; if (0 == tmxr_open_device_count) fprintf(st, "No Attached Multiplexer Devices\n"); else { for (i=0; i<tmxr_open_device_count; ++i) { TMXR *mp = tmxr_open_devices[i]; TMLN *lp; char *attach; fprintf(st, "Multiplexer device: %s", (mp->dptr ? sim_dname (mp->dptr) : "")); if (mp->lines > 1) { fprintf(st, ", "); tmxr_show_lines(st, NULL, 0, mp); } if (mp->packet) fprintf(st, ", Packet"); if (mp->datagram) fprintf(st, ", UDP"); if (mp->notelnet) fprintf(st, ", Telnet=disabled"); if (mp->modem_control) fprintf(st, ", ModemControl=enabled"); if (mp->buffered) fprintf(st, ", Buffered=%d", mp->buffered); attach = tmxr_mux_attach_string (NULL, mp); if (attach) fprintf(st, ",\n attached to %s, ", attach); free (attach); tmxr_show_summ(st, NULL, 0, mp); fprintf(st, ", sessions=%d", mp->sessions); if (mp->lines == 1) { if (mp->ldsc->rxbps) { fprintf(st, ", Speed=%d", mp->ldsc->rxbps); if (mp->ldsc->rxbpsfactor != TMXR_RX_BPS_UNIT_SCALE) fprintf(st, "*%.0f", mp->ldsc->rxbpsfactor/TMXR_RX_BPS_UNIT_SCALE); fprintf(st, " bps"); } } fprintf(st, "\n"); if (mp->ring_start_time) { fprintf (st, " incoming Connection from: %s ringing for %d milliseconds\n", mp->ring_ipad, sim_os_msec () - mp->ring_start_time); } for (j = 0; j < mp->lines; j++) { lp = mp->ldsc + j; if (mp->lines > 1) { if (lp->dptr && (mp->dptr != lp->dptr)) fprintf (st, "Device: %s ", sim_dname(lp->dptr)); fprintf (st, "Line: %d", j); if (mp->notelnet != lp->notelnet) fprintf (st, " - %stelnet", lp->notelnet ? "no" : ""); if (lp->uptr && (lp->uptr != lp->mp->uptr)) fprintf (st, " - Unit: %s", sim_uname (lp->uptr)); if (mp->modem_control != lp->modem_control) fprintf(st, ", ModemControl=%s", lp->modem_control ? "enabled" : "disabled"); if (lp->loopback) fprintf(st, ", Loopback"); if (lp->rxbps) { fprintf(st, ", Speed=%d", lp->rxbps); if (lp->rxbpsfactor != TMXR_RX_BPS_UNIT_SCALE) fprintf(st, "*%.0f", lp->rxbpsfactor/TMXR_RX_BPS_UNIT_SCALE); fprintf(st, " bps"); } fprintf (st, "\n"); } if ((!lp->sock) && (!lp->connecting) && (!lp->serport) && (!lp->master)) { if (lp->modem_control) tmxr_fconns (st, lp, -1); continue; } tmxr_fconns (st, lp, -1); tmxr_fstats (st, lp, -1); } } } return SCPE_OK; } /* Close a master listening socket. The listening socket associated with multiplexer descriptor "mp" is closed and deallocated. In addition, all current Telnet sessions are disconnected. Serial and outgoing sessions are also disconnected. */ t_stat tmxr_close_master (TMXR *mp) { int32 i; TMLN *lp; for (i = 0; i < mp->lines; i++) { /* loop thru conn */ lp = mp->ldsc + i; if (!lp->destination && lp->sock) { /* not serial and is connected? */ tmxr_report_disconnection (lp); /* report disconnection */ tmxr_reset_ln (lp); /* disconnect line */ } else { if (lp->sock) { tmxr_report_disconnection (lp); /* report disconnection */ tmxr_reset_ln (lp); } if (lp->serport) { sim_control_serial (lp->serport, 0, TMXR_MDM_DTR|TMXR_MDM_RTS, NULL);/* drop DTR and RTS */ tmxr_close_ln (lp); } free (lp->destination); lp->destination = NULL; if (lp->connecting) { lp->sock = lp->connecting; lp->connecting = 0; tmxr_reset_ln (lp); } lp->conn = FALSE; } if (lp->master) { sim_close_sock (lp->master); /* close master socket */ lp->master = 0; free (lp->port); lp->port = NULL; } lp->txbfd = 0; free (lp->txb); lp->txb = NULL; free (lp->rxb); lp->rxb = NULL; free (lp->rbr); lp->rbr = NULL; lp->modembits = 0; } if (mp->master) sim_close_sock (mp->master); /* close master socket */ mp->master = 0; free (mp->port); mp->port = NULL; if (mp->ring_sock != INVALID_SOCKET) { sim_close_sock (mp->ring_sock); mp->ring_sock = INVALID_SOCKET; free (mp->ring_ipad); mp->ring_ipad = NULL; mp->ring_start_time = 0; } _tmxr_remove_from_open_list (mp); return SCPE_OK; } /* Detach unit from master socket and close all active network connections and/or serial ports. Note that we return SCPE_OK, regardless of whether a listening socket was attached. */ t_stat tmxr_detach (TMXR *mp, UNIT *uptr) { int32 i; if (!(uptr->flags & UNIT_ATT)) /* attached? */ return SCPE_OK; tmxr_close_master (mp); /* close master socket */ free (uptr->filename); /* free setup string */ uptr->filename = NULL; uptr->tmxr = NULL; mp->last_poll_time = 0; for (i=0; i < mp->lines; i++) { UNIT *uptr = mp->ldsc[i].uptr ? mp->ldsc[i].uptr : mp->uptr; UNIT *o_uptr = mp->ldsc[i].o_uptr ? mp->ldsc[i].o_uptr : mp->uptr; uptr->dynflags &= ~UNIT_TM_POLL; /* no polling */ o_uptr->dynflags &= ~UNIT_TM_POLL; /* no polling */ } uptr->flags &= ~(UNIT_ATT); /* not attached */ uptr->dynflags &= ~(UNIT_TM_POLL|TMUF_NOASYNCH); /* no polling, not asynch disabled */ return SCPE_OK; } t_stat tmxr_activate (UNIT *uptr, int32 interval) { if (uptr->dynflags & UNIT_TMR_UNIT) return sim_timer_activate (uptr, interval); #if defined(SIM_ASYNCH_MUX) if ((!(uptr->dynflags & UNIT_TM_POLL)) || (!sim_asynch_enabled)) { return _sim_activate (uptr, interval); } return SCPE_OK; #else return _sim_activate (uptr, interval); #endif } t_stat tmxr_activate_after (UNIT *uptr, uint32 usecs_walltime) { #if defined(SIM_ASYNCH_MUX) if ((!(uptr->dynflags & UNIT_TM_POLL)) || (!sim_asynch_enabled)) { return _sim_activate_after (uptr, (double)usecs_walltime); } return SCPE_OK; #else return _sim_activate_after (uptr, (double)usecs_walltime); #endif } t_stat tmxr_activate_after_abs (UNIT *uptr, uint32 usecs_walltime) { #if defined(SIM_ASYNCH_MUX) if ((!(uptr->dynflags & UNIT_TM_POLL)) || (!sim_asynch_enabled)) { return _sim_activate_after_abs (uptr, (double)usecs_walltime); } return SCPE_OK; #else return _sim_activate_after_abs (uptr, (double)usecs_walltime); #endif } t_stat tmxr_clock_coschedule (UNIT *uptr, int32 interval) { int32 tmr = sim_rtcn_calibrated_tmr (); int32 ticks = (interval + (sim_rtcn_tick_size (tmr)/2))/sim_rtcn_tick_size (tmr);/* Convert to ticks */ return tmxr_clock_coschedule_tmr (uptr, tmr, ticks); } t_stat tmxr_clock_coschedule_abs (UNIT *uptr, int32 interval) { sim_cancel (uptr); return tmxr_clock_coschedule (uptr, interval); } #define MIN(a,b) (((a) < (b)) ? (a) : (b)) t_stat tmxr_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 ticks) { TMXR *mp = (TMXR *)uptr->tmxr; int32 interval = ticks * sim_rtcn_tick_size (tmr); #if defined(SIM_ASYNCH_MUX) if ((!(uptr->dynflags & UNIT_TM_POLL)) || (!sim_asynch_enabled)) { return sim_clock_coschedule (uptr, tmr, ticks); } return SCPE_OK; #else if (mp) { int32 i, soon = interval; double sim_gtime_now = sim_gtime (); for (i = 0; i < mp->lines; i++) { TMLN *lp = &mp->ldsc[i]; if (tmxr_rqln_bare (lp, FALSE)) { int32 due; if (lp->rxbps) if (lp->rxnexttime > sim_gtime_now) due = (int32)(lp->rxnexttime - sim_gtime_now); else due = sim_processing_event ? 1 : 0; /* avoid potential infinite loop if called from service routine */ else due = (int32)((uptr->wait * sim_timer_inst_per_sec ())/TMXR_RX_BPS_UNIT_SCALE); soon = MIN(soon, due); } } if (soon != interval) { sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %d instructions\n", sim_uname (uptr), soon); return _sim_activate (uptr, soon); } } sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "coscheduling %s after interval %d ticks\n", sim_uname (uptr), ticks); return sim_clock_coschedule_tmr (uptr, tmr, ticks); #endif } t_stat tmxr_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 ticks) { sim_cancel (uptr); return tmxr_clock_coschedule_tmr (uptr, tmr, ticks); } /* Generic Multiplexer attach help */ t_stat tmxr_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { TMXR *mux = (TMXR *)dptr->help_ctx; t_bool single_line = FALSE; /* default to Multi-Line help */ if (mux) single_line = (mux->lines == 1); if (!flag) fprintf (st, "%s Multiplexer Attach Help\n\n", dptr->name); if (single_line) { /* Single Line Multiplexer */ fprintf (st, "The %s multiplexer may be connected to terminal emulators supporting the\n", dptr->name); fprintf (st, "Telnet protocol via sockets, or to hardware terminals via host serial\n"); fprintf (st, "ports.\n\n"); if (mux->modem_control) { fprintf (st, "The %s device is a full modem control device and therefore is capable of\n", dptr->name); fprintf (st, "passing port configuration information and modem signals.\n"); } fprintf (st, "A Telnet listening port can be configured with:\n\n"); fprintf (st, " sim> ATTACH %s {interface:}port\n\n", dptr->name); fprintf (st, "Line buffering can be enabled for the %s device with:\n\n", dptr->name); fprintf (st, " sim> ATTACH %s Buffer{=bufsize}\n\n", dptr->name); fprintf (st, "Line buffering can be disabled for the %s device with:\n\n", dptr->name); fprintf (st, " sim> ATTACH %s NoBuffer\n\n", dptr->name); fprintf (st, "The default buffer size is 32k bytes, the max buffer size is 1024k bytes\n\n"); fprintf (st, "The outbound traffic the %s device can be logged to a file with:\n", dptr->name); fprintf (st, " sim> ATTACH %s Log=LogFileName\n\n", dptr->name); fprintf (st, "File logging can be disabled for the %s device with:\n\n", dptr->name); fprintf (st, " sim> ATTACH %s NoLog\n\n", dptr->name); fprintf (st, "The %s device may be connected to a serial port on the host system.\n", dptr->name); } else { fprintf (st, "%s multiplexer lines may be connected to terminal emulators supporting the\n", dptr->name); fprintf (st, "Telnet protocol via sockets, or to hardware terminals via host serial\n"); fprintf (st, "ports. Concurrent Telnet and serial connections may be mixed on a given\n"); fprintf (st, "multiplexer.\n\n"); if (mux && mux->modem_control) { fprintf (st, "The %s device is a full modem control device and therefore is capable of\n", dptr->name); fprintf (st, "passing port configuration information and modem signals on all lines.\n"); } fprintf (st, "Modem Control signalling behaviors can be enabled/disabled on a specific\n"); fprintf (st, "multiplexer line with:\n\n"); fprintf (st, " sim> ATTACH %s Line=n,Modem\n", dptr->name); fprintf (st, " sim> ATTACH %s Line=n,NoModem\n\n", dptr->name); fprintf (st, "A Telnet listening port can be configured with:\n\n"); fprintf (st, " sim> ATTACH %s {interface:}port\n\n", dptr->name); if (mux) fprintf (st, "Line buffering for all %d lines on the %s device can be configured with:\n\n", mux->lines, dptr->name); else fprintf (st, "Line buffering for all lines on the %s device can be configured with:\n\n", dptr->name); fprintf (st, " sim> ATTACH %s Buffer{=bufsize}\n\n", dptr->name); if (mux) fprintf (st, "Line buffering for all %d lines on the %s device can be disabled with:\n\n", mux->lines, dptr->name); else fprintf (st, "Line buffering for all lines on the %s device can be disabled with:\n\n", dptr->name); fprintf (st, " sim> ATTACH %s NoBuffer\n\n", dptr->name); fprintf (st, "The default buffer size is 32k bytes, the max buffer size is 1024k bytes\n\n"); fprintf (st, "The outbound traffic for the lines of the %s device can be logged to files\n", dptr->name); fprintf (st, "with:\n\n"); fprintf (st, " sim> ATTACH %s Log=LogFileName\n\n", dptr->name); fprintf (st, "The log file name for each line uses the above LogFileName as a template\n"); fprintf (st, "for the actual file name which will be LogFileName_n where n is the line\n"); fprintf (st, "number.\n\n"); fprintf (st, "Multiplexer lines may be connected to serial ports on the host system.\n"); } fprintf (st, "Serial ports may be specified as an operating system specific device names\n"); fprintf (st, "or using simh generic serial names. simh generic names are of the form\n"); fprintf (st, "serN, where N is from 0 thru one less than the maximum number of serial\n"); fprintf (st, "ports on the local system. The mapping of simh generic port names to OS \n"); fprintf (st, "specific names can be displayed using the following command:\n\n"); fprintf (st, " sim> SHOW SERIAL\n"); fprintf (st, " Serial devices:\n"); fprintf (st, " ser0 COM1 (\\Device\\Serial0)\n"); fprintf (st, " ser1 COM3 (Winachcf0)\n\n"); if (single_line) { /* Single Line Multiplexer */ fprintf (st, " sim> ATTACH %s Connect=ser0\n\n", dptr->name); fprintf (st, "or equivalently:\n\n"); fprintf (st, " sim> ATTACH %s Connect=COM1\n\n", dptr->name); } else { fprintf (st, " sim> ATTACH %s Line=n,Connect=ser0\n\n", dptr->name); fprintf (st, "or equivalently:\n\n"); fprintf (st, " sim> ATTACH %s Line=n,Connect=COM1\n\n", dptr->name); if (mux) fprintf (st, "Valid line numbers are from 0 thru %d\n\n", mux->lines-1); } if (single_line) { /* Single Line Multiplexer */ fprintf (st, "The input data rate for the %s device can be controlled by\n", dptr->name); fprintf (st, "specifying SPEED=nnn{*fac} on the the ATTACH command.\n"); } else { fprintf (st, "The input data rate for all lines or a particular line of a the %s\n", dptr->name); fprintf (st, "device can be controlled by specifying SPEED=nnn{*fac} on the ATTACH command.\n"); } fprintf (st, "SPEED values can be any one of:\n\n"); fprintf (st, " 0 50 75 110 134 150 300 600 1200 1800 2000 2400\n"); fprintf (st, " 3600 4800 7200 9600 19200 38400 57600 76800 115200\n\n"); fprintf (st, "A SPEED value of 0 causes input data to be delivered to the simulated\n"); fprintf (st, "port as fast as it arrives.\n\n"); fprintf (st, "If a simulated multiplexor devices can programmatically set a serial\n"); fprintf (st, "port line speed, the programmatically specified speed will take precidence\n"); fprintf (st, "over any input speed specified on an attach command.\n"); fprintf (st, "Some simulated systems run very much faster than the original system\n"); fprintf (st, "which is being simulated. To accommodate this, the speed specified may\n"); fprintf (st, "include a factor which will increase the input data delivery rate by\n"); fprintf (st, "the specified factor. A factor is specified with a speed value of the\n"); fprintf (st, "form \"speed*factor\". Factor values can range from 1 thru 32.\n"); fprintf (st, "Example:\n\n"); fprintf (st, " sim> ATTACH %s 1234,SPEED=2400\n", dptr->name); fprintf (st, " sim> ATTACH %s 1234,SPEED=9600*8\n", dptr->name); if (!single_line) fprintf (st, " sim> ATTACH %s Line=2,SPEED=2400\n", dptr->name); fprintf (st, "\n"); fprintf (st, "The SPEED parameter only influences the rate at which data is deliverd\n"); fprintf (st, "into the simulated multiplexor port. Output data rates are unaffected\n"); fprintf (st, "If an attach command specifies a speed multiply factor, that value will\n"); fprintf (st, "persist independent of any programatic action by the simulated system to\n"); fprintf (st, "change the port speed.\n\n"); fprintf (st, "An optional serial port configuration string may be present after the port\n"); fprintf (st, "name. If present, it must be separated from the port name with a semicolon\n"); fprintf (st, "and has this form:\n\n"); fprintf (st, " <rate>-<charsize><parity><stopbits>\n\n"); fprintf (st, "where:\n"); fprintf (st, " rate = communication rate in bits per second\n"); fprintf (st, " charsize = character size in bits (5-8, including optional parity)\n"); fprintf (st, " parity = parity designator (N/E/O/M/S for no/even/odd/mark/space parity)\n"); fprintf (st, " stopbits = number of stop bits (1, 1.5, or 2)\n\n"); fprintf (st, "As an example:\n\n"); fprintf (st, " 9600-8n1\n\n"); fprintf (st, "The supported rates, sizes, and parity options are host-specific. If\n"); fprintf (st, "a configuration string is not supplied, then the default of 9600-8N1\n"); fprintf (st, "is used.\n"); fprintf (st, "Note: The serial port configuration option is only available on multiplexer\n"); fprintf (st, " lines which are not operating with full modem control behaviors enabled.\n"); fprintf (st, " Lines with full modem control behaviors enabled have all of their\n"); fprintf (st, " configuration managed by the Operating System running within the\n"); fprintf (st, " simulator.\n\n"); fprintf (st, "An attachment to a serial port with the '-V' switch will cause a\n"); fprintf (st, "connection message to be output to the connected serial port.\n"); fprintf (st, "This will help to confirm the correct port has been connected and\n"); fprintf (st, "that the port settings are reasonable for the connected device.\n"); fprintf (st, "This would be done as:\n\n"); if (single_line) /* Single Line Multiplexer */ fprintf (st, " sim> ATTACH -V %s Connect=SerN\n", dptr->name); else { fprintf (st, " sim> ATTACH -V %s Line=n,Connect=SerN\n\n", dptr->name); fprintf (st, "Line specific tcp listening ports are supported. These are configured\n"); fprintf (st, "using commands of the form:\n\n"); fprintf (st, " sim> ATTACH %s Line=n,{interface:}port{;notelnet}\n\n", dptr->name); } fprintf (st, "Direct computer to computer connections (Virutal Null Modem cables) may\n"); fprintf (st, "be established using the telnet protocol or via raw tcp sockets.\n\n"); fprintf (st, " sim> ATTACH %s Line=n,Connect=host:port{;notelnet}\n\n", dptr->name); fprintf (st, "Computer to computer virtual connections can be one way (as illustrated\n"); fprintf (st, "above) or symmetric. A symmetric connection is configured by combining\n"); if (single_line) { /* Single Line Multiplexer */ fprintf (st, "a one way connection with a tcp listening port on the same line:\n\n"); fprintf (st, " sim> ATTACH %s listenport,Connect=host:port\n\n", dptr->name); } else { fprintf (st, "a one way connection with a tcp listening port on the same line:\n\n"); fprintf (st, " sim> ATTACH %s Line=n,listenport,Connect=host:port\n\n", dptr->name); } fprintf (st, "When symmetric virtual connections are configured, incoming connections\n"); fprintf (st, "on the specified listening port are checked to assure that they actually\n"); fprintf (st, "come from the specified connection destination host system.\n\n"); if (single_line) { /* Single Line Multiplexer */ fprintf (st, "The %s device can be attached in LOOPBACK mode:\n\n", dptr->name); fprintf (st, " sim> ATTACH %s Loopback\n\n", dptr->name); } else { fprintf (st, "A line on the %s device can be attached in LOOPBACK mode:\n\n", dptr->name); fprintf (st, " sim> ATTACH %s Line=n,Loopback\n\n", dptr->name); } fprintf (st, "When operating in LOOPBACK mode, all outgoing data arrives as input and\n"); fprintf (st, "outgoing modem signals (if enabled) (DTR and RTS) are reflected in the\n"); fprintf (st, "incoming modem signals (DTR->(DCD and DSR), RTS->CTS)\n\n"); if (single_line) /* Single Line Multiplexer */ fprintf (st, "The connection configured for the %s device is unconfigured by:\n\n", dptr->name); else fprintf (st, "All connections configured for the %s device are unconfigured by:\n\n", dptr->name); fprintf (st, " sim> DETACH %s\n\n", dptr->name); if (dptr->modifiers) { MTAB *mptr; for (mptr = dptr->modifiers; mptr->mask != 0; mptr++) if (mptr->valid == &tmxr_dscln) { fprintf (st, "A specific line on the %s device can be disconnected with:\n\n", dptr->name); fprintf (st, " sim> SET %s %s=n\n\n", dptr->name, mptr->mstring); fprintf (st, "This will cause a telnet connection to be closed, but a serial port will\n"); fprintf (st, "normally have DTR dropped for 500ms and raised again (thus hanging up a\n"); fprintf (st, "modem on that serial port).\n\n"); fprintf (st, "A line which is connected to a serial port can be manually closed by\n"); fprintf (st, "adding the -C switch to a %s command.\n\n", mptr->mstring); fprintf (st, " sim> SET -C %s %s=n\n\n", dptr->name, mptr->mstring); } } return SCPE_OK; } /* Stub examine and deposit */ t_stat tmxr_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { return SCPE_NOFNC; } t_stat tmxr_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { return SCPE_NOFNC; } /* Write a message directly to a socket */ void tmxr_msg (SOCKET sock, const char *msg) { if ((sock) && (sock != INVALID_SOCKET)) sim_write_sock (sock, msg, (int32)strlen (msg)); return; } /* Write a message to a line */ void tmxr_linemsg (TMLN *lp, const char *msg) { while (*msg) { while (SCPE_STALL == tmxr_putc_ln (lp, (int32)(*msg))) if (lp->txbsz == tmxr_send_buffered_data (lp)) sim_os_ms_sleep (10); ++msg; } return; } /* Write a formatted message to a line */ void tmxr_linemsgf (TMLN *lp, const char *fmt, ...) { va_list arglist; va_start (arglist, fmt); tmxr_linemsgvf (lp, fmt, arglist); va_end (arglist); } void tmxr_linemsgvf (TMLN *lp, const char *fmt, va_list arglist) { char stackbuf[STACKBUFSIZE]; int32 bufsize = sizeof(stackbuf); char *buf = stackbuf; int32 i, len; buf[bufsize-1] = '\0'; while (1) { /* format passed string, args */ #if defined(NO_vsnprintf) len = vsprintf (buf, fmt, arglist); #else /* !defined(NO_vsnprintf) */ len = vsnprintf (buf, bufsize-1, fmt, arglist); #endif /* NO_vsnprintf */ /* If the formatted result didn't fit into the buffer, then grow the buffer and try again */ if ((len < 0) || (len >= bufsize-1)) { if (buf != stackbuf) free (buf); bufsize = bufsize * 2; if (bufsize < len + 2) bufsize = len + 2; buf = (char *) malloc (bufsize); if (buf == NULL) /* out of memory */ return; buf[bufsize-1] = '\0'; continue; } break; } /* Output the formatted data expanding newlines where they exist */ for (i = 0; i < len; ++i) { if (('\n' == buf[i]) && ((i == 0) || ('\r' != buf[i-1]))) { while (SCPE_STALL == tmxr_putc_ln (lp, '\r')) if (lp->txbsz == tmxr_send_buffered_data (lp)) sim_os_ms_sleep (10); } while (SCPE_STALL == tmxr_putc_ln (lp, buf[i])) if (lp->txbsz == tmxr_send_buffered_data (lp)) sim_os_ms_sleep (10); } if (buf != stackbuf) free (buf); return; } /* Print connections - used only in named SHOW command */ void tmxr_fconns (FILE *st, const TMLN *lp, int32 ln) { int32 hr, mn, sc; uint32 ctime; if (ln >= 0) fprintf (st, "line %d: ", ln); if ((lp->sock) || (lp->connecting)) { /* tcp connection? */ if (lp->destination) /* remote connection? */ if (lp->datagram) fprintf (st, "Datagram Connection from %s to remote port %s\n", lp->port, lp->destination);/* print port name */ else fprintf (st, "Connection to remote port %s\n", lp->destination);/* print port name */ else /* incoming connection */ fprintf (st, "Connection from IP address %s\n", lp->ipad); } else if (lp->destination) /* remote connection? */ fprintf (st, "Connecting to remote port %s\n", lp->destination);/* print port name */ if (lp->sock) { char *sockname, *peername; sim_getnames_sock (lp->sock, &sockname, &peername); fprintf (st, "Connection %s->%s\n", sockname, peername); free (sockname); free (peername); } if ((lp->port) && (!lp->datagram)) fprintf (st, "Listening on port %s\n", lp->port); /* print port name */ if (lp->serport) /* serial connection? */ fprintf (st, "Connected to serial port %s\n", lp->destination); /* print port name */ if (lp->cnms) { ctime = (sim_os_msec () - lp->cnms) / 1000; hr = ctime / 3600; mn = (ctime / 60) % 60; sc = ctime % 60; if (ctime) fprintf (st, " %s %02d:%02d:%02d\n", lp->connecting ? "Connecting for" : "Connected", hr, mn, sc); } else fprintf (st, " Line disconnected\n"); if (lp->modem_control) { fprintf (st, " Modem Bits: %s%s%s%s%s%s\n", (lp->modembits & TMXR_MDM_DTR) ? "DTR " : "", (lp->modembits & TMXR_MDM_RTS) ? "RTS " : "", (lp->modembits & TMXR_MDM_DCD) ? "DCD " : "", (lp->modembits & TMXR_MDM_RNG) ? "RNG " : "", (lp->modembits & TMXR_MDM_CTS) ? "CTS " : "", (lp->modembits & TMXR_MDM_DSR) ? "DSR " : ""); } if ((lp->serport == 0) && (lp->sock) && (!lp->datagram)) fprintf (st, " %s\n", (lp->notelnet) ? "Telnet disabled (RAW data)" : "Telnet protocol"); if (lp->send.buffer) sim_show_send_input (st, &lp->send); if (lp->expect.buf) sim_exp_showall (st, &lp->expect); if (lp->txlog) fprintf (st, " Logging to %s\n", lp->txlogname); return; } /* Print statistics - used only in named SHOW command */ void tmxr_fstats (FILE *st, const TMLN *lp, int32 ln) { static const char *enab = "on"; static const char *dsab = "off"; if (ln >= 0) fprintf (st, "Line %d:", ln); if ((!lp->sock) && (!lp->connecting) && (!lp->serport)) fprintf (st, " not connected\n"); else { if (ln >= 0) fprintf (st, "\n"); fprintf (st, " input (%s)", (lp->rcve? enab: dsab)); if (lp->rxcnt) fprintf (st, " queued/total = %d/%d", tmxr_rqln (lp), lp->rxcnt); if (lp->rxpcnt) fprintf (st, " packets = %d", lp->rxpcnt); fprintf (st, "\n output (%s)", (lp->xmte? enab: dsab)); if (lp->txcnt || lp->txbpi) fprintf (st, " queued/total = %d/%d", tmxr_tqln (lp), lp->txcnt); if (lp->txpcnt || tmxr_tpqln (lp)) fprintf (st, " packet data queued/packets sent = %d/%d", tmxr_tpqln (lp), lp->txpcnt); fprintf (st, "\n"); } if (lp->txbfd) fprintf (st, " output buffer size = %d\n", lp->txbsz); if (lp->txcnt || lp->txbpi) fprintf (st, " bytes in buffer = %d\n", ((lp->txcnt > 0) && (lp->txcnt > lp->txbsz)) ? lp->txbsz : lp->txbpi); if (lp->txdrp) fprintf (st, " dropped = %d\n", lp->txdrp); return; } /* Disconnect a line. Disconnect a line of the multiplexer associated with descriptor "desc" from a tcp session or a serial port. Two calling sequences are supported: 1. If "val" is zero, then "uptr" is implicitly associated with the line number corresponding to the position of the unit in the zero-based array of units belonging to the associated device, and "cptr" is ignored. For example, if "uptr" points to unit 3 in a given device, then line 3 will be disconnected. 2. If "val" is non-zero, then "cptr" points to a string that is parsed for an explicit line number, and "uptr" is ignored. For example, if "cptr" points to the string "3", then line 3 will be disconnected. If the line was connected to a tcp session, the socket associated with the line will be closed. If the line was connected to a serial port, the port will NOT be closed, but DTR will be dropped. After a 500ms delay DTR will be raised again. If the sim_switches -C flag is set, then a serial port connection will be closed. Implementation notes: 1. This function is usually called as an MTAB processing routine. */ t_stat tmxr_dscln (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { TMXR *mp = (TMXR *) desc; TMLN *lp; t_stat status; if (val) /* explicit line? */ uptr = NULL; /* indicate to get routine */ tmxr_debug_trace (mp, "tmxr_dscln()"); lp = tmxr_get_ldsc (uptr, cptr, mp, &status); /* get referenced line */ if (lp == NULL) /* bad line number? */ return status; /* report it */ if ((lp->sock) || (lp->serport)) { /* connection active? */ if (!lp->notelnet) tmxr_linemsg (lp, "\r\nOperator disconnected line\r\n\n");/* report closure */ tmxr_reset_ln_ex (lp, (sim_switches & SWMASK ('C'))); /* drop the line */ } return SCPE_OK; } /* Enable logging for line */ t_stat tmxr_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { TMXR *mp = (TMXR *) desc; TMLN *lp; if (cptr == NULL) /* no file name? */ return SCPE_2FARG; lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */ if (lp == NULL) return SCPE_IERR; if (lp->txlog) /* close existing log */ tmxr_set_nolog (NULL, val, NULL, desc); lp->txlogname = (char *) calloc (CBUFSIZE, sizeof (char)); /* alloc namebuf */ if (lp->txlogname == NULL) /* can't? */ return SCPE_MEM; strncpy (lp->txlogname, cptr, CBUFSIZE); /* save file name */ sim_open_logfile (cptr, TRUE, &lp->txlog, &lp->txlogref);/* open log */ if (lp->txlog == NULL) { /* error? */ free (lp->txlogname); /* free buffer */ return SCPE_OPENERR; } if (mp->uptr) /* attached?, then update attach string */ lp->mp->uptr->filename = tmxr_mux_attach_string (lp->mp->uptr->filename, lp->mp); return SCPE_OK; } /* Disable logging for line */ t_stat tmxr_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { TMXR *mp = (TMXR *) desc; TMLN *lp; if (cptr) /* no arguments */ return SCPE_2MARG; lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */ if (lp == NULL) return SCPE_IERR; if (lp->txlog) { /* logging? */ sim_close_logfile (&lp->txlogref); /* close log */ free (lp->txlogname); /* free namebuf */ lp->txlog = NULL; lp->txlogname = NULL; } if (mp->uptr) lp->mp->uptr->filename = tmxr_mux_attach_string (lp->mp->uptr->filename, lp->mp); return SCPE_OK; } /* Show logging status for line */ t_stat tmxr_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { const TMXR *mp = (const TMXR *) desc; TMLN *lp; lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */ if (lp == NULL) return SCPE_IERR; if (lp->txlog) fprintf (st, "logging to %s", lp->txlogname); else fprintf (st, "no logging"); return SCPE_OK; } /* Set the line connection order. Example command for eight-line multiplexer: SET <dev> LINEORDER=1;5;2-4;7 Resulting connection order: 1,5,2,3,4,7,0,6. Parameters: - uptr = (not used) - val = (not used) - cptr = pointer to first character of range specification - desc = pointer to multiplexer's TMXR structure On entry, cptr points to the value portion of the command string, which may be either a semicolon-separated list of line ranges or the keyword ALL. If a line connection order array is not defined in the multiplexer descriptor, the command is rejected. If the specified range encompasses all of the lines, the first value of the connection order array is set to -1 to indicate sequential connection order. Otherwise, the line values in the array are set to the order specified by the command string. All values are populated, first with those explicitly specified in the command string, and then in ascending sequence with those not specified. If an error occurs, the original line order is not disturbed. */ t_stat tmxr_set_lnorder (UNIT *uptr, int32 val, CONST char *carg, void *desc) { TMXR *mp = (TMXR *) desc; char *tbuf; char *tptr; CONST char *cptr; t_addr low, high, max = (t_addr) mp->lines - 1; int32 *list; t_bool *set; uint32 line, idx = 0; t_stat result = SCPE_OK; if (mp->lnorder == NULL) /* line connection order undefined? */ return SCPE_NXPAR; /* "Non-existent parameter" error */ else if ((carg == NULL) || (*carg == '\0')) /* line range not supplied? */ return SCPE_MISVAL; /* "Missing value" error */ list = (int32 *) calloc (mp->lines, sizeof (int32)); /* allocate new line order array */ if (list == NULL) /* allocation failed? */ return SCPE_MEM; /* report it */ set = (t_bool *) calloc (mp->lines, sizeof (t_bool)); /* allocate line set tracking array */ if (set == NULL) { /* allocation failed? */ free (list); /* free successful list allocation */ return SCPE_MEM; /* report it */ } tbuf = (char *) calloc (strlen(carg)+2, sizeof(*carg)); strcpy (tbuf, carg); tptr = tbuf + strlen (tbuf); /* append a semicolon */ *tptr++ = ';'; /* to the command string */ *tptr = '\0'; /* to make parsing easier for get_range */ cptr = tbuf; while (*cptr) { /* parse command string */ cptr = get_range (NULL, cptr, &low, &high, 10, max, ';');/* get a line range */ if (cptr == NULL) { /* parsing error? */ result = SCPE_ARG; /* "Invalid argument" error */ break; } else if ((low > max) || (high > max)) { /* line out of range? */ result = SCPE_SUB; /* "Subscript out of range" error */ break; } else if ((low == 0) && (high == max)) { /* entire line range specified? */ list [0] = -1; /* set sequential order flag */ idx = (uint32) max + 1; /* indicate no fill-in needed */ break; } else for (line = (uint32) low; line <= (uint32) high; line++) /* see if previously specified */ if (set [line] == FALSE) { /* not already specified? */ set [line] = TRUE; /* now it is */ list [idx] = line; /* add line to connection order */ idx = idx + 1; /* bump "specified" count */ } } if (result == SCPE_OK) { /* assignment successful? */ if (idx <= max) /* any lines not specified? */ for (line = 0; line <= max; line++) /* fill them in sequentially */ if (set [line] == FALSE) { /* specified? */ list [idx] = line; /* no, so add it */ idx = idx + 1; } memcpy (mp->lnorder, list, mp->lines * sizeof (int32)); /* copy working array to connection array */ } free (list); /* free list allocation */ free (set); /* free set allocation */ free (tbuf); /* free arg copy with ; */ return result; } /* Show line connection order. Parameters: - st = stream on which output is to be written - uptr = (not used) - val = (not used) - desc = pointer to multiplexer's TMXR structure If a connection order array is not defined in the multiplexer descriptor, the command is rejected. If the first value of the connection order array is set to -1, then the connection order is sequential. Otherwise, the line values in the array are printed as a semicolon-separated list. Ranges are printed where possible to shorten the output. */ t_stat tmxr_show_lnorder (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { int32 i, j, low, last; const TMXR *mp = (const TMXR *) desc; int32 *iptr = mp->lnorder; t_bool first = TRUE; if (iptr == NULL) /* connection order undefined? */ return SCPE_NXPAR; /* "Non-existent parameter" error */ if (*iptr < 0) /* sequential order indicated? */ fprintf (st, "Order=0-%d\n", mp->lines - 1); /* print full line range */ else { low = last = *iptr++; /* set first line value */ for (j = 1; j <= mp->lines; j++) { /* print remaining lines in order list */ if (j < mp->lines) /* more lines to process? */ i = *iptr++; /* get next line in list */ else /* final iteration */ i = -1; /* get "tie-off" value */ if (i != last + 1) { /* end of a range? */ if (first) { /* first line to print? */ fputs ("Order=", st); /* print header */ first = FALSE; } else /* not first line printed */ fputc (';', st); /* print separator */ if (low == last) /* range null? */ fprintf (st, "%d", last); /* print single line value */ else /* range established */ fprintf (st, "%d-%d", low, last); /* print start and end line */ low = i; /* start new range */ } last = i; /* note value for range check */ } } if (first == FALSE) /* sanity check for lines == 0 */ fputc ('\n', st); return SCPE_OK; } /* Show summary processor */ t_stat tmxr_show_summ (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { const TMXR *mp = (const TMXR *) desc; int32 i, t; if (mp == NULL) return SCPE_IERR; for (i = t = 0; i < mp->lines; i++) if ((mp->ldsc[i].sock != 0) || (mp->ldsc[i].serport != 0)) t = t + 1; if (mp->lines > 1) fprintf (st, "%d current connection%s", t, (t != 1) ? "s" : ""); else fprintf (st, "%s", (t == 1) ? "connected" : "disconnected"); return SCPE_OK; } /* Show conn/stat processor */ t_stat tmxr_show_cstat (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { const TMXR *mp = (const TMXR *) desc; int32 i, any; if (mp == NULL) return SCPE_IERR; for (i = any = 0; i < mp->lines; i++) { if ((mp->ldsc[i].sock != 0) || (mp->ldsc[i].serport != 0) || mp->ldsc[i].modem_control) { if ((mp->ldsc[i].sock != 0) || (mp->ldsc[i].serport != 0)) any++; if (val) tmxr_fconns (st, &mp->ldsc[i], i); else if ((mp->ldsc[i].sock != 0) || (mp->ldsc[i].serport != 0)) tmxr_fstats (st, &mp->ldsc[i], i); } } if (any == 0) fprintf (st, (mp->lines == 1? "disconnected\n": "all disconnected\n")); return SCPE_OK; } /* Show number of lines */ t_stat tmxr_show_lines (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { const TMXR *mp = (const TMXR *) desc; if (mp == NULL) return SCPE_IERR; fprintf (st, "lines=%d", mp->lines); return SCPE_OK; } static struct { u_char value; const char *name; } tn_chars[] = { {TN_IAC, "TN_IAC"}, /* protocol delim */ {TN_DONT, "TN_DONT"}, /* dont */ {TN_DO, "TN_DO"}, /* do */ {TN_WONT, "TN_WONT"}, /* wont */ {TN_WILL, "TN_WILL"}, /* will */ {TN_SB, "TN_SB"}, /* sub-option negotiation */ {TN_GA, "TN_SG"}, /* go ahead */ {TN_EL, "TN_EL"}, /* erase line */ {TN_EC, "TN_EC"}, /* erase character */ {TN_AYT, "TN_AYT"}, /* are you there */ {TN_AO, "TN_AO"}, /* abort output */ {TN_IP, "TN_IP"}, /* interrupt process */ {TN_BRK, "TN_BRK"}, /* break */ {TN_DATAMK, "TN_DATAMK"}, /* data mark */ {TN_NOP, "TN_NOP"}, /* no operation */ {TN_SE, "TN_SE"}, /* end sub-option negot */ /* Options */ {TN_BIN, "TN_BIN"}, /* bin */ {TN_ECHO, "TN_ECHO"}, /* echo */ {TN_SGA, "TN_SGA"}, /* sga */ {TN_STATUS, "TN_STATUS"}, /* option status query */ {TN_TIMING, "TN_TIMING"}, /* Timing Mark */ {TN_NAOCRD, "TN_NAOCRD"}, /* Output Carriage-Return Disposition */ {TN_NAOHTS, "TN_NAOHTS"}, /* Output Horizontal Tab Stops */ {TN_NAOHTD, "TN_NAOHTD"}, /* Output Horizontal Tab Stop Disposition */ {TN_NAOFFD, "TN_NAOFFD"}, /* Output Forfeed Disposition */ {TN_NAOVTS, "TN_NAOVTS"}, /* Output Vertical Tab Stop */ {TN_NAOVTD, "TN_NAOVTD"}, /* Output Vertical Tab Stop Disposition */ {TN_NAOLFD, "TN_NAOLFD"}, /* Output Linefeed Disposition */ {TN_EXTEND, "TN_EXTEND"}, /* Extended Ascii */ {TN_LOGOUT, "TN_LOGOUT"}, /* Logout */ {TN_BM, "TN_BM"}, /* Byte Macro */ {TN_DET, "TN_DET"}, /* Data Entry Terminal */ {TN_SENDLO, "TN_SENDLO"}, /* Send Location */ {TN_TERMTY, "TN_TERMTY"}, /* Terminal Type */ {TN_ENDREC, "TN_ENDREC"}, /* Terminal Type */ {TN_TUID, "TN_TUID"}, /* TACACS User Identification */ {TN_OUTMRK, "TN_OUTMRK"}, /* Output Marking */ {TN_TTYLOC, "TN_TTYLOC"}, /* Terminal Location Number */ {TN_3270, "TN_3270"}, /* 3270 Regime */ {TN_X3PAD, "TN_X3PAD"}, /* X.3 PAD */ {TN_NAWS, "TN_NAWS"}, /* Negotiate About Window Size */ {TN_TERMSP, "TN_TERMSP"}, /* Terminal Speed */ {TN_TOGFLO, "TN_TOGFLO"}, /* Remote Flow Control */ {TN_LINE, "TN_LINE"}, /* line mode */ {TN_XDISPL, "TN_XDISPL"}, /* X Display Location */ {TN_ENVIRO, "TN_ENVIRO"}, /* Environment */ {TN_AUTH, "TN_AUTH"}, /* Authentication */ {TN_ENCRYP, "TN_ENCRYP"}, /* Data Encryption */ {TN_NEWENV, "TN_NEWENV"}, /* New Environment */ {TN_TN3270, "TN_TN3270"}, /* TN3270 Enhancements */ {TN_CHARST, "TN_CHARST"}, /* CHARSET */ {TN_COMPRT, "TN_COMPRT"}, /* Com Port Control */ {TN_KERMIT, "TN_KERMIT"}, /* KERMIT */ {0, NULL}}; static char *tmxr_debug_buf = NULL; static size_t tmxr_debug_buf_used = 0; static size_t tmxr_debug_buf_size = 0; static void tmxr_buf_debug_char (char value) { if (tmxr_debug_buf_used+2 > tmxr_debug_buf_size) { tmxr_debug_buf_size += 1024; tmxr_debug_buf = (char *)realloc (tmxr_debug_buf, tmxr_debug_buf_size); } tmxr_debug_buf[tmxr_debug_buf_used++] = value; tmxr_debug_buf[tmxr_debug_buf_used] = '\0'; } static void tmxr_buf_debug_string (const char *string) { while (*string) tmxr_buf_debug_char (*string++); } static void tmxr_buf_debug_telnet_option (u_char chr) { int j; for (j=0; 1; ++j) { if (NULL == tn_chars[j].name) { if (isprint(chr)) tmxr_buf_debug_char (chr); else { tmxr_buf_debug_char ('_'); if ((chr >= 1) && (chr <= 26)) { tmxr_buf_debug_char ('^'); tmxr_buf_debug_char ('A' + chr - 1); } else { char octal[8]; sprintf(octal, "\\%03o", (u_char)chr); tmxr_buf_debug_string (octal); } tmxr_buf_debug_char ('_'); } break; } if ((u_char)chr == tn_chars[j].value) { tmxr_buf_debug_char ('_'); tmxr_buf_debug_string (tn_chars[j].name); tmxr_buf_debug_char ('_'); break; } } } static int tmxr_buf_debug_telnet_options (u_char *buf, int bufsize) { int optsize = 2; tmxr_buf_debug_telnet_option ((u_char)buf[0]); tmxr_buf_debug_telnet_option ((u_char)buf[1]); switch ((u_char)buf[1]) { case TN_IAC: default: return optsize; break; case TN_WILL: case TN_WONT: case TN_DO: case TN_DONT: ++optsize; tmxr_buf_debug_telnet_option ((u_char)buf[2]); break; } return optsize; } void _tmxr_debug (uint32 dbits, TMLN *lp, const char *msg, char *buf, int bufsize) { DEVICE *dptr = (lp->dptr ? lp->dptr : (lp->mp ? lp->mp->dptr : NULL)); if ((dptr) && (dbits & dptr->dctrl)) { int i; tmxr_debug_buf_used = 0; if (tmxr_debug_buf) tmxr_debug_buf[tmxr_debug_buf_used] = '\0'; if (lp->notelnet) { int same, group, sidx, oidx; char outbuf[80], strbuf[18]; static char hex[] = "0123456789ABCDEF"; for (i=same=0; i<bufsize; i += 16) { if ((i > 0) && (0 == memcmp(&buf[i], &buf[i-16], 16))) { ++same; continue; } if (same > 0) { if (lp->mp->lines > 1) sim_debug (dbits, dptr, "Line:%d %04X thru %04X same as above\n", (int)(lp-lp->mp->ldsc), i-(16*same), i-1); else sim_debug (dbits, dptr, "%04X thru %04X same as above\n", i-(16*same), i-1); same = 0; } group = (((bufsize - i) > 16) ? 16 : (bufsize - i)); for (sidx=oidx=0; sidx<group; ++sidx) { outbuf[oidx++] = ' '; outbuf[oidx++] = hex[(buf[i+sidx]>>4)&0xf]; outbuf[oidx++] = hex[buf[i+sidx]&0xf]; if (isprint((u_char)buf[i+sidx])) strbuf[sidx] = buf[i+sidx]; else strbuf[sidx] = '.'; } outbuf[oidx] = '\0'; strbuf[sidx] = '\0'; if (lp->mp->lines > 1) sim_debug (dbits, dptr, "Line:%d %04X%-48s %s\n", (int)(lp-lp->mp->ldsc), i, outbuf, strbuf); else sim_debug (dbits, dptr, "%04X%-48s %s\n", i, outbuf, strbuf); } if (same > 0) { if (lp->mp->lines > 1) sim_debug (dbits, dptr, "Line:%d %04X thru %04X same as above\n", (int)(lp-lp->mp->ldsc), i-(16*same), bufsize-1); else sim_debug (dbits, dptr, "%04X thru %04X same as above\n", i-(16*same), bufsize-1); } } else { tmxr_debug_buf_used = 0; if (tmxr_debug_buf) tmxr_debug_buf[tmxr_debug_buf_used] = '\0'; for (i=0; i<bufsize; ++i) { switch ((u_char)buf[i]) { case TN_CR: tmxr_buf_debug_string ("_TN_CR_"); break; case TN_LF: tmxr_buf_debug_string ("_TN_LF_"); break; case TN_IAC: if (!lp->notelnet) { i += (tmxr_buf_debug_telnet_options ((u_char *)(&buf[i]), bufsize-i) - 1); break; } default: if (isprint((u_char)buf[i])) tmxr_buf_debug_char (buf[i]); else { tmxr_buf_debug_char ('_'); if ((buf[i] >= 1) && (buf[i] <= 26)) { tmxr_buf_debug_char ('^'); tmxr_buf_debug_char ('A' + buf[i] - 1); } else { char octal[8]; sprintf(octal, "\\%03o", (u_char)buf[i]); tmxr_buf_debug_string (octal); } tmxr_buf_debug_char ('_'); } break; } } if (lp->mp->lines > 1) sim_debug (dbits, dptr, "Line:%d %s %d bytes '%s'\n", (int)(lp-lp->mp->ldsc), msg, bufsize, tmxr_debug_buf); else sim_debug (dbits, dptr, "%s %d bytes '%s'\n", msg, bufsize, tmxr_debug_buf); } } } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | /* sim_tmxr.h: terminal multiplexer definitions Copyright (c) 2001-2008, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. Based on the original DZ11 simulator by Thord Nilson, as updated by Arthur Krewat. 10-Oct-12 MP Added extended attach support for serial, per line listener and outgoing connections 17-Jan-11 MP Added buffered line capabilities 20-Nov-08 RMS Added three new standardized SHOW routines 07-Oct-08 JDB Added serial port support to TMXR, TMLN 27-May-08 JDB Added lnorder to TMXR structure, added tmxr_set_lnorder and tmxr_set_lnorder 14-May-08 JDB Added dptr to TMXR structure 04-Jan-04 RMS Changed TMXR ldsc to be pointer to linedesc array Added tmxr_linemsg, logging (from Mark Pizzolato) 29-Dec-03 RMS Added output stall support, increased buffer size 22-Dec-02 RMS Added break support (from Mark Pizzolato) 20-Aug-02 RMS Added tmxr_open_master, tmxr_close_master, tmxr.port 30-Dec-01 RMS Renamed tmxr_fstatus, added tmxr_fstats 20-Oct-01 RMS Removed tmxr_getchar, formalized buffer guard, added tmxr_rqln, tmxr_tqln */ #ifndef SIM_TMXR_H_ #define SIM_TMXR_H_ 0 #ifdef __cplusplus extern "C" { #endif #ifndef SIMH_SERHANDLE_DEFINED #define SIMH_SERHANDLE_DEFINED 0 typedef struct SERPORT *SERHANDLE; #endif #include "sim_sock.h" #define TMXR_V_VALID 15 #define TMXR_VALID (1 << TMXR_V_VALID) #define TMXR_MAXBUF 256 /* buffer size */ #define TMXR_DTR_DROP_TIME 500 /* milliseconds to drop DTR for 'pseudo' modem control */ #define TMXR_MODEM_RING_TIME 3 /* seconds to wait for DTR for incoming connections */ #define TMXR_DEFAULT_CONNECT_POLL_INTERVAL 1 /* seconds between connection polls */ #define TMXR_DBG_XMT 0x0010000 /* Debug Transmit Data */ #define TMXR_DBG_RCV 0x0020000 /* Debug Received Data */ #define TMXR_DBG_RET 0x0040000 /* Debug Returned Received Data */ #define TMXR_DBG_MDM 0x0080000 /* Debug Modem Signals */ #define TMXR_DBG_CON 0x0100000 /* Debug Connection Activities */ #define TMXR_DBG_ASY 0x0200000 /* Debug Asynchronous Activities */ #define TMXR_DBG_TRC 0x0400000 /* Debug trace routine calls */ #define TMXR_DBG_PXMT 0x0800000 /* Debug Transmit Packet Data */ #define TMXR_DBG_PRCV 0x1000000 /* Debug Received Packet Data */ #define TMXR_DBG_EXP 0x2000000 /* Debug Expect Activities */ #define TMXR_DBG_SEND 0x4000000 /* Debug Send Activities */ /* Modem Control Bits */ #define TMXR_MDM_DTR 0x01 /* Data Terminal Ready */ #define TMXR_MDM_RTS 0x02 /* Request To Send */ #define TMXR_MDM_DCD 0x04 /* Data Carrier Detect */ #define TMXR_MDM_RNG 0x08 /* Ring Indicator */ #define TMXR_MDM_CTS 0x10 /* Clear To Send */ #define TMXR_MDM_DSR 0x20 /* Data Set Ready */ #define TMXR_MDM_INCOMING (TMXR_MDM_DCD|TMXR_MDM_RNG|TMXR_MDM_CTS|TMXR_MDM_DSR) /* Settable Modem Bits */ #define TMXR_MDM_OUTGOING (TMXR_MDM_DTR|TMXR_MDM_RTS) /* Settable Modem Bits */ /* Unit flags */ #define TMUF_V_NOASYNCH (UNIT_V_UF + 12) /* Asynch Disabled unit */ #define TMUF_NOASYNCH (1u << TMUF_V_NOASYNCH) /* This flag can be defined */ /* statically in a unit's flag field */ /* This will disable the unit from */ /* supporting asynchronmous mux behaviors */ /* Receive line speed limits */ #define TMLN_SPD_50_BPS 200000 /* usec per character */ #define TMLN_SPD_75_BPS 133333 /* usec per character */ #define TMLN_SPD_110_BPS 90909 /* usec per character */ #define TMLN_SPD_134_BPS 74626 /* usec per character */ #define TMLN_SPD_150_BPS 66666 /* usec per character */ #define TMLN_SPD_300_BPS 33333 /* usec per character */ #define TMLN_SPD_600_BPS 16666 /* usec per character */ #define TMLN_SPD_1200_BPS 8333 /* usec per character */ #define TMLN_SPD_1800_BPS 5555 /* usec per character */ #define TMLN_SPD_2000_BPS 5000 /* usec per character */ #define TMLN_SPD_2400_BPS 4166 /* usec per character */ #define TMLN_SPD_3600_BPS 2777 /* usec per character */ #define TMLN_SPD_4800_BPS 2083 /* usec per character */ #define TMLN_SPD_7200_BPS 1388 /* usec per character */ #define TMLN_SPD_9600_BPS 1041 /* usec per character */ #define TMLN_SPD_19200_BPS 520 /* usec per character */ #define TMLN_SPD_38400_BPS 260 /* usec per character */ #define TMLN_SPD_57600_BPS 173 /* usec per character */ #define TMLN_SPD_76800_BPS 130 /* usec per character */ #define TMLN_SPD_115200_BPS 86 /* usec per character */ typedef struct tmln TMLN; typedef struct tmxr TMXR; struct loopbuf { int32 bpr; /* xmt buf remove */ int32 bpi; /* xmt buf insert */ int32 size; }; struct tmln { int conn; /* line connected flag */ SOCKET sock; /* connection socket */ char *ipad; /* IP address */ SOCKET master; /* line specific master socket */ char *port; /* line specific listening port */ int32 sessions; /* count of tcp connections received */ uint32 cnms; /* conn time */ int32 tsta; /* Telnet state */ int32 rcve; /* rcv enable */ int32 xmte; /* xmt enable */ int32 dstb; /* disable Telnet binary mode */ t_bool notelnet; /* raw binary data (no telnet interpretation) */ uint8 *telnet_sent_opts; /* Telnet Options which we have sent a DON'T/WON'T */ int32 rxbpr; /* rcv buf remove */ int32 rxbpi; /* rcv buf insert */ int32 rxbsz; /* rcv buffer size */ int32 rxcnt; /* rcv count */ int32 rxpcnt; /* rcv packet count */ int32 txbpr; /* xmt buf remove */ int32 txbpi; /* xmt buf insert */ int32 txcnt; /* xmt count */ int32 txpcnt; /* xmt packet count */ int32 txdrp; /* xmt drop count */ int32 txbsz; /* xmt buffer size */ int32 txbfd; /* xmt buffered flag */ t_bool modem_control; /* line supports modem control behaviors */ int32 modembits; /* modem bits which are currently set */ FILE *txlog; /* xmt log file */ FILEREF *txlogref; /* xmt log file reference */ char *txlogname; /* xmt log file name */ char *rxb; /* rcv buffer */ char *rbr; /* rcv break */ char *txb; /* xmt buffer */ uint8 *rxpb; /* rcv packet buffer */ uint32 rxpbsize; /* rcv packet buffer size */ uint32 rxpboffset; /* rcv packet buffer offset */ uint32 rxbps; /* rcv bps speed (0 - unlimited) */ double rxbpsfactor; /* receive speed factor (scaled to usecs) */ #define TMXR_RX_BPS_UNIT_SCALE 1000000.0 uint32 rxdelta; /* rcv inter character min time (usecs) */ double rxnexttime; /* min time for next receive character */ uint32 txbps; /* xmt bps speed (0 - unlimited) */ uint32 txdelta; /* xmt inter character min time (usecs) */ double txnexttime; /* min time for next transmit character */ uint8 *txpb; /* xmt packet buffer */ uint32 txpbsize; /* xmt packet buffer size */ uint32 txppsize; /* xmt packet packet size */ uint32 txppoffset; /* xmt packet buffer offset */ TMXR *mp; /* back pointer to mux */ char *serconfig; /* line config */ SERHANDLE serport; /* serial port handle */ t_bool ser_connect_pending; /* serial connection notice pending */ SOCKET connecting; /* Outgoing socket while connecting */ char *destination; /* Outgoing destination address:port */ t_bool loopback; /* Line in loopback mode */ t_bool halfduplex; /* Line in half-duplex mode */ t_bool datagram; /* Line is datagram packet oriented */ t_bool packet; /* Line is packet oriented */ int32 lpbpr; /* loopback buf remove */ int32 lpbpi; /* loopback buf insert */ int32 lpbcnt; /* loopback buf used count */ int32 lpbsz; /* loopback buffer size */ char *lpb; /* loopback buffer */ UNIT *uptr; /* input polling unit (default to mp->uptr) */ UNIT *o_uptr; /* output polling unit (default to lp->uptr)*/ DEVICE *dptr; /* line specific device */ EXPECT expect; /* Expect rules */ SEND send; /* Send input state */ }; struct tmxr { int32 lines; /* # lines */ char *port; /* listening port */ SOCKET master; /* master socket */ TMLN *ldsc; /* line descriptors */ int32 *lnorder; /* line connection order */ DEVICE *dptr; /* multiplexer device */ UNIT *uptr; /* polling unit (connection) */ char logfiletmpl[FILENAME_MAX]; /* template logfile name */ int32 txcount; /* count of transmit bytes */ int32 buffered; /* Buffered Line Behavior and Buffer Size Flag */ int32 sessions; /* count of tcp connections received */ uint32 poll_interval; /* frequency of connection polls (seconds) */ uint32 last_poll_time; /* time of last connection poll */ uint32 ring_start_time; /* time ring signal was raised */ char *ring_ipad; /* incoming connection address awaiting DTR */ SOCKET ring_sock; /* incoming connection socket awaiting DTR */ t_bool notelnet; /* default telnet capability for incoming connections */ t_bool modem_control; /* multiplexer supports modem control behaviors */ t_bool packet; /* Lines are packet oriented */ t_bool datagram; /* Lines use datagram packet transport */ }; int32 tmxr_poll_conn (TMXR *mp); t_stat tmxr_reset_ln (TMLN *lp); t_stat tmxr_detach_ln (TMLN *lp); int32 tmxr_input_pending_ln (TMLN *lp); int32 tmxr_getc_ln (TMLN *lp); t_stat tmxr_get_packet_ln (TMLN *lp, const uint8 **pbuf, size_t *psize); t_stat tmxr_get_packet_ln_ex (TMLN *lp, const uint8 **pbuf, size_t *psize, uint8 frame_byte); void tmxr_poll_rx (TMXR *mp); t_stat tmxr_putc_ln (TMLN *lp, int32 chr); t_stat tmxr_put_packet_ln (TMLN *lp, const uint8 *buf, size_t size); t_stat tmxr_put_packet_ln_ex (TMLN *lp, const uint8 *buf, size_t size, uint8 frame_byte); void tmxr_poll_tx (TMXR *mp); int32 tmxr_send_buffered_data (TMLN *lp); t_stat tmxr_open_master (TMXR *mp, CONST char *cptr); t_stat tmxr_close_master (TMXR *mp); t_stat tmxr_connection_poll_interval (TMXR *mp, uint32 seconds); t_stat tmxr_attach_ex (TMXR *mp, UNIT *uptr, CONST char *cptr, t_bool async); t_stat tmxr_detach (TMXR *mp, UNIT *uptr); t_stat tmxr_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); char *tmxr_line_attach_string(TMLN *lp); t_stat tmxr_set_modem_control_passthru (TMXR *mp); t_stat tmxr_clear_modem_control_passthru (TMXR *mp); t_stat tmxr_set_get_modem_bits (TMLN *lp, int32 bits_to_set, int32 bits_to_clear, int32 *incoming_bits); t_stat tmxr_set_line_loopback (TMLN *lp, t_bool enable_loopback); t_bool tmxr_get_line_loopback (TMLN *lp); t_stat tmxr_set_line_halfduplex (TMLN *lp, t_bool enable_loopback); t_bool tmxr_get_line_halfduplex (TMLN *lp); t_stat tmxr_set_line_speed (TMLN *lp, CONST char *speed); t_stat tmxr_set_config_line (TMLN *lp, CONST char *config); t_stat tmxr_set_line_unit (TMXR *mp, int line, UNIT *uptr_poll); t_stat tmxr_set_line_output_unit (TMXR *mp, int line, UNIT *uptr_poll); t_stat tmxr_set_console_units (UNIT *rxuptr, UNIT *txuptr); t_stat tmxr_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); t_stat tmxr_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); void tmxr_msg (SOCKET sock, const char *msg); void tmxr_linemsg (TMLN *lp, const char *msg); void tmxr_linemsgf (TMLN *lp, const char *fmt, ...); void tmxr_linemsgvf (TMLN *lp, const char *fmt, va_list args); void tmxr_fconns (FILE *st, const TMLN *lp, int32 ln); void tmxr_fstats (FILE *st, const TMLN *lp, int32 ln); t_stat tmxr_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat tmxr_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat tmxr_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat tmxr_dscln (UNIT *uptr, int32 val, CONST char *cptr, void *desc); int32 tmxr_rqln (const TMLN *lp); int32 tmxr_tqln (const TMLN *lp); int32 tmxr_tpqln (const TMLN *lp); t_bool tmxr_tpbusyln (const TMLN *lp); t_stat tmxr_set_lnorder (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat tmxr_show_lnorder (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat tmxr_show_summ (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat tmxr_show_cstat (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat tmxr_show_lines (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat tmxr_show_open_devices (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc); t_stat tmxr_activate (UNIT *uptr, int32 interval); t_stat tmxr_activate_after (UNIT *uptr, uint32 usecs_walltime); t_stat tmxr_activate_after_abs (UNIT *uptr, uint32 usecs_walltime); t_stat tmxr_clock_coschedule (UNIT *uptr, int32 interval); t_stat tmxr_clock_coschedule_abs (UNIT *uptr, int32 interval); t_stat tmxr_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 ticks); t_stat tmxr_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 ticks); t_stat tmxr_change_async (void); t_stat tmxr_locate_line_send (const char *dev_line, SEND **snd); t_stat tmxr_locate_line_expect (const char *dev_line, EXPECT **exp); t_stat tmxr_startup (void); t_stat tmxr_shutdown (void); t_stat tmxr_start_poll (void); t_stat tmxr_stop_poll (void); void _tmxr_debug (uint32 dbits, TMLN *lp, const char *msg, char *buf, int bufsize); #define tmxr_debug(dbits, lp, msg, buf, bufsize) do {if (sim_deb && (lp)->mp && (lp)->mp->dptr && ((dbits) & (lp)->mp->dptr->dctrl)) _tmxr_debug (dbits, lp, msg, buf, bufsize); } while (0) #define tmxr_debug_msg(dbits, lp, msg) do {if (sim_deb && (lp)->mp && (lp)->mp->dptr && ((dbits) & (lp)->mp->dptr->dctrl)) sim_debug (dbits, (lp)->mp->dptr, "%s", msg); } while (0) #define tmxr_debug_return(lp, val) do {if (sim_deb && (val) && (lp)->mp && (lp)->mp->dptr && (TMXR_DBG_RET & (lp)->mp->dptr->dctrl)) { if ((lp)->rxbps) sim_debug (TMXR_DBG_RET, (lp)->mp->dptr, "Ln%d: 0x%x - Next after: %.0f\n", (int)((lp)-(lp)->mp->ldsc), val, (lp)->rxnexttime); else sim_debug (TMXR_DBG_RET, (lp)->mp->dptr, "Ln%d: 0x%x\n", (int)((lp)-(lp)->mp->ldsc), val); } } while (0) #define tmxr_debug_trace(mp, msg) do {if (sim_deb && (mp)->dptr && (TMXR_DBG_TRC & (mp)->dptr->dctrl)) sim_debug (TMXR_DBG_TRC, mp->dptr, "%s\n", (msg)); } while (0) #define tmxr_debug_trace_line(lp, msg) do {if (sim_deb && (lp)->mp && (lp)->mp->dptr && (TMXR_DBG_TRC & (lp)->mp->dptr->dctrl)) sim_debug (TMXR_DBG_TRC, (lp)->mp->dptr, "Ln%d:%s\n", (int)((lp)-(lp)->mp->ldsc), (msg)); } while (0) #define tmxr_debug_connect(mp, msg) do {if (sim_deb && (mp)->dptr && (TMXR_DBG_CON & (mp)->dptr->dctrl)) sim_debug (TMXR_DBG_CON, mp->dptr, "%s\n", (msg)); } while (0) #define tmxr_debug_connect_line(lp, msg) do {if (sim_deb && (lp)->mp && (lp)->mp->dptr && (TMXR_DBG_CON & (lp)->mp->dptr->dctrl)) sim_debug (TMXR_DBG_CON, (lp)->mp->dptr, "Ln%d:%s\n", (int)((lp)-(lp)->mp->ldsc), (msg)); } while (0) #if defined(SIM_ASYNCH_MUX) && !defined(SIM_ASYNCH_IO) #undef SIM_ASYNCH_MUX #endif /* defined(SIM_ASYNCH_MUX) && !defined(SIM_ASYNCH_IO) */ #if defined(SIM_ASYNCH_MUX) #define tmxr_attach(mp, uptr, cptr) tmxr_attach_ex(mp, uptr, cptr, TRUE) #else #define tmxr_attach(mp, uptr, cptr) tmxr_attach_ex(mp, uptr, cptr, FALSE) #endif #if (!defined(NOT_MUX_USING_CODE)) #define sim_activate tmxr_activate #define sim_activate_after tmxr_activate_after #define sim_activate_after_abs tmxr_activate_after_abs #define sim_clock_coschedule tmxr_clock_coschedule #define sim_clock_coschedule_abs tmxr_clock_coschedule_abs #define sim_clock_coschedule_tmr tmxr_clock_coschedule_tmr #define sim_clock_coschedule_tmr_abs tmxr_clock_coschedule_tmr_abs #endif #ifdef __cplusplus } #endif #endif /* _SIM_TMXR_H_ */ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 | /* sim_video.c: Bitmap video output Copyright (c) 2011-2013, Matt Burke Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the author shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. 08-Nov-2013 MB Added globals for current mouse status 11-Jun-2013 MB First version */ #include "sim_video.h" #include "scp.h" t_bool vid_active = FALSE; int32 vid_mouse_xrel; int32 vid_mouse_yrel; int32 vid_cursor_x; int32 vid_cursor_y; t_bool vid_mouse_b1 = FALSE; t_bool vid_mouse_b2 = FALSE; t_bool vid_mouse_b3 = FALSE; static VID_QUIT_CALLBACK vid_quit_callback = NULL; t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback) { vid_quit_callback = callback; return SCPE_OK; } t_stat vid_show (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc) { return vid_show_video (st, uptr, val, desc); } #if defined(USE_SIM_VIDEO) && defined(HAVE_LIBSDL) char vid_release_key[64] = "Ctrl-Right-Shift"; #include <SDL.h> #include <SDL_thread.h> static const char *key_names[] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "BACKQUOTE", "MINUS", "EQUALS", "LEFT_BRACKET", "RIGHT_BRACKET", "SEMICOLON", "SINGLE_QUOTE", "BACKSLASH", "LEFT_BACKSLASH", "COMMA", "PERIOD", "SLASH", "PRINT", "SCRL_LOCK", "PAUSE", "ESC", "BACKSPACE", "TAB", "ENTER", "SPACE", "INSERT", "DELETE", "HOME", "END", "PAGE_UP", "PAGE_DOWN", "UP", "DOWN", "LEFT", "RIGHT", "CAPS_LOCK", "NUM_LOCK", "ALT_L", "ALT_R", "CTRL_L", "CTRL_R", "SHIFT_L", "SHIFT_R", "WIN_L", "WIN_R", "MENU", "KP_ADD", "KP_SUBTRACT", "KP_END", "KP_DOWN", "KP_PAGE_DOWN", "KP_LEFT", "KP_RIGHT", "KP_HOME", "KP_UP", "KP_PAGE_UP", "KP_INSERT", "KP_DELETE", "KP_5", "KP_ENTER", "KP_MULTIPLY", "KP_DIVIDE" }; const char *vid_key_name (int32 key) { static char tmp_key_name[40]; if (key < sizeof(key_names)/sizeof(key_names[0])) sprintf (tmp_key_name, "SIM_KEY_%s", key_names[key]); else sprintf (tmp_key_name, "UNKNOWN KEY: %d", key); return tmp_key_name; } #if defined(HAVE_LIBPNG) /* From: https://github.com/driedfruit/SDL_SavePNG */ /* * Save an SDL_Surface as a PNG file. * * Returns 0 success or -1 on failure, the error message is then retrievable * via SDL_GetError(). */ #define SDL_SavePNG(surface, file) \ SDL_SavePNG_RW(surface, SDL_RWFromFile(file, "wb"), 1) /* * SDL_SavePNG -- libpng-based SDL_Surface writer. * * This code is free software, available under zlib/libpng license. * http://www.libpng.org/pub/png/src/libpng-LICENSE.txt */ #include <SDL.h> #include <png.h> #define SUCCESS 0 #define ERROR -1 #define USE_ROW_POINTERS #if SDL_BYTEORDER == SDL_BIG_ENDIAN #define rmask 0xFF000000 #define gmask 0x00FF0000 #define bmask 0x0000FF00 #define amask 0x000000FF #else #define rmask 0x000000FF #define gmask 0x0000FF00 #define bmask 0x00FF0000 #define amask 0xFF000000 #endif /* libpng callbacks */ static void png_error_SDL(png_structp ctx, png_const_charp str) { SDL_SetError("libpng: %s\n", str); } static void png_write_SDL(png_structp png_ptr, png_bytep data, png_size_t length) { SDL_RWops *rw = (SDL_RWops*)png_get_io_ptr(png_ptr); SDL_RWwrite(rw, data, sizeof(png_byte), length); } static SDL_Surface *SDL_PNGFormatAlpha(SDL_Surface *src) { SDL_Surface *surf; SDL_Rect rect = { 0 }; /* NO-OP for images < 32bpp and 32bpp images that already have Alpha channel */ if (src->format->BitsPerPixel <= 24 || src->format->Amask) { src->refcount++; return src; } /* Convert 32bpp alpha-less image to 24bpp alpha-less image */ rect.w = src->w; rect.h = src->h; surf = SDL_CreateRGBSurface(src->flags, src->w, src->h, 24, src->format->Rmask, src->format->Gmask, src->format->Bmask, 0); SDL_LowerBlit(src, &rect, surf, &rect); return surf; } static int SDL_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst) { png_structp png_ptr; png_infop info_ptr; png_colorp pal_ptr; SDL_Palette *pal; int i, colortype; #ifdef USE_ROW_POINTERS png_bytep *row_pointers; #endif /* Initialize and do basic error checking */ if (!dst) { SDL_SetError("Argument 2 to SDL_SavePNG_RW can't be NULL, expecting SDL_RWops*\n"); return (ERROR); } if (!surface) { SDL_SetError("Argument 1 to SDL_SavePNG_RW can't be NULL, expecting SDL_Surface*\n"); if (freedst) SDL_RWclose(dst); return (ERROR); } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_SDL, NULL); /* err_ptr, err_fn, warn_fn */ if (!png_ptr) { SDL_SetError("Unable to png_create_write_struct on %s\n", PNG_LIBPNG_VER_STRING); if (freedst) SDL_RWclose(dst); return (ERROR); } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { SDL_SetError("Unable to png_create_info_struct\n"); png_destroy_write_struct(&png_ptr, NULL); if (freedst) SDL_RWclose(dst); return (ERROR); } if (setjmp(png_jmpbuf(png_ptr))) /* All other errors, see also "png_error_SDL" */ { png_destroy_write_struct(&png_ptr, &info_ptr); if (freedst) SDL_RWclose(dst); return (ERROR); } /* Setup our RWops writer */ png_set_write_fn(png_ptr, dst, png_write_SDL, NULL); /* w_ptr, write_fn, flush_fn */ /* Prepare chunks */ colortype = PNG_COLOR_MASK_COLOR; if (surface->format->BytesPerPixel > 0 && surface->format->BytesPerPixel <= 8 && (pal = surface->format->palette)) { colortype |= PNG_COLOR_MASK_PALETTE; pal_ptr = (png_colorp)malloc(pal->ncolors * sizeof(png_color)); for (i = 0; i < pal->ncolors; i++) { pal_ptr[i].red = pal->colors[i].r; pal_ptr[i].green = pal->colors[i].g; pal_ptr[i].blue = pal->colors[i].b; } png_set_PLTE(png_ptr, info_ptr, pal_ptr, pal->ncolors); free(pal_ptr); } else if (surface->format->BytesPerPixel > 3 || surface->format->Amask) colortype |= PNG_COLOR_MASK_ALPHA; png_set_IHDR(png_ptr, info_ptr, surface->w, surface->h, 8, colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); // png_set_packing(png_ptr); /* Allow BGR surfaces */ if (surface->format->Rmask == bmask && surface->format->Gmask == gmask && surface->format->Bmask == rmask) png_set_bgr(png_ptr); /* Write everything */ png_write_info(png_ptr, info_ptr); #ifdef USE_ROW_POINTERS row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*surface->h); for (i = 0; i < surface->h; i++) row_pointers[i] = (png_bytep)(Uint8*)surface->pixels + i * surface->pitch; png_write_image(png_ptr, row_pointers); free(row_pointers); #else for (i = 0; i < surface->h; i++) png_write_row(png_ptr, (png_bytep)(Uint8*)surface->pixels + i * surface->pitch); #endif png_write_end(png_ptr, info_ptr); /* Done */ png_destroy_write_struct(&png_ptr, &info_ptr); if (freedst) SDL_RWclose(dst); return (SUCCESS); } #endif /* defined(HAVE_LIBPNG) */ /* Some platforms (OS X), require that ALL input event processing be performed by the main thread of the process. To satisfy this requirement, we leverage the SDL_MAIN functionality which does: #defines main SDL_main and we define the main() entry point here. Locally, we run the application's SDL_main in a separate thread, and while that thread is running, the main thread performs event handling and dispatch. */ #define EVENT_REDRAW 1 /* redraw event for SDL */ #define EVENT_CLOSE 2 /* close event for SDL */ #define EVENT_CURSOR 3 /* new cursor for SDL */ #define EVENT_WARP 4 /* warp mouse position for SDL */ #define EVENT_DRAW 5 /* draw/blit region for SDL */ #define EVENT_SHOW 6 /* show SDL capabilities */ #define EVENT_OPEN 7 /* vid_open request */ #define EVENT_EXIT 8 /* program exit */ #define EVENT_SCREENSHOT 9 /* produce screenshot of video window */ #define EVENT_BEEP 10 /* audio beep */ #define MAX_EVENTS 20 /* max events in queue */ typedef struct { SIM_KEY_EVENT events[MAX_EVENTS]; SDL_sem *sem; int32 head; int32 tail; int32 count; } KEY_EVENT_QUEUE; typedef struct { SIM_MOUSE_EVENT events[MAX_EVENTS]; SDL_sem *sem; int32 head; int32 tail; int32 count; } MOUSE_EVENT_QUEUE; int vid_thread (void* arg); int vid_video_events (void); void vid_show_video_event (void); void vid_screenshot_event (void); void vid_beep_event (void); /* libSDL and libSDL2 have significantly different APIs. The consequence is that this code has significant #ifdef sections. The current structure is to implement the API differences in each routine that has a difference. This allows the decision and flow logic to exist once and thus to allow logic changes to be implemented in one place. */ t_bool vid_mouse_captured; int32 vid_flags; /* Open Flags */ int32 vid_width; int32 vid_height; t_bool vid_ready; char vid_title[128]; static void vid_beep_setup (int duration_ms, int tone_frequency); static void vid_beep_cleanup (void); #if SDL_MAJOR_VERSION == 1 /* Some platforms that use X11 display technology have libSDL environments which need to call XInitThreads when libSDL is used in multi-threaded programs. This routine attempts to locate the X11 shareable library and if it is found loads it and calls the XInitThreads routine to meet this requirement. */ #ifdef HAVE_DLOPEN #include <dlfcn.h> #endif static void _XInitThreads (void) { #ifdef HAVE_DLOPEN static void *hLib = NULL; /* handle to Library */ #define __STR_QUOTE(tok) #tok #define __STR(tok) __STR_QUOTE(tok) static const char* lib_name = "libX11." __STR(HAVE_DLOPEN); typedef int (*_func)(); _func _func_ptr = NULL; if (!hLib) hLib = dlopen(lib_name, RTLD_NOW); if (hLib) _func_ptr = (_func)((size_t)dlsym(hLib, "XInitThreads")); if (_func_ptr) _func_ptr(); #endif } t_bool vid_key_state[SDLK_LAST]; SDL_Surface *vid_image; /* video buffer */ SDL_Surface *vid_window; /* window handle */ #else t_bool vid_key_state[SDL_NUM_SCANCODES]; SDL_Texture *vid_texture; /* video buffer in GPU */ SDL_Renderer *vid_renderer; SDL_Window *vid_window; /* window handle */ uint32 vid_windowID; #endif SDL_Thread *vid_thread_handle = NULL; /* event thread handle */ SDL_Cursor *vid_cursor = NULL; /* current cursor */ t_bool vid_cursor_visible = FALSE; /* cursor visibility state */ uint32 vid_mono_palette[2]; /* Monochrome Color Map */ SDL_Color vid_colors[256]; KEY_EVENT_QUEUE vid_key_events; /* keyboard events */ MOUSE_EVENT_QUEUE vid_mouse_events; /* mouse events */ DEVICE *vid_dev; #if defined (SDL_MAIN_AVAILABLE) #if defined (main) #undef main #endif static int main_argc; static char **main_argv; static SDL_Thread *vid_main_thread_handle; int main_thread (void *arg) { SDL_Event user_event; int stat; stat = SDL_main (main_argc, main_argv); user_event.type = SDL_USEREVENT; user_event.user.code = EVENT_EXIT; user_event.user.data1 = NULL; user_event.user.data2 = NULL; while (SDL_PushEvent (&user_event) < 0) sim_os_ms_sleep (10); return stat; } int main (int argc, char *argv[]) { SDL_Event event; int status; main_argc = argc; main_argv = argv; #if SDL_MAJOR_VERSION == 1 _XInitThreads(); SDL_Init (SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE); vid_main_thread_handle = SDL_CreateThread (main_thread , NULL); #else SDL_SetHint (SDL_HINT_RENDER_DRIVER, "software"); SDL_Init (SDL_INIT_VIDEO); vid_main_thread_handle = SDL_CreateThread (main_thread , "simh-main", NULL); #endif sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); vid_beep_setup (400, 660); while (1) { int status = SDL_WaitEvent (&event); if (status == 1) { if (event.type == SDL_USEREVENT) { if (event.user.code == EVENT_EXIT) break; if (event.user.code == EVENT_OPEN) vid_video_events (); else { if (event.user.code == EVENT_SHOW) vid_show_video_event (); else { if (event.user.code == EVENT_SCREENSHOT) vid_screenshot_event (); else { if (event.user.code == EVENT_BEEP) vid_beep_event (); else { sim_printf ("main(): Unexpected User event: %d\n", event.user.code); break; } } } } } else { // sim_printf ("main(): Ignoring unexpected event: %d\n", event.type); } } else { if (status < 0) sim_printf ("main() - ` error: %s\n", SDL_GetError()); } } SDL_WaitThread (vid_main_thread_handle, &status); vid_beep_cleanup (); SDL_Quit (); return status; } static t_stat vid_create_window () { int wait_count = 0; SDL_Event user_event; vid_ready = FALSE; user_event.type = SDL_USEREVENT; user_event.user.code = EVENT_OPEN; user_event.user.data1 = NULL; user_event.user.data2 = NULL; SDL_PushEvent (&user_event); while ((!vid_ready) && (++wait_count < 20)) sim_os_ms_sleep (100); if (!vid_ready) { vid_close (); return SCPE_OPENERR; } return SCPE_OK; } #else static int vid_create_window () { int wait_count = 0; #if SDL_MAJOR_VERSION == 1 vid_thread_handle = SDL_CreateThread (vid_thread, NULL); #else vid_thread_handle = SDL_CreateThread (vid_thread, "vid-thread", NULL); #endif if (vid_thread_handle == NULL) { vid_close (); return SCPE_OPENERR; } while ((!vid_ready) && (++wait_count < 20)) sim_os_ms_sleep (100); if (!vid_ready) { vid_close (); return SCPE_OPENERR; } return SCPE_OK; } #endif t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, int flags) { if (!vid_active) { int wait_count = 0; t_stat stat; if ((strlen(sim_name) + 7 + (dptr ? strlen (dptr->name) : 0) + (title ? strlen (title) : 0)) < sizeof (vid_title)) sprintf (vid_title, "%s%s%s%s%s", sim_name, dptr ? " - " : "", dptr ? dptr->name : "", title ? " - " : "", title ? title : ""); else sprintf (vid_title, "%s", sim_name); vid_flags = flags; vid_active = TRUE; vid_width = width; vid_height = height; vid_mouse_captured = FALSE; vid_cursor_visible = (vid_flags & SIM_VID_INPUTCAPTURED); vid_mouse_xrel = 0; vid_mouse_yrel = 0; vid_key_events.head = 0; vid_key_events.tail = 0; vid_key_events.count = 0; vid_key_events.sem = SDL_CreateSemaphore (1); vid_mouse_events.head = 0; vid_mouse_events.tail = 0; vid_mouse_events.count = 0; vid_mouse_events.sem = SDL_CreateSemaphore (1); vid_dev = dptr; stat = vid_create_window (); if (stat != SCPE_OK) return stat; sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_open() - Success\n"); } return SCPE_OK; } t_stat vid_close (void) { if (vid_active) { SDL_Event user_event; int status; vid_active = FALSE; if (vid_ready) { sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_close()\n"); user_event.type = SDL_USEREVENT; user_event.user.code = EVENT_CLOSE; user_event.user.data1 = NULL; user_event.user.data2 = NULL; while (SDL_PushEvent (&user_event) < 0) sim_os_ms_sleep (10); if (vid_thread_handle) { SDL_WaitThread (vid_thread_handle, &status); vid_thread_handle = NULL; } vid_dev = NULL; } while (vid_ready) sim_os_ms_sleep (10); if (vid_mouse_events.sem) { SDL_DestroySemaphore(vid_mouse_events.sem); vid_mouse_events.sem = NULL; } if (vid_key_events.sem) { SDL_DestroySemaphore(vid_key_events.sem); vid_key_events.sem = NULL; } } return SCPE_OK; } t_stat vid_poll_kb (SIM_KEY_EVENT *ev) { if (SDL_SemTryWait (vid_key_events.sem) == 0) { /* get lock */ if (vid_key_events.count > 0) { /* events in queue? */ *ev = vid_key_events.events[vid_key_events.head++]; vid_key_events.count--; if (vid_key_events.head == MAX_EVENTS) vid_key_events.head = 0; SDL_SemPost (vid_key_events.sem); return SCPE_OK; } SDL_SemPost (vid_key_events.sem); } return SCPE_EOF; } t_stat vid_poll_mouse (SIM_MOUSE_EVENT *ev) { t_stat stat = SCPE_EOF; SIM_MOUSE_EVENT *nev; if (SDL_SemTryWait (vid_mouse_events.sem) == 0) { if (vid_mouse_events.count > 0) { stat = SCPE_OK; *ev = vid_mouse_events.events[vid_mouse_events.head++]; vid_mouse_events.count--; if (vid_mouse_events.head == MAX_EVENTS) vid_mouse_events.head = 0; nev = &vid_mouse_events.events[vid_mouse_events.head]; if ((vid_mouse_events.count > 0) && (0 == (ev->x_rel + nev->x_rel)) && (0 == (ev->y_rel + nev->y_rel)) && (ev->b1_state == nev->b1_state) && (ev->b2_state == nev->b2_state) && (ev->b3_state == nev->b3_state)) { if ((++vid_mouse_events.head) == MAX_EVENTS) vid_mouse_events.head = 0; vid_mouse_events.count--; stat = SCPE_EOF; sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "vid_poll_mouse: ignoring bouncing events\n"); } } if (SDL_SemPost (vid_mouse_events.sem)) sim_printf ("%s: vid_poll_mouse(): SDL_SemPost error: %s\n", sim_dname(vid_dev), SDL_GetError()); } return stat; } void vid_draw (int32 x, int32 y, int32 w, int32 h, uint32 *buf) { #if SDL_MAJOR_VERSION == 1 int32 i; uint32* pixels; sim_debug (SIM_VID_DBG_VIDEO, vid_dev, "vid_draw(%d, %d, %d, %d)\n", x, y, w, h); pixels = (uint32 *)vid_image->pixels; for (i = 0; i < h; i++) memcpy (pixels + ((i + y) * vid_width) + x, buf + w*i, w*sizeof(*pixels)); #else SDL_Event user_event; SDL_Rect *vid_dst; uint32 *vid_data; sim_debug (SIM_VID_DBG_VIDEO, vid_dev, "vid_draw(%d, %d, %d, %d)\n", x, y, w, h); vid_dst = (SDL_Rect *)malloc (sizeof(*vid_dst)); if (!vid_dst) { sim_printf ("%s: vid_draw() memory allocation error\n", vid_dev ? sim_dname(vid_dev) : "Video Device"); return; } vid_dst->x = x; vid_dst->y = y; vid_dst->w = w; vid_dst->h = h; vid_data = (uint32 *)malloc (w*h*sizeof(*buf)); if (!vid_data) { sim_printf ("%s: vid_draw() memory allocation error\n", vid_dev ? sim_dname(vid_dev) : "Video Device"); free (vid_dst); return; } memcpy (vid_data, buf, w*h*sizeof(*buf)); user_event.type = SDL_USEREVENT; user_event.user.code = EVENT_DRAW; user_event.user.data1 = (void *)vid_dst; user_event.user.data2 = (void *)vid_data; if (SDL_PushEvent (&user_event) < 0) { sim_printf ("%s: vid_draw() SDL_PushEvent error: %s\n", vid_dev ? sim_dname(vid_dev) : "Video Device", SDL_GetError()); free (vid_dst); free (vid_data); } #endif } t_stat vid_set_cursor (t_bool visible, uint32 width, uint32 height, uint8 *data, uint8 *mask, uint32 hot_x, uint32 hot_y) { SDL_Cursor *cursor = SDL_CreateCursor (data, mask, width, height, hot_x, hot_y); SDL_Event user_event; sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "vid_set_cursor(%s, %d, %d) Setting New Cursor\n", visible ? "visible" : "invisible", width, height); if (sim_deb) { uint32 i, j; for (i=0; i<height; i++) { sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "Cursor: "); for (j=0; j<width; j++) { int byte = (j + i*width) >> 3; int bit = 7 - ((j + i*width) & 0x7); static char mode[] = "TWIB"; sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "%c", mode[(((data[byte]>>bit)&1)<<1)|(mask[byte]>>bit)&1]); } sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "\n"); } } user_event.type = SDL_USEREVENT; user_event.user.code = EVENT_CURSOR; user_event.user.data1 = cursor; user_event.user.data2 = (void *)((size_t)visible); if (SDL_PushEvent (&user_event) < 0) { sim_printf ("%s: vid_set_cursor() SDL_PushEvent error: %s\n", vid_dev ? sim_dname(vid_dev) : "Video Device", SDL_GetError()); SDL_FreeCursor (cursor); } return SCPE_OK; } void vid_set_cursor_position (int32 x, int32 y) { int32 x_delta = vid_cursor_x - x; int32 y_delta = vid_cursor_y - y; if ((x_delta) || (y_delta)) { sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "vid_set_cursor_position(%d, %d) - Cursor position changed\n", x, y); /* Any queued mouse motion events need to have their relative positions adjusted since they were queued based on different info. */ if (SDL_SemWait (vid_mouse_events.sem) == 0) { int32 i; SIM_MOUSE_EVENT *ev; for (i=0; i<vid_mouse_events.count; i++) { ev = &vid_mouse_events.events[(vid_mouse_events.head + i)%MAX_EVENTS]; sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "Pending Mouse Motion Event Adjusted from: (%d, %d) to (%d, %d)\n", ev->x_rel, ev->y_rel, ev->x_rel + x_delta, ev->y_rel + y_delta); vid_mouse_xrel -= ev->x_rel; /* remove previously accumulated relative position */ vid_mouse_yrel -= ev->y_rel; ev->x_rel += x_delta; ev->y_rel += y_delta; vid_mouse_xrel += ev->x_rel; /* update cumulative x & y rel */ vid_mouse_yrel += ev->y_rel; } if (SDL_SemPost (vid_mouse_events.sem)) sim_printf ("%s: vid_set_cursor_position(): SDL_SemPost error: %s\n", vid_dev ? sim_dname(vid_dev) : "Video Device", SDL_GetError()); } else { sim_printf ("%s: vid_set_cursor_position(): SDL_SemWait error: %s\n", vid_dev ? sim_dname(vid_dev) : "Video Device", SDL_GetError()); } vid_cursor_x = x; vid_cursor_y = y; if (vid_cursor_visible) { SDL_Event user_event; user_event.type = SDL_USEREVENT; user_event.user.code = EVENT_WARP; user_event.user.data1 = NULL; user_event.user.data2 = NULL; if (SDL_PushEvent (&user_event) < 0) sim_printf ("%s: vid_set_cursor_position() SDL_PushEvent error: %s\n", sim_dname(vid_dev), SDL_GetError()); sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "vid_set_cursor_position() - Warp Queued\n"); } else { sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "vid_set_cursor_position() - Warp Skipped\n"); } } } void vid_refresh (void) { SDL_Event user_event; sim_debug (SIM_VID_DBG_VIDEO, vid_dev, "vid_refresh() - Queueing Refresh Event\n"); user_event.type = SDL_USEREVENT; user_event.user.code = EVENT_REDRAW; user_event.user.data1 = NULL; user_event.user.data2 = NULL; if (SDL_PushEvent (&user_event) < 0) sim_printf ("%s: vid_refresh() SDL_PushEvent error: %s\n", sim_dname(vid_dev), SDL_GetError()); } int vid_map_key (int key) { switch (key) { case SDLK_BACKSPACE: return SIM_KEY_BACKSPACE; case SDLK_TAB: return SIM_KEY_TAB; case SDLK_RETURN: return SIM_KEY_ENTER; case SDLK_ESCAPE: return SIM_KEY_ESC; case SDLK_SPACE: return SIM_KEY_SPACE; case SDLK_QUOTE: return SIM_KEY_SINGLE_QUOTE; case SDLK_COMMA: return SIM_KEY_COMMA; case SDLK_MINUS: return SIM_KEY_MINUS; case SDLK_PERIOD: return SIM_KEY_PERIOD; case SDLK_SLASH: return SIM_KEY_SLASH; case SDLK_0: return SIM_KEY_0; case SDLK_1: return SIM_KEY_1; case SDLK_2: return SIM_KEY_2; case SDLK_3: return SIM_KEY_3; case SDLK_4: return SIM_KEY_4; case SDLK_5: return SIM_KEY_5; case SDLK_6: return SIM_KEY_6; case SDLK_7: return SIM_KEY_7; case SDLK_8: return SIM_KEY_8; case SDLK_9: return SIM_KEY_9; case SDLK_SEMICOLON: return SIM_KEY_SEMICOLON; case SDLK_EQUALS: return SIM_KEY_EQUALS; case SDLK_LEFTBRACKET: return SIM_KEY_LEFT_BRACKET; case SDLK_BACKSLASH: return SIM_KEY_BACKSLASH; case SDLK_RIGHTBRACKET: return SIM_KEY_RIGHT_BRACKET; case SDLK_BACKQUOTE: return SIM_KEY_BACKQUOTE; case SDLK_a: return SIM_KEY_A; case SDLK_b: return SIM_KEY_B; case SDLK_c: return SIM_KEY_C; case SDLK_d: return SIM_KEY_D; case SDLK_e: return SIM_KEY_E; case SDLK_f: return SIM_KEY_F; case SDLK_g: return SIM_KEY_G; case SDLK_h: return SIM_KEY_H; case SDLK_i: return SIM_KEY_I; case SDLK_j: return SIM_KEY_J; case SDLK_k: return SIM_KEY_K; case SDLK_l: return SIM_KEY_L; case SDLK_m: return SIM_KEY_M; case SDLK_n: return SIM_KEY_N; case SDLK_o: return SIM_KEY_O; case SDLK_p: return SIM_KEY_P; case SDLK_q: return SIM_KEY_Q; case SDLK_r: return SIM_KEY_R; case SDLK_s: return SIM_KEY_S; case SDLK_t: return SIM_KEY_T; case SDLK_u: return SIM_KEY_U; case SDLK_v: return SIM_KEY_V; case SDLK_w: return SIM_KEY_W; case SDLK_x: return SIM_KEY_X; case SDLK_y: return SIM_KEY_Y; case SDLK_z: return SIM_KEY_Z; case SDLK_DELETE: return SIM_KEY_DELETE; #if SDL_MAJOR_VERSION == 1 case SDLK_KP0: return SIM_KEY_KP_INSERT; case SDLK_KP1: return SIM_KEY_KP_END; case SDLK_KP2: return SIM_KEY_KP_DOWN; case SDLK_KP3: return SIM_KEY_KP_PAGE_DOWN; case SDLK_KP4: return SIM_KEY_KP_LEFT; case SDLK_KP5: return SIM_KEY_KP_5; case SDLK_KP6: return SIM_KEY_KP_RIGHT; case SDLK_KP7: return SIM_KEY_KP_HOME; case SDLK_KP8: return SIM_KEY_KP_UP; case SDLK_KP9: return SIM_KEY_KP_PAGE_UP; #else case SDLK_KP_0: return SIM_KEY_KP_INSERT; case SDLK_KP_1: return SIM_KEY_KP_END; case SDLK_KP_2: return SIM_KEY_KP_DOWN; case SDLK_KP_3: return SIM_KEY_KP_PAGE_DOWN; case SDLK_KP_4: return SIM_KEY_KP_LEFT; case SDLK_KP_5: return SIM_KEY_KP_5; case SDLK_KP_6: return SIM_KEY_KP_RIGHT; case SDLK_KP_7: return SIM_KEY_KP_HOME; case SDLK_KP_8: return SIM_KEY_KP_UP; case SDLK_KP_9: return SIM_KEY_KP_PAGE_UP; #endif case SDLK_KP_PERIOD: return SIM_KEY_KP_DELETE; case SDLK_KP_DIVIDE: return SIM_KEY_KP_DIVIDE; case SDLK_KP_MULTIPLY: return SIM_KEY_KP_MULTIPLY; case SDLK_KP_MINUS: return SIM_KEY_KP_SUBTRACT; case SDLK_KP_PLUS: return SIM_KEY_KP_ADD; case SDLK_KP_ENTER: return SIM_KEY_KP_ENTER; case SDLK_UP: return SIM_KEY_UP; case SDLK_DOWN: return SIM_KEY_DOWN; case SDLK_RIGHT: return SIM_KEY_RIGHT; case SDLK_LEFT: return SIM_KEY_LEFT; case SDLK_INSERT: return SIM_KEY_INSERT; case SDLK_HOME: return SIM_KEY_HOME; case SDLK_END: return SIM_KEY_END; case SDLK_PAGEUP: return SIM_KEY_PAGE_UP; case SDLK_PAGEDOWN: return SIM_KEY_PAGE_DOWN; case SDLK_F1: return SIM_KEY_F1; case SDLK_F2: return SIM_KEY_F2; case SDLK_F3: return SIM_KEY_F3; case SDLK_F4: return SIM_KEY_F4; case SDLK_F5: return SIM_KEY_F5; case SDLK_F6: return SIM_KEY_F6; case SDLK_F7: return SIM_KEY_F7; case SDLK_F8: return SIM_KEY_F8; case SDLK_F9: return SIM_KEY_F9; case SDLK_F10: return SIM_KEY_F10; case SDLK_F11: return SIM_KEY_F11; case SDLK_F12: return SIM_KEY_F12; #if SDL_MAJOR_VERSION != 1 case SDLK_NUMLOCKCLEAR: return SIM_KEY_NUM_LOCK; #endif case SDLK_CAPSLOCK: return SIM_KEY_CAPS_LOCK; #if SDL_MAJOR_VERSION == 1 case SDLK_SCROLLOCK: return SIM_KEY_SCRL_LOCK; #else case SDLK_SCROLLLOCK: return SIM_KEY_SCRL_LOCK; #endif case SDLK_RSHIFT: return SIM_KEY_SHIFT_R; case SDLK_LSHIFT: return SIM_KEY_SHIFT_L; case SDLK_RCTRL: return SIM_KEY_CTRL_R; case SDLK_LCTRL: return SIM_KEY_CTRL_L; case SDLK_RALT: return SIM_KEY_ALT_R; case SDLK_LALT: return SIM_KEY_ALT_L; #if SDL_MAJOR_VERSION == 1 case SDLK_RMETA: return SIM_KEY_ALT_R; case SDLK_LMETA: return SIM_KEY_WIN_L; #else case SDLK_LGUI: return SIM_KEY_WIN_L; case SDLK_RGUI: return SIM_KEY_WIN_R; #endif #if SDL_MAJOR_VERSION == 1 case SDLK_PRINT: return SIM_KEY_PRINT; #else case SDLK_PRINTSCREEN: return SIM_KEY_PRINT; #endif case SDLK_PAUSE: return SIM_KEY_PAUSE; case SDLK_MENU: return SIM_KEY_MENU; default: return SIM_KEY_UNKNOWN; } } void vid_key (SDL_KeyboardEvent *event) { SIM_KEY_EVENT ev; if (vid_mouse_captured) { static const Uint8 *KeyStates = NULL; static int numkeys; if (!KeyStates) #if SDL_MAJOR_VERSION == 1 KeyStates = SDL_GetKeyState(&numkeys); if ((vid_flags & SIM_VID_INPUTCAPTURED) && (event->state == SDL_PRESSED) && KeyStates[SDLK_RSHIFT] && (KeyStates[SDLK_LCTRL] || KeyStates[SDLK_RCTRL])) { #else KeyStates = SDL_GetKeyboardState(&numkeys); if ((vid_flags & SIM_VID_INPUTCAPTURED) && (event->state == SDL_PRESSED) && KeyStates[SDL_SCANCODE_RSHIFT] && (KeyStates[SDL_SCANCODE_LCTRL] || KeyStates[SDL_SCANCODE_RCTRL])) { #endif sim_debug (SIM_VID_DBG_KEY, vid_dev, "vid_key() - Cursor Release\n"); #if SDL_MAJOR_VERSION == 1 if (SDL_WM_GrabInput (SDL_GRAB_OFF) < 0) /* relese cursor */ sim_printf ("%s: vid_key(): SDL_WM_GrabInput error: %s\n", sim_dname(vid_dev), SDL_GetError()); if (SDL_ShowCursor (SDL_ENABLE) < 0) /* show cursor */ sim_printf ("%s: vid_key(): SDL_ShowCursor error: %s\n", sim_dname(vid_dev), SDL_GetError()); #else if (SDL_SetRelativeMouseMode(SDL_FALSE) < 0) /* release cursor, show cursor */ sim_printf ("%s: vid_key(): SDL_SetRelativeMouseMode error: %s\n", sim_dname(vid_dev), SDL_GetError()); #endif vid_mouse_captured = FALSE; return; } } if (!sim_is_running) return; if (SDL_SemWait (vid_key_events.sem) == 0) { if (vid_key_events.count < MAX_EVENTS) { ev.key = vid_map_key (event->keysym.sym); sim_debug (SIM_VID_DBG_KEY, vid_dev, "Keyboard Event: State: %s, Keysym(scancode,sym): (%d,%d) - %s\n", (event->state == SDL_PRESSED) ? "PRESSED" : "RELEASED", event->keysym.scancode, event->keysym.sym, vid_key_name(ev.key)); if (event->state == SDL_PRESSED) { #if SDL_MAJOR_VERSION == 1 if (!vid_key_state[event->keysym.sym]) { /* Key was not down before */ vid_key_state[event->keysym.sym] = TRUE; #else if (!vid_key_state[event->keysym.scancode]) {/* Key was not down before */ vid_key_state[event->keysym.scancode] = TRUE; #endif ev.state = SIM_KEYPRESS_DOWN; } else ev.state = SIM_KEYPRESS_REPEAT; } else { #if SDL_MAJOR_VERSION == 1 vid_key_state[event->keysym.sym] = FALSE; #else vid_key_state[event->keysym.scancode] = FALSE; #endif ev.state = SIM_KEYPRESS_UP; } vid_key_events.events[vid_key_events.tail++] = ev; vid_key_events.count++; if (vid_key_events.tail == MAX_EVENTS) vid_key_events.tail = 0; } else { sim_debug (SIM_VID_DBG_KEY, vid_dev, "Keyboard Event DISCARDED: State: %s, Keysym: Scancode: %d, Keysym: %d\n", (event->state == SDL_PRESSED) ? "PRESSED" : "RELEASED", event->keysym.scancode, event->keysym.sym); } if (SDL_SemPost (vid_key_events.sem)) sim_printf ("%s: vid_key(): SDL_SemPost error: %s\n", sim_dname(vid_dev), SDL_GetError()); } } void vid_mouse_move (SDL_MouseMotionEvent *event) { SDL_Event dummy_event; SDL_MouseMotionEvent *dev = (SDL_MouseMotionEvent *)&dummy_event; SIM_MOUSE_EVENT ev; if ((!vid_mouse_captured) && (vid_flags & SIM_VID_INPUTCAPTURED)) return; if (!sim_is_running) return; if (!vid_cursor_visible) return; sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Move Event: pos:(%d,%d) rel:(%d,%d) buttons:(%d,%d,%d)\n", event->x, event->y, event->xrel, event->yrel, (event->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? 1 : 0); #if SDL_MAJOR_VERSION == 1 while (SDL_PeepEvents (&dummy_event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK)) { #else while (SDL_PeepEvents (&dummy_event, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION)) { #endif /* Coalesce motion activity to avoid thrashing */ event->xrel += dev->xrel; event->yrel += dev->yrel; event->x = dev->x; event->y = dev->y; event->state = dev->state; sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Move Event: Additional Event Coalesced:pos:(%d,%d) rel:(%d,%d) buttons:(%d,%d,%d)\n", dev->x, dev->y, dev->xrel, dev->yrel, (dev->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? 1 : 0, (dev->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? 1 : 0, (dev->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? 1 : 0); }; if (SDL_SemWait (vid_mouse_events.sem) == 0) { if (!vid_mouse_captured) { event->xrel = (event->x - vid_cursor_x); event->yrel = (event->y - vid_cursor_y); } vid_mouse_xrel += event->xrel; /* update cumulative x rel */ vid_mouse_yrel += event->yrel; /* update cumulative y rel */ vid_mouse_b1 = (event->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? TRUE : FALSE; vid_mouse_b2 = (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? TRUE : FALSE; vid_mouse_b3 = (event->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? TRUE : FALSE; sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Move Event: pos:(%d,%d) rel:(%d,%d) buttons:(%d,%d,%d) - Count: %d vid_mouse_rel:(%d,%d), vid_cursor:(%d,%d)\n", event->x, event->y, event->xrel, event->yrel, (event->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? 1 : 0, vid_mouse_events.count, vid_mouse_xrel, vid_mouse_yrel, vid_cursor_x, vid_cursor_y); if (vid_mouse_events.count < MAX_EVENTS) { SIM_MOUSE_EVENT *tail = &vid_mouse_events.events[(vid_mouse_events.tail+MAX_EVENTS-1)%MAX_EVENTS]; ev.x_rel = event->xrel; ev.y_rel = event->yrel; ev.b1_state = vid_mouse_b1; ev.b2_state = vid_mouse_b2; ev.b3_state = vid_mouse_b3; ev.x_pos = event->x; ev.y_pos = event->y; if ((vid_mouse_events.count > 0) && /* Is there a tail event? */ (ev.b1_state == tail->b1_state) && /* With the same button state? */ (ev.b2_state == tail->b2_state) && (ev.b3_state == tail->b3_state)) { /* Merge the motion */ tail->x_rel += ev.x_rel; tail->y_rel += ev.y_rel; tail->x_pos = ev.x_pos; tail->y_pos = ev.y_pos; sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Move Event: Coalesced into pending event: (%d,%d) vid_mouse_rel:(%d,%d)\n", tail->x_rel, tail->y_rel, vid_mouse_xrel, vid_mouse_yrel); } else { /* Add a new event */ vid_mouse_events.events[vid_mouse_events.tail++] = ev; vid_mouse_events.count++; if (vid_mouse_events.tail == MAX_EVENTS) vid_mouse_events.tail = 0; } } else { sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Move Event Discarded: Count: %d\n", vid_mouse_events.count); } if (SDL_SemPost (vid_mouse_events.sem)) sim_printf ("%s: vid_mouse_move(): SDL_SemPost error: %s\n", sim_dname(vid_dev), SDL_GetError()); } } void vid_mouse_button (SDL_MouseButtonEvent *event) { SDL_Event dummy_event; SIM_MOUSE_EVENT ev; t_bool state; if ((!vid_mouse_captured) && (vid_flags & SIM_VID_INPUTCAPTURED)) { if ((event->state == SDL_PRESSED) && (event->button == SDL_BUTTON_LEFT)) { /* left click and cursor not captured? */ sim_debug (SIM_VID_DBG_KEY, vid_dev, "vid_mouse_button() - Cursor Captured\n"); #if SDL_MAJOR_VERSION == 1 SDL_WM_GrabInput (SDL_GRAB_ON); /* lock cursor to window */ SDL_ShowCursor (SDL_DISABLE); /* hide cursor */ SDL_WarpMouse (vid_width/2, vid_height/2); /* back to center */ SDL_PumpEvents (); while (SDL_PeepEvents (&dummy_event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK)) {}; #else if (SDL_SetRelativeMouseMode (SDL_TRUE) < 0) /* lock cursor to window, hide cursor */ sim_printf ("%s: vid_mouse_button(): SDL_SetRelativeMouseMode error: %s\n", sim_dname(vid_dev), SDL_GetError()); SDL_WarpMouseInWindow (NULL, vid_width/2, vid_height/2);/* back to center */ SDL_PumpEvents (); while (SDL_PeepEvents (&dummy_event, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION)) {}; #endif vid_mouse_captured = TRUE; } return; } if (!sim_is_running) return; state = (event->state == SDL_PRESSED) ? TRUE : FALSE; if (SDL_SemWait (vid_mouse_events.sem) == 0) { switch (event->button) { case SDL_BUTTON_LEFT: vid_mouse_b1 = state; break; case SDL_BUTTON_MIDDLE: vid_mouse_b2 = state; break; case SDL_BUTTON_RIGHT: vid_mouse_b3 = state; break; } sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Button Event: State: %d, Button: %d, (%d,%d)\n", event->state, event->button, event->x, event->y); if (vid_mouse_events.count < MAX_EVENTS) { ev.x_rel = 0; ev.y_rel = 0; ev.x_pos = event->x; ev.y_pos = event->y; ev.b1_state = vid_mouse_b1; ev.b2_state = vid_mouse_b2; ev.b3_state = vid_mouse_b3; vid_mouse_events.events[vid_mouse_events.tail++] = ev; vid_mouse_events.count++; if (vid_mouse_events.tail == MAX_EVENTS) vid_mouse_events.tail = 0; } else { sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Button Event Discarded: Count: %d\n", vid_mouse_events.count); } if (SDL_SemPost (vid_mouse_events.sem)) sim_printf ("%s: Mouse Button Event: SDL_SemPost error: %s\n", sim_dname(vid_dev), SDL_GetError()); } } void vid_update (void) { SDL_Rect vid_dst; vid_dst.x = 0; vid_dst.y = 0; vid_dst.w = vid_width; vid_dst.h = vid_height; sim_debug (SIM_VID_DBG_VIDEO, vid_dev, "Video Update Event: \n"); if (sim_deb) fflush (sim_deb); #if SDL_MAJOR_VERSION == 1 if (SDL_BlitSurface (vid_image, NULL, vid_window, &vid_dst) < 0) sim_printf ("%s: vid_update(): SDL_BlitSurface error: %s\n", sim_dname(vid_dev), SDL_GetError()); SDL_UpdateRects (vid_window, 1, &vid_dst); #else if (SDL_RenderClear (vid_renderer)) sim_printf ("%s: Video Update Event: SDL_RenderClear error: %s\n", sim_dname(vid_dev), SDL_GetError()); if (SDL_RenderCopy (vid_renderer, vid_texture, NULL, NULL)) sim_printf ("%s: Video Update Event: SDL_RenderCopy error: %s\n", sim_dname(vid_dev), SDL_GetError()); SDL_RenderPresent (vid_renderer); #endif } void vid_update_cursor (SDL_Cursor *cursor, t_bool visible) { if (!cursor) return; sim_debug (SIM_VID_DBG_VIDEO, vid_dev, "Cursor Update Event: Previously %s, Now %s, New Cursor object at: %p, Old Cursor object at: %p\n", SDL_ShowCursor(-1) ? "visible" : "invisible", visible ? "visible" : "invisible", cursor, vid_cursor); SDL_SetCursor (cursor); #if SDL_MAJOR_VERSION == 1 if (visible) SDL_WarpMouse (vid_cursor_x, vid_cursor_y);/* sync position */ #else if ((vid_window == SDL_GetMouseFocus ()) && visible) SDL_WarpMouseInWindow (NULL, vid_cursor_x, vid_cursor_y);/* sync position */ #endif if ((vid_cursor != cursor) && (vid_cursor)) SDL_FreeCursor (vid_cursor); vid_cursor = cursor; SDL_ShowCursor (visible); vid_cursor_visible = visible; } void vid_warp_position (void) { sim_debug (SIM_VID_DBG_VIDEO, vid_dev, "Mouse Warp Event: Warp to: (%d,%d)\n", vid_cursor_x, vid_cursor_y); SDL_PumpEvents (); #if SDL_MAJOR_VERSION == 1 SDL_WarpMouse (vid_cursor_x, vid_cursor_y); #else SDL_WarpMouseInWindow (NULL, vid_cursor_x, vid_cursor_y); #endif SDL_PumpEvents (); } void vid_draw_region (SDL_UserEvent *event) { SDL_Rect *vid_dst = (SDL_Rect *)event->data1; uint32 *buf = (uint32 *)event->data2; sim_debug (SIM_VID_DBG_VIDEO, vid_dev, "Draw Region Event: (%d,%d,%d,%d)\n", vid_dst->x, vid_dst->x, vid_dst->w, vid_dst->h); #if SDL_MAJOR_VERSION == 1 if (1) { int32 i; uint32* pixels; pixels = (uint32 *)vid_image->pixels; for (i = 0; i < vid_dst->h; i++) memcpy (pixels + ((i + vid_dst->y) * vid_width) + vid_dst->x, buf + vid_dst->w*i, vid_dst->w*sizeof(*pixels)); } #else if (SDL_UpdateTexture(vid_texture, vid_dst, buf, vid_dst->w*sizeof(*buf))) sim_printf ("%s: vid_draw() - SDL_UpdateTexture error: %s\n", sim_dname(vid_dev), SDL_GetError()); #endif free (vid_dst); free (buf); event->data1 = NULL; } int vid_video_events (void) { SDL_Event event; #if SDL_MAJOR_VERSION == 1 static const char *eventtypes[] = { "NOEVENT", /**< Unused (do not remove) */ "ACTIVEEVENT", /**< Application loses/gains visibility */ "KEYDOWN", /**< Keys pressed */ "KEYUP", /**< Keys released */ "MOUSEMOTION", /**< Mouse moved */ "MOUSEBUTTONDOWN", /**< Mouse button pressed */ "MOUSEBUTTONUP", /**< Mouse button released */ "JOYAXISMOTION", /**< Joystick axis motion */ "JOYBALLMOTION", /**< Joystick trackball motion */ "JOYHATMOTION", /**< Joystick hat position change */ "JOYBUTTONDOWN", /**< Joystick button pressed */ "JOYBUTTONUP", /**< Joystick button released */ "QUIT", /**< User-requested quit */ "SYSWMEVENT", /**< System specific event */ "EVENT_RESERVEDA", /**< Reserved for future use.. */ "EVENT_RESERVEDB", /**< Reserved for future use.. */ "VIDEORESIZE", /**< User resized video mode */ "VIDEOEXPOSE", /**< Screen needs to be redrawn */ "EVENT_RESERVED2", /**< Reserved for future use.. */ "EVENT_RESERVED3", /**< Reserved for future use.. */ "EVENT_RESERVED4", /**< Reserved for future use.. */ "EVENT_RESERVED5", /**< Reserved for future use.. */ "EVENT_RESERVED6", /**< Reserved for future use.. */ "EVENT_RESERVED7", /**< Reserved for future use.. */ "USEREVENT", /** Events SDL_USEREVENT(24) through SDL_MAXEVENTS-1(31) are for your use */ "", "", "", "", "", "", "" }; #else static const char *eventtypes[SDL_LASTEVENT]; #endif static const char *windoweventtypes[256]; static t_bool initialized = FALSE; if (!initialized) { initialized = TRUE; #if SDL_MAJOR_VERSION != 1 eventtypes[SDL_QUIT] = "QUIT"; /**< User-requested quit */ /* These application events have special meaning on iOS, see README-ios.txt for details */ eventtypes[SDL_APP_TERMINATING] = "APP_TERMINATING"; /**< The application is being terminated by the OS Called on iOS in applicationWillTerminate() Called on Android in onDestroy() */ eventtypes[SDL_APP_LOWMEMORY] = "APP_LOWMEMORY"; /**< The application is low on memory, free memory if possible. Called on iOS in applicationDidReceiveMemoryWarning() Called on Android in onLowMemory() */ eventtypes[SDL_APP_WILLENTERBACKGROUND] = "APP_WILLENTERBACKGROUND"; /**< The application is about to enter the background Called on iOS in applicationWillResignActive() Called on Android in onPause() */ eventtypes[SDL_APP_DIDENTERBACKGROUND] = "APP_DIDENTERBACKGROUND"; /**< The application did enter the background and may not get CPU for some time Called on iOS in applicationDidEnterBackground() Called on Android in onPause() */ eventtypes[SDL_APP_WILLENTERFOREGROUND] = "APP_WILLENTERFOREGROUND"; /**< The application is about to enter the foreground Called on iOS in applicationWillEnterForeground() Called on Android in onResume() */ eventtypes[SDL_APP_DIDENTERFOREGROUND] = "APP_DIDENTERFOREGROUND"; /**< The application is now interactive Called on iOS in applicationDidBecomeActive() Called on Android in onResume() */ /* Window events */ eventtypes[SDL_WINDOWEVENT] = "WINDOWEVENT"; /**< Window state change */ eventtypes[SDL_SYSWMEVENT] = "SYSWMEVENT"; /**< System specific event */ windoweventtypes[SDL_WINDOWEVENT_NONE] = "NONE"; /**< Never used */ windoweventtypes[SDL_WINDOWEVENT_SHOWN] = "SHOWN"; /**< Window has been shown */ windoweventtypes[SDL_WINDOWEVENT_HIDDEN] = "HIDDEN"; /**< Window has been hidden */ windoweventtypes[SDL_WINDOWEVENT_EXPOSED] = "EXPOSED"; /**< Window has been exposed and should be redrawn */ windoweventtypes[SDL_WINDOWEVENT_MOVED] = "MOVED"; /**< Window has been moved to data1, data2 */ windoweventtypes[SDL_WINDOWEVENT_RESIZED] = "RESIZED"; /**< Window has been resized to data1xdata2 */ windoweventtypes[SDL_WINDOWEVENT_SIZE_CHANGED] = "SIZE_CHANGED";/**< The window size has changed, either as a result of an API call or through the system or user changing the window size. */ windoweventtypes[SDL_WINDOWEVENT_MINIMIZED] = "MINIMIZED"; /**< Window has been minimized */ windoweventtypes[SDL_WINDOWEVENT_MAXIMIZED] = "MAXIMIZED"; /**< Window has been maximized */ windoweventtypes[SDL_WINDOWEVENT_RESTORED] = "RESTORED"; /**< Window has been restored to normal size and position */ windoweventtypes[SDL_WINDOWEVENT_ENTER] = "ENTER"; /**< Window has gained mouse focus */ windoweventtypes[SDL_WINDOWEVENT_LEAVE] = "LEAVE"; /**< Window has lost mouse focus */ windoweventtypes[SDL_WINDOWEVENT_FOCUS_GAINED] = "FOCUS_GAINED";/**< Window has gained keyboard focus */ windoweventtypes[SDL_WINDOWEVENT_FOCUS_LOST] = "FOCUS_LOST"; /**< Window has lost keyboard focus */ windoweventtypes[SDL_WINDOWEVENT_CLOSE] = "CLOSE"; /**< The window manager requests that the window be closed */ /* Keyboard events */ eventtypes[SDL_KEYDOWN] = "KEYDOWN"; /**< Key pressed */ eventtypes[SDL_KEYUP] = "KEYUP"; /**< Key released */ eventtypes[SDL_TEXTEDITING] = "TEXTEDITING"; /**< Keyboard text editing (composition) */ eventtypes[SDL_TEXTINPUT] = "TEXTINPUT"; /**< Keyboard text input */ /* Mouse events */ eventtypes[SDL_MOUSEMOTION] = "MOUSEMOTION"; /**< Mouse moved */ eventtypes[SDL_MOUSEBUTTONDOWN] = "MOUSEBUTTONDOWN"; /**< Mouse button pressed */ eventtypes[SDL_MOUSEBUTTONUP] = "MOUSEBUTTONUP"; /**< Mouse button released */ eventtypes[SDL_MOUSEWHEEL] = "MOUSEWHEEL"; /**< Mouse wheel motion */ /* Joystick events */ eventtypes[SDL_JOYAXISMOTION] = "JOYAXISMOTION"; /**< Joystick axis motion */ eventtypes[SDL_JOYBALLMOTION] = "JOYBALLMOTION"; /**< Joystick trackball motion */ eventtypes[SDL_JOYHATMOTION] = "JOYHATMOTION"; /**< Joystick hat position change */ eventtypes[SDL_JOYBUTTONDOWN] = "JOYBUTTONDOWN"; /**< Joystick button pressed */ eventtypes[SDL_JOYBUTTONUP] = "JOYBUTTONUP"; /**< Joystick button released */ eventtypes[SDL_JOYDEVICEADDED] = "JOYDEVICEADDED"; /**< A new joystick has been inserted into the system */ eventtypes[SDL_JOYDEVICEREMOVED] = "JOYDEVICEREMOVED"; /**< An opened joystick has been removed */ /* Game controller events */ eventtypes[SDL_CONTROLLERAXISMOTION] = "CONTROLLERAXISMOTION"; /**< Game controller axis motion */ eventtypes[SDL_CONTROLLERBUTTONDOWN] = "CONTROLLERBUTTONDOWN"; /**< Game controller button pressed */ eventtypes[SDL_CONTROLLERBUTTONUP] = "CONTROLLERBUTTONUP"; /**< Game controller button released */ eventtypes[SDL_CONTROLLERDEVICEADDED] = "CONTROLLERDEVICEADDED"; /**< A new Game controller has been inserted into the system */ eventtypes[SDL_CONTROLLERDEVICEREMOVED] = "CONTROLLERDEVICEREMOVED"; /**< An opened Game controller has been removed */ eventtypes[SDL_CONTROLLERDEVICEREMAPPED] = "CONTROLLERDEVICEREMAPPED"; /**< The controller mapping was updated */ /* Touch events */ eventtypes[SDL_FINGERDOWN] = "FINGERDOWN"; eventtypes[SDL_FINGERUP] = "FINGERUP"; eventtypes[SDL_FINGERMOTION] = "FINGERMOTION"; /* Gesture events */ eventtypes[SDL_DOLLARGESTURE] = "DOLLARGESTURE"; eventtypes[SDL_DOLLARRECORD] = "DOLLARRECORD"; eventtypes[SDL_MULTIGESTURE] = "MULTIGESTURE"; /* Clipboard events */ eventtypes[SDL_CLIPBOARDUPDATE] = "CLIPBOARDUPDATE"; /**< The clipboard changed */ /* Drag and drop events */ eventtypes[SDL_DROPFILE] = "DROPFILE"; /**< The system requests a file open */ #if (SDL_MINOR_VERSION > 0) || (SDL_PATCHLEVEL >= 3) /* Render events */ eventtypes[SDL_RENDER_TARGETS_RESET] = "RENDER_TARGETS_RESET"; /**< The render targets have been reset */ #endif #if (SDL_MINOR_VERSION > 0) || (SDL_PATCHLEVEL >= 4) /* Render events */ eventtypes[SDL_RENDER_DEVICE_RESET] = "RENDER_DEVICE_RESET"; /**< The render device has been reset */ #endif /** Events ::SDL_USEREVENT through ::SDL_LASTEVENT are for your use, * and should be allocated with SDL_RegisterEvents() */ eventtypes[SDL_USEREVENT] = "USEREVENT"; #endif /* SDL_MAJOR_VERSION != 1 */ } sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_thread() - Starting\n"); vid_mono_palette[0] = sim_end ? 0xFF000000 : 0x000000FF; /* Black */ vid_mono_palette[1] = 0xFFFFFFFF; /* White */ memset (&vid_key_state, 0, sizeof(vid_key_state)); #if SDL_MAJOR_VERSION == 1 vid_window = SDL_SetVideoMode (vid_width, vid_height, 8, 0); SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); if (sim_end) vid_image = SDL_CreateRGBSurface (SDL_SWSURFACE, vid_width, vid_height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); else vid_image = SDL_CreateRGBSurface (SDL_SWSURFACE, vid_width, vid_height, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); #else SDL_CreateWindowAndRenderer (vid_width, vid_height, SDL_WINDOW_SHOWN, &vid_window, &vid_renderer); if ((vid_window == NULL) || (vid_renderer == NULL)) { sim_printf ("%s: Error Creating Video Window: %s\n", sim_dname(vid_dev), SDL_GetError()); SDL_Quit (); return 0; } SDL_SetRenderDrawColor (vid_renderer, 0, 0, 0, 255); SDL_RenderClear (vid_renderer); SDL_RenderPresent (vid_renderer); vid_texture = SDL_CreateTexture (vid_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, vid_width, vid_height); if (!vid_texture) { sim_printf ("%s: Error configuring Video environment: %s\n", sim_dname(vid_dev), SDL_GetError()); SDL_DestroyRenderer(vid_renderer); vid_renderer = NULL; SDL_DestroyWindow(vid_window); vid_window = NULL; SDL_Quit (); return 0; } SDL_StopTextInput (); vid_windowID = SDL_GetWindowID (vid_window); #endif if (vid_flags & SIM_VID_INPUTCAPTURED) { char title[150]; memset (title, 0, sizeof(title)); strncpy (title, vid_title, sizeof(title)-1); strncat (title, " ReleaseKey=", sizeof(title)-(1+strlen(title))); strncat (title, vid_release_key, sizeof(title)-(1+strlen(title))); #if SDL_MAJOR_VERSION == 1 SDL_WM_SetCaption (title, title); #else SDL_SetWindowTitle (vid_window, title); #endif } else #if SDL_MAJOR_VERSION == 1 SDL_WM_SetCaption (vid_title, sim_name); #else SDL_SetWindowTitle (vid_window, vid_title); #endif vid_ready = TRUE; sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE|SIM_VID_DBG_CURSOR, vid_dev, "vid_thread() - Started\n"); while (vid_active) { int status = SDL_WaitEvent (&event); if (status == 1) { switch (event.type) { case SDL_KEYDOWN: case SDL_KEYUP: vid_key ((SDL_KeyboardEvent*)&event); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: vid_mouse_button ((SDL_MouseButtonEvent*)&event); break; case SDL_MOUSEMOTION: vid_mouse_move ((SDL_MouseMotionEvent*)&event); break; #if SDL_MAJOR_VERSION != 1 case SDL_WINDOWEVENT: if (event.window.windowID == vid_windowID) { sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE|SIM_VID_DBG_CURSOR, vid_dev, "vid_thread() - Window Event: %d - %s\n", event.window.event, windoweventtypes[event.window.event]); switch (event.window.event) { case SDL_WINDOWEVENT_ENTER: if (vid_flags & SIM_VID_INPUTCAPTURED) SDL_WarpMouseInWindow (NULL, vid_width/2, vid_height/2); /* center position */ break; } } break; #endif case SDL_USEREVENT: /* There are 6 user events generated */ /* EVENT_REDRAW to update the display */ /* EVENT_DRAW to update a region in the display texture */ /* EVENT_SHOW to display the current SDL video capabilities */ /* EVENT_CURSOR to change the current cursor */ /* EVENT_WARP to warp the cursor position */ /* EVENT_CLOSE to wake up this thread and let */ /* it notice vid_active has changed */ while (vid_active && event.user.code) { if (event.user.code == EVENT_REDRAW) { vid_update (); event.user.code = 0; /* Mark as done */ #if SDL_MAJOR_VERSION == 1 if (0) while (SDL_PeepEvents (&event, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_USEREVENT))) { #else if (0) while (SDL_PeepEvents (&event, 1, SDL_GETEVENT, SDL_USEREVENT, SDL_USEREVENT)) { #endif if (event.user.code == EVENT_REDRAW) { /* Only do a single video update between waiting for events */ sim_debug (SIM_VID_DBG_VIDEO, vid_dev, "vid_thread() - Ignored extra REDRAW Event\n"); event.user.code = 0; /* Mark as done */ continue; } break; } } if (event.user.code == EVENT_CURSOR) { vid_update_cursor ((SDL_Cursor *)(event.user.data1), (t_bool)((size_t)event.user.data2)); event.user.data1 = NULL; event.user.code = 0; /* Mark as done */ } if (event.user.code == EVENT_WARP) { vid_warp_position (); event.user.code = 0; /* Mark as done */ } if (event.user.code == EVENT_CLOSE) { event.user.code = 0; /* Mark as done */ } if (event.user.code == EVENT_DRAW) { vid_draw_region ((SDL_UserEvent*)&event); event.user.code = 0; /* Mark as done */ } if (event.user.code == EVENT_SHOW) { vid_show_video_event (); event.user.code = 0; /* Mark as done */ } if (event.user.code == EVENT_SCREENSHOT) { vid_screenshot_event (); event.user.code = 0; /* Mark as done */ } if (event.user.code == EVENT_BEEP) { vid_beep_event (); event.user.code = 0; /* Mark as done */ } if (event.user.code != 0) { sim_printf ("vid_thread(): Unexpected user event code: %d\n", event.user.code); } } break; case SDL_QUIT: sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE|SIM_VID_DBG_CURSOR, vid_dev, "vid_thread() - QUIT Event - %s\n", vid_quit_callback ? "Signaled" : "Ignored"); if (vid_quit_callback) vid_quit_callback (); break; default: sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE|SIM_VID_DBG_CURSOR, vid_dev, "vid_thread() - Ignored Event: Type: %s(%d)\n", eventtypes[event.type], event.type); break; } } else { if (status < 0) sim_printf ("%s: vid_thread() - SDL_WaitEvent error: %s\n", sim_dname(vid_dev), SDL_GetError()); } } vid_ready = FALSE; if (vid_cursor) { SDL_FreeCursor (vid_cursor); vid_cursor = NULL; } #if SDL_MAJOR_VERSION != 1 SDL_DestroyTexture(vid_texture); vid_texture = NULL; SDL_DestroyRenderer(vid_renderer); vid_renderer = NULL; SDL_DestroyWindow(vid_window); #endif /* SDL_MAJOR_VERSION != 1 */ vid_window = NULL; sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE|SIM_VID_DBG_CURSOR, vid_dev, "vid_thread() - Exiting\n"); return 0; } int vid_thread (void *arg) { #if SDL_MAJOR_VERSION == 1 _XInitThreads(); SDL_Init (SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE); #else SDL_SetHint (SDL_HINT_RENDER_DRIVER, "software"); SDL_Init (SDL_INIT_VIDEO); #endif vid_beep_setup (400, 660); vid_video_events (); vid_beep_cleanup (); SDL_Quit (); return 0; } const char *vid_version(void) { static char SDLVersion[80]; SDL_version compiled, running; #if SDL_MAJOR_VERSION == 1 const SDL_version *ver = SDL_Linked_Version(); running.major = ver->major; running.minor = ver->minor; running.patch = ver->patch; #else SDL_GetVersion(&running); #endif SDL_VERSION(&compiled); if ((compiled.major == running.major) && (compiled.minor == running.minor) && (compiled.patch == running.patch)) sprintf(SDLVersion, "SDL Version %d.%d.%d", compiled.major, compiled.minor, compiled.patch); else sprintf(SDLVersion, "SDL Version (Compiled: %d.%d.%d, Runtime: %d.%d.%d)", compiled.major, compiled.minor, compiled.patch, running.major, running.minor, running.patch); return (const char *)SDLVersion; } t_stat vid_set_release_key (FILE* st, UNIT* uptr, int32 val, CONST void* desc) { return SCPE_NOFNC; } t_stat vid_show_release_key (FILE* st, UNIT* uptr, int32 val, CONST void* desc) { if (vid_flags & SIM_VID_INPUTCAPTURED) fprintf (st, "ReleaseKey=%s", vid_release_key); return SCPE_OK; } static t_stat _vid_show_video (FILE* st, UNIT* uptr, int32 val, CONST void* desc) { int i; fprintf (st, "Video support using SDL: %s\n", vid_version()); #if defined (SDL_MAIN_AVAILABLE) fprintf (st, " SDL Events being processed on the main process thread\n"); #endif if (!vid_active) { #if !defined (SDL_MAIN_AVAILABLE) SDL_Init(SDL_INIT_VIDEO); #endif } else { fprintf (st, " Currently Active Video Window: (%d by %d pixels)\n", vid_width, vid_height); fprintf (st, " "); vid_show_release_key (st, uptr, val, desc); fprintf (st, "\n"); #if SDL_MAJOR_VERSION != 1 fprintf (st, " SDL Video Driver: %s\n", SDL_GetCurrentVideoDriver()); #endif } #if SDL_MAJOR_VERSION == 1 if (1) { char driver_name[64]; const SDL_VideoInfo *info = SDL_GetVideoInfo(); fprintf (st, " Video Driver: %s\n", SDL_VideoDriverName(driver_name, sizeof(driver_name))); fprintf (st, " hardware surfaces available: %s\n", info->hw_available ? "Yes" : "No"); fprintf (st, " window manager available: %s\n", info->wm_available ? "Yes" : "No"); fprintf (st, " hardware to hardware blits accelerated: %s\n", info->blit_hw ? "Yes" : "No"); fprintf (st, " hardware to hardware colorkey blits accelerated: %s\n", info->blit_hw_CC ? "Yes" : "No"); fprintf (st, " hardware to hardware alpha blits accelerated: %s\n", info->blit_hw_A ? "Yes" : "No"); fprintf (st, " software to hardware blits accelerated: %s\n", info->blit_sw ? "Yes" : "No"); fprintf (st, " software to hardware colorkey blits accelerated: %s\n", info->blit_sw_CC ? "Yes" : "No"); fprintf (st, " software to hardware alpha blits accelerated: %s\n", info->blit_sw_A ? "Yes" : "No"); fprintf (st, " color fills accelerated: %s\n", info->blit_fill ? "Yes" : "No"); fprintf (st, " Video Memory: %dKb\n", info->video_mem); } #else for (i = 0; i < SDL_GetNumVideoDisplays(); ++i) { SDL_DisplayMode display; if (SDL_GetCurrentDisplayMode(i, &display)) { fprintf (st, "Could not get display mode for video display #%d: %s", i, SDL_GetError()); } else { fprintf (st, " Display %s(#%d): current display mode is %dx%dpx @ %dhz. \n", SDL_GetDisplayName(i), i, display.w, display.h, display.refresh_rate); } } fprintf (st, " Available SDL Renderers:\n"); for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) { SDL_RendererInfo info; if (SDL_GetRenderDriverInfo (i, &info)) { fprintf (st, "Could not get render driver info for driver #%d: %s", i, SDL_GetError()); } else { uint32 j, k; static struct {uint32 format; const char *name;} PixelFormats[] = { {SDL_PIXELFORMAT_INDEX1LSB, "Index1LSB"}, {SDL_PIXELFORMAT_INDEX1MSB, "Index1MSB"}, {SDL_PIXELFORMAT_INDEX4LSB, "Index4LSB"}, {SDL_PIXELFORMAT_INDEX4MSB, "Index4MSB"}, {SDL_PIXELFORMAT_INDEX8, "Index8"}, {SDL_PIXELFORMAT_RGB332, "RGB332"}, {SDL_PIXELFORMAT_RGB444, "RGB444"}, {SDL_PIXELFORMAT_RGB555, "RGB555"}, {SDL_PIXELFORMAT_BGR555, "BGR555"}, {SDL_PIXELFORMAT_ARGB4444, "ARGB4444"}, {SDL_PIXELFORMAT_RGBA4444, "RGBA4444"}, {SDL_PIXELFORMAT_ABGR4444, "ABGR4444"}, {SDL_PIXELFORMAT_BGRA4444, "BGRA4444"}, {SDL_PIXELFORMAT_ARGB1555, "ARGB1555"}, {SDL_PIXELFORMAT_RGBA5551, "RGBA5551"}, {SDL_PIXELFORMAT_ABGR1555, "ABGR1555"}, {SDL_PIXELFORMAT_BGRA5551, "BGRA5551"}, {SDL_PIXELFORMAT_RGB565, "RGB565"}, {SDL_PIXELFORMAT_BGR565, "BGR565"}, {SDL_PIXELFORMAT_RGB24, "RGB24"}, {SDL_PIXELFORMAT_BGR24, "BGR24"}, {SDL_PIXELFORMAT_RGB888, "RGB888"}, {SDL_PIXELFORMAT_RGBX8888, "RGBX8888"}, {SDL_PIXELFORMAT_BGR888, "BGR888"}, {SDL_PIXELFORMAT_BGRX8888, "BGRX8888"}, {SDL_PIXELFORMAT_ARGB8888, "ARGB8888"}, {SDL_PIXELFORMAT_RGBA8888, "RGBA8888"}, {SDL_PIXELFORMAT_ABGR8888, "ABGR8888"}, {SDL_PIXELFORMAT_BGRA8888, "BGRA8888"}, {SDL_PIXELFORMAT_ARGB2101010, "ARGB2101010"}, {SDL_PIXELFORMAT_YV12, "YV12"}, {SDL_PIXELFORMAT_IYUV, "IYUV"}, {SDL_PIXELFORMAT_YUY2, "YUY2"}, {SDL_PIXELFORMAT_UYVY, "UYVY"}, {SDL_PIXELFORMAT_YVYU, "YVYU"}, {SDL_PIXELFORMAT_UNKNOWN, "Unknown"}}; fprintf (st, " Render #%d - %s\n", i, info.name); fprintf (st, " Flags: 0x%X - ", info.flags); if (info.flags & SDL_RENDERER_SOFTWARE) fprintf (st, "Software|"); if (info.flags & SDL_RENDERER_ACCELERATED) fprintf (st, "Accelerated|"); if (info.flags & SDL_RENDERER_PRESENTVSYNC) fprintf (st, "PresentVSync|"); if (info.flags & SDL_RENDERER_TARGETTEXTURE) fprintf (st, "TargetTexture|"); fprintf (st, "\n"); if ((info.max_texture_height != 0) || (info.max_texture_width != 0)) fprintf (st, " Max Texture: %d by %d\n", info.max_texture_height, info.max_texture_width); fprintf (st, " Pixel Formats:\n"); for (j=0; j<info.num_texture_formats; j++) { for (k=0; 1; k++) { if (PixelFormats[k].format == info.texture_formats[j]) { fprintf (st, " %s\n", PixelFormats[k].name); break; } if (PixelFormats[k].format == SDL_PIXELFORMAT_UNKNOWN) { fprintf (st, " %s - 0x%X\n", PixelFormats[k].name, info.texture_formats[j]); break; } } } } } if (vid_active) { SDL_RendererInfo info; SDL_GetRendererInfo (vid_renderer, &info); fprintf (st, " Currently Active Renderer: %s\n", info.name); } if (1) { static const char *hints[] = { #if defined (SDL_HINT_FRAMEBUFFER_ACCELERATION) SDL_HINT_FRAMEBUFFER_ACCELERATION , #endif #if defined (SDL_HINT_RENDER_DRIVER) SDL_HINT_RENDER_DRIVER , #endif #if defined (SDL_HINT_RENDER_OPENGL_SHADERS) SDL_HINT_RENDER_OPENGL_SHADERS , #endif #if defined (SDL_HINT_RENDER_DIRECT3D_THREADSAFE) SDL_HINT_RENDER_DIRECT3D_THREADSAFE , #endif #if defined (SDL_HINT_RENDER_DIRECT3D11_DEBUG) SDL_HINT_RENDER_DIRECT3D11_DEBUG , #endif #if defined (SDL_HINT_RENDER_SCALE_QUALITY) SDL_HINT_RENDER_SCALE_QUALITY , #endif #if defined (SDL_HINT_RENDER_VSYNC) SDL_HINT_RENDER_VSYNC , #endif #if defined (SDL_HINT_VIDEO_ALLOW_SCREENSAVER) SDL_HINT_VIDEO_ALLOW_SCREENSAVER , #endif #if defined (SDL_HINT_VIDEO_X11_XVIDMODE) SDL_HINT_VIDEO_X11_XVIDMODE , #endif #if defined (SDL_HINT_VIDEO_X11_XINERAMA) SDL_HINT_VIDEO_X11_XINERAMA , #endif #if defined (SDL_HINT_VIDEO_X11_XRANDR) SDL_HINT_VIDEO_X11_XRANDR , #endif #if defined (SDL_HINT_GRAB_KEYBOARD) SDL_HINT_GRAB_KEYBOARD , #endif #if defined (SDL_HINT_MOUSE_RELATIVE_MODE_WARP) SDL_HINT_MOUSE_RELATIVE_MODE_WARP , #endif #if defined (SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS) SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS , #endif #if defined (SDL_HINT_IDLE_TIMER_DISABLED) SDL_HINT_IDLE_TIMER_DISABLED , #endif #if defined (SDL_HINT_ORIENTATIONS) SDL_HINT_ORIENTATIONS , #endif #if defined (SDL_HINT_ACCELEROMETER_AS_JOYSTICK) SDL_HINT_ACCELEROMETER_AS_JOYSTICK , #endif #if defined (SDL_HINT_XINPUT_ENABLED) SDL_HINT_XINPUT_ENABLED , #endif #if defined (SDL_HINT_GAMECONTROLLERCONFIG) SDL_HINT_GAMECONTROLLERCONFIG , #endif #if defined (SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS) SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS , #endif #if defined (SDL_HINT_ALLOW_TOPMOST) SDL_HINT_ALLOW_TOPMOST , #endif #if defined (SDL_HINT_TIMER_RESOLUTION) SDL_HINT_TIMER_RESOLUTION , #endif #if defined (SDL_HINT_VIDEO_HIGHDPI_DISABLED) SDL_HINT_VIDEO_HIGHDPI_DISABLED , #endif #if defined (SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK) SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK , #endif #if defined (SDL_HINT_VIDEO_WIN_D3DCOMPILER) SDL_HINT_VIDEO_WIN_D3DCOMPILER , #endif #if defined (SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT) SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT , #endif #if defined (SDL_HINT_WINRT_PRIVACY_POLICY_URL) SDL_HINT_WINRT_PRIVACY_POLICY_URL , #endif #if defined (SDL_HINT_WINRT_PRIVACY_POLICY_LABEL) SDL_HINT_WINRT_PRIVACY_POLICY_LABEL , #endif #if defined (SDL_HINT_WINRT_HANDLE_BACK_BUTTON) SDL_HINT_WINRT_HANDLE_BACK_BUTTON , #endif #if defined (SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES) SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, #endif NULL}; fprintf (st, " Currently Active SDL Hints:\n"); for (i=0; hints[i]; i++) { if (SDL_GetHint (hints[i])) fprintf (st, " %s = %s\n", hints[i], SDL_GetHint (hints[i])); } } #endif /* SDL_MAJOR_VERSION != 1 */ #if !defined (SDL_MAIN_AVAILABLE) if (!vid_active) SDL_Quit(); #endif return SCPE_OK; } static t_stat _show_stat; static FILE *_show_st; static UNIT *_show_uptr; static int32 _show_val; static CONST void *_show_desc; void vid_show_video_event (void) { _show_stat = _vid_show_video (_show_st, _show_uptr, _show_val, _show_desc); } t_stat vid_show_video (FILE* st, UNIT* uptr, int32 val, CONST void* desc) { SDL_Event user_event; _show_stat = -1; _show_st = st; _show_uptr = uptr; _show_val = val; _show_desc = desc; user_event.type = SDL_USEREVENT; user_event.user.code = EVENT_SHOW; user_event.user.data1 = NULL; user_event.user.data2 = NULL; #if defined (SDL_MAIN_AVAILABLE) while (SDL_PushEvent (&user_event) < 0) sim_os_ms_sleep (10); #else vid_show_video_event (); #endif while (_show_stat == -1) SDL_Delay (20); return _show_stat; } static t_stat _vid_screenshot (const char *filename) { int stat; char *fullname = NULL; if (!vid_active) { sim_printf ("No video display is active\n"); return SCPE_UDIS | SCPE_NOMESSAGE; } fullname = (char *)malloc (strlen(filename) + 5); if (!filename) return SCPE_MEM; #if SDL_MAJOR_VERSION == 1 #if defined(HAVE_LIBPNG) if (!match_ext (filename, "bmp")) { sprintf (fullname, "%s%s", filename, match_ext (filename, "png") ? "" : ".png"); stat = SDL_SavePNG(vid_image, fullname); } else { sprintf (fullname, "%s", filename); stat = SDL_SaveBMP(vid_image, fullname); } #else sprintf (fullname, "%s%s", filename, match_ext (filename, "bmp") ? "" : ".bmp"); stat = SDL_SaveBMP(vid_image, fullname); #endif /* defined(HAVE_LIBPNG) */ #else /* SDL_MAJOR_VERSION != 1 */ if (1) { SDL_Surface *sshot = sim_end ? SDL_CreateRGBSurface(0, vid_width, vid_height, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000) : SDL_CreateRGBSurface(0, vid_width, vid_height, 32, 0x0000ff00, 0x000ff000, 0xff000000, 0x000000ff) ; SDL_RenderReadPixels(vid_renderer, NULL, SDL_PIXELFORMAT_ARGB8888, sshot->pixels, sshot->pitch); #if defined(HAVE_LIBPNG) if (!match_ext (filename, "bmp")) { sprintf (fullname, "%s%s", filename, match_ext (filename, "png") ? "" : ".png"); stat = SDL_SavePNG(sshot, fullname); } else { sprintf (fullname, "%s", filename); stat = SDL_SaveBMP(sshot, fullname); } #else sprintf (fullname, "%s%s", filename, match_ext (filename, "bmp") ? "" : ".bmp"); stat = SDL_SaveBMP(sshot, fullname); #endif /* defined(HAVE_LIBPNG) */ SDL_FreeSurface(sshot); } #endif if (stat) { sim_printf ("Error saving screenshot to %s: %s\n", fullname, SDL_GetError()); free (fullname); return SCPE_IOERR | SCPE_NOMESSAGE; } else { if (!sim_quiet) sim_printf ("Screenshot saved to %s\n", fullname); free (fullname); return SCPE_OK; } } static t_stat _screenshot_stat; static const char *_screenshot_filename; void vid_screenshot_event (void) { _screenshot_stat = _vid_screenshot (_screenshot_filename); } t_stat vid_screenshot (const char *filename) { SDL_Event user_event; _screenshot_stat = -1; _screenshot_filename = filename; user_event.type = SDL_USEREVENT; user_event.user.code = EVENT_SCREENSHOT; user_event.user.data1 = NULL; user_event.user.data2 = NULL; #if defined (SDL_MAIN_AVAILABLE) while (SDL_PushEvent (&user_event) < 0) sim_os_ms_sleep (10); #else vid_screenshot_event (); #endif while (_screenshot_stat == -1) SDL_Delay (20); return _screenshot_stat; } #include <SDL_audio.h> #include <math.h> const int AMPLITUDE = 20000; const int SAMPLE_FREQUENCY = 11025; static int16 *vid_beep_data; static int vid_beep_offset; static int vid_beep_duration; static int vid_beep_samples; static void vid_audio_callback(void *ctx, Uint8 *stream, int length) { int16 *data = (int16 *)stream; int i, sum, remnant = ((vid_beep_samples - vid_beep_offset) * sizeof (*vid_beep_data)); if (length > remnant) { memset (stream + remnant, 0, length - remnant); length = remnant; if (remnant == 0) { SDL_PauseAudio(1); return; } } memcpy (stream, &vid_beep_data[vid_beep_offset], length); for (i=sum=0; i<length; i++) sum += stream[i]; vid_beep_offset += length / sizeof(*vid_beep_data); } static void vid_beep_setup (int duration_ms, int tone_frequency) { if (!vid_beep_data) { int i; SDL_AudioSpec desiredSpec; memset (&desiredSpec, 0, sizeof(desiredSpec)); desiredSpec.freq = SAMPLE_FREQUENCY; desiredSpec.format = AUDIO_S16SYS; desiredSpec.channels = 1; desiredSpec.samples = 2048; desiredSpec.callback = vid_audio_callback; SDL_OpenAudio(&desiredSpec, NULL); vid_beep_samples = (int)((SAMPLE_FREQUENCY * duration_ms) / 1000.0); vid_beep_duration = duration_ms; vid_beep_data = (int16 *)malloc (sizeof(*vid_beep_data) * vid_beep_samples); for (i=0; i<vid_beep_samples; i++) vid_beep_data[i] = (int16)(AMPLITUDE * sin(((double)(i * M_PI * tone_frequency)) / SAMPLE_FREQUENCY)); } } static void vid_beep_cleanup (void) { SDL_CloseAudio(); free (vid_beep_data); vid_beep_data = NULL; } void vid_beep_event (void) { vid_beep_offset = 0; /* reset to beginning of sample set */ SDL_PauseAudio (0); /* Play sound */ } void vid_beep (void) { SDL_Event user_event; user_event.type = SDL_USEREVENT; user_event.user.code = EVENT_BEEP; user_event.user.data1 = NULL; user_event.user.data2 = NULL; #if defined (SDL_MAIN_AVAILABLE) while (SDL_PushEvent (&user_event) < 0) sim_os_ms_sleep (10); #else vid_beep_event (); #endif SDL_Delay (vid_beep_duration + 100);/* Wait for sound to finnish */ } #else /* !(defined(USE_SIM_VIDEO) && defined(HAVE_LIBSDL)) */ /* Non-implemented versions */ uint32 vid_mono_palette[2]; /* Monochrome Color Map */ t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, int flags) { return SCPE_NOFNC; } t_stat vid_close (void) { return SCPE_OK; } t_stat vid_poll_kb (SIM_KEY_EVENT *ev) { return SCPE_EOF; } t_stat vid_poll_mouse (SIM_MOUSE_EVENT *ev) { return SCPE_EOF; } void vid_draw (int32 x, int32 y, int32 w, int32 h, uint32 *buf) { return; } t_stat vid_set_cursor (t_bool visible, uint32 width, uint32 height, uint8 *data, uint8 *mask, uint32 hot_x, uint32 hot_y) { return SCPE_NOFNC; } void vid_set_cursor_position (int32 x, int32 y) { return; } void vid_refresh (void) { return; } void vid_beep (void) { return; } const char *vid_version (void) { return "No Video Support"; } t_stat vid_set_release_key (FILE* st, UNIT* uptr, int32 val, CONST void* desc) { return SCPE_NOFNC; } t_stat vid_show_release_key (FILE* st, UNIT* uptr, int32 val, CONST void* desc) { fprintf (st, "no release key"); return SCPE_OK; } t_stat vid_show_video (FILE* st, UNIT* uptr, int32 val, CONST void* desc) { fprintf (st, "video support unavailable"); return SCPE_OK; } t_stat vid_screenshot (const char *filename) { sim_printf ("video support unavailable\n"); return SCPE_NOFNC|SCPE_NOMESSAGE; } #endif /* defined(USE_SIM_VIDEO) */ |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | /* sim_video.c: Bitmap video output Copyright (c) 2011-2013, Matt Burke Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the author shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. 08-Nov-2013 MB Added globals for current mouse status 11-Jun-2013 MB First version */ #ifndef SIM_VIDEO_H_ #define SIM_VIDEO_H_ 0 #include "sim_defs.h" #ifdef __cplusplus extern "C" { #endif #define SIM_KEYPRESS_DOWN 0 /* key states */ #define SIM_KEYPRESS_UP 1 #define SIM_KEYPRESS_REPEAT 2 #define SIM_KEY_F1 0 /* key syms */ #define SIM_KEY_F2 1 #define SIM_KEY_F3 2 #define SIM_KEY_F4 3 #define SIM_KEY_F5 4 #define SIM_KEY_F6 5 #define SIM_KEY_F7 6 #define SIM_KEY_F8 7 #define SIM_KEY_F9 8 #define SIM_KEY_F10 9 #define SIM_KEY_F11 10 #define SIM_KEY_F12 11 #define SIM_KEY_0 12 #define SIM_KEY_1 13 #define SIM_KEY_2 14 #define SIM_KEY_3 15 #define SIM_KEY_4 16 #define SIM_KEY_5 17 #define SIM_KEY_6 18 #define SIM_KEY_7 19 #define SIM_KEY_8 20 #define SIM_KEY_9 21 #define SIM_KEY_A 22 #define SIM_KEY_B 23 #define SIM_KEY_C 24 #define SIM_KEY_D 25 #define SIM_KEY_E 26 #define SIM_KEY_F 27 #define SIM_KEY_G 28 #define SIM_KEY_H 29 #define SIM_KEY_I 30 #define SIM_KEY_J 31 #define SIM_KEY_K 32 #define SIM_KEY_L 33 #define SIM_KEY_M 34 #define SIM_KEY_N 35 #define SIM_KEY_O 36 #define SIM_KEY_P 37 #define SIM_KEY_Q 38 #define SIM_KEY_R 39 #define SIM_KEY_S 40 #define SIM_KEY_T 41 #define SIM_KEY_U 42 #define SIM_KEY_V 43 #define SIM_KEY_W 44 #define SIM_KEY_X 45 #define SIM_KEY_Y 46 #define SIM_KEY_Z 47 #define SIM_KEY_BACKQUOTE 48 #define SIM_KEY_MINUS 49 #define SIM_KEY_EQUALS 50 #define SIM_KEY_LEFT_BRACKET 51 #define SIM_KEY_RIGHT_BRACKET 52 #define SIM_KEY_SEMICOLON 53 #define SIM_KEY_SINGLE_QUOTE 54 #define SIM_KEY_BACKSLASH 55 #define SIM_KEY_LEFT_BACKSLASH 56 #define SIM_KEY_COMMA 57 #define SIM_KEY_PERIOD 58 #define SIM_KEY_SLASH 59 #define SIM_KEY_PRINT 60 #define SIM_KEY_SCRL_LOCK 61 #define SIM_KEY_PAUSE 62 #define SIM_KEY_ESC 63 #define SIM_KEY_BACKSPACE 64 #define SIM_KEY_TAB 65 #define SIM_KEY_ENTER 66 #define SIM_KEY_SPACE 67 #define SIM_KEY_INSERT 68 #define SIM_KEY_DELETE 69 #define SIM_KEY_HOME 70 #define SIM_KEY_END 71 #define SIM_KEY_PAGE_UP 72 #define SIM_KEY_PAGE_DOWN 73 #define SIM_KEY_UP 74 #define SIM_KEY_DOWN 75 #define SIM_KEY_LEFT 76 #define SIM_KEY_RIGHT 77 #define SIM_KEY_CAPS_LOCK 78 #define SIM_KEY_NUM_LOCK 79 #define SIM_KEY_ALT_L 80 #define SIM_KEY_ALT_R 81 #define SIM_KEY_CTRL_L 82 #define SIM_KEY_CTRL_R 83 #define SIM_KEY_SHIFT_L 84 #define SIM_KEY_SHIFT_R 85 #define SIM_KEY_WIN_L 86 #define SIM_KEY_WIN_R 87 #define SIM_KEY_MENU 88 #define SIM_KEY_KP_ADD 89 #define SIM_KEY_KP_SUBTRACT 90 #define SIM_KEY_KP_END 91 #define SIM_KEY_KP_DOWN 92 #define SIM_KEY_KP_PAGE_DOWN 93 #define SIM_KEY_KP_LEFT 94 #define SIM_KEY_KP_RIGHT 95 #define SIM_KEY_KP_HOME 96 #define SIM_KEY_KP_UP 97 #define SIM_KEY_KP_PAGE_UP 98 #define SIM_KEY_KP_INSERT 99 #define SIM_KEY_KP_DELETE 100 #define SIM_KEY_KP_5 101 #define SIM_KEY_KP_ENTER 102 #define SIM_KEY_KP_MULTIPLY 103 #define SIM_KEY_KP_DIVIDE 104 #define SIM_KEY_UNKNOWN 200 struct mouse_event { int32 x_rel; /* X axis relative motion */ int32 y_rel; /* Y axis relative motion */ int32 x_pos; /* X axis position */ int32 y_pos; /* Y axis position */ t_bool b1_state; /* state of button 1 */ t_bool b2_state; /* state of button 2 */ t_bool b3_state; /* state of button 3 */ }; struct key_event { uint32 key; /* key sym */ uint32 state; /* key state change */ }; typedef struct mouse_event SIM_MOUSE_EVENT; typedef struct key_event SIM_KEY_EVENT; t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, int flags); #define SIM_VID_INPUTCAPTURED 1 /* Mouse and Keyboard input captured (calling */ /* code responsible for cursor display in video) */ typedef void (*VID_QUIT_CALLBACK)(void); t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback); t_stat vid_close (void); t_stat vid_poll_kb (SIM_KEY_EVENT *ev); t_stat vid_poll_mouse (SIM_MOUSE_EVENT *ev); void vid_draw (int32 x, int32 y, int32 w, int32 h, uint32 *buf); void vid_beep (void); void vid_refresh (void); const char *vid_version (void); const char *vid_key_name (int32 key); t_stat vid_set_cursor (t_bool visible, uint32 width, uint32 height, uint8 *data, uint8 *mask, uint32 hot_x, uint32 hot_y); t_stat vid_set_release_key (FILE* st, UNIT* uptr, int32 val, CONST void* desc); t_stat vid_show_release_key (FILE* st, UNIT* uptr, int32 val, CONST void* desc); t_stat vid_show_video (FILE* st, UNIT* uptr, int32 val, CONST void* desc); t_stat vid_show (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc); t_stat vid_screenshot (const char *filename); extern t_bool vid_active; extern uint32 vid_mono_palette[2]; extern int32 vid_mouse_xrel; /* mouse cumulative x rel */ extern int32 vid_mouse_yrel; /* mouse cumulative y rel */ extern t_bool vid_mouse_b1; /* mouse button 1 state */ extern t_bool vid_mouse_b2; /* mouse button 2 state */ extern t_bool vid_mouse_b3; /* mouse button 3 state */ void vid_set_cursor_position (int32 x, int32 y); /* cursor position (set by calling code) */ #define SIM_VID_DBG_MOUSE 0x01000000 #define SIM_VID_DBG_CURSOR 0x02000000 #define SIM_VID_DBG_KEY 0x04000000 #define SIM_VID_DBG_VIDEO 0x08000000 #ifdef __cplusplus } #endif #if defined(USE_SIM_VIDEO) && defined(HAVE_LIBSDL) #include <SDL.h> #endif /* HAVE_LIBSDL */ #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | /* test.c - Front panel LED and switch testing program, built as pidp8i-test Copyright © 2016-2017 Paul R. Bernard and Warren Young Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the names of the authors above shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from those authors. */ #include "gpio-common.h" #include <assert.h> #include <ctype.h> #include <curses.h> #include <pthread.h> #include <signal.h> #include <stdarg.h> #include <stddef.h> #include <stdlib.h> #include <string.h> #include <time.h> typedef unsigned int uint32; typedef unsigned char uint8; static uint16_t lastswitchstatus[3]; // to watch for switch changes uint8 path[] = { 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x87, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x69, 0x6a, 0x6b, 0x6c, 0x71, 0x72, 0x75, 0x74, 0x73 }; static int auto_advance = 1; #define KEY_CHECK \ switch (getch()) { \ case KEY_DOWN: \ case KEY_LEFT: auto_advance = 0; return step - 1; \ case KEY_UP: \ case KEY_RIGHT: auto_advance = 0; return step + 1; \ case 'r': \ case 'R': auto_advance = 1; return step + 1; \ case 'x': \ case 'X': \ case 3: exit (1); \ } #define DISPLAY_HOLD_ITERATIONS 20 #define DISPLAY_HOLD \ sleep_us (250 * 1000); \ if (auto_advance) { putchar('.'); } else { dhi = 0; } \ KEY_CHECK typedef int (*action_handler)(int, int); struct action { action_handler ph; int step; int arg; }; static void banner (const char* b, ...) { va_list ap; va_start (ap, b); if (!auto_advance) { clear(); refresh(); printf ("Manual mode: Press x or Ctrl-C to exit, " "arrows to step, r to resume."); } printf ("\r\n"); vprintf (b, ap); va_end (ap); } int all_leds_on (int step, int ignored) { puts ("\r"); banner ("Turn on ALL LEDs"); for (int row = 0; row < NLEDROWS; ++row) ledstatus[row] = 07777; for (int dhi = 0; dhi < DISPLAY_HOLD_ITERATIONS; ++dhi) { DISPLAY_HOLD; } return step + 1; } int all_leds_off (int step, int ignored) { puts ("\r"); banner ("Turn off ALL LEDs"); memset (ledstatus, 0, sizeof(ledstatus)); for (int dhi = 0; dhi < DISPLAY_HOLD_ITERATIONS; ++dhi) { DISPLAY_HOLD; } return step + 1; } int led_row_on (int step, int row) { if (row == 0) puts ("\r"); memset (ledstatus, 0, sizeof(ledstatus)); banner ("Turning on LED row %d", row + 1); for (int dhi = 0; dhi < DISPLAY_HOLD_ITERATIONS / 4; ++dhi) { ledstatus[row] = 07777; DISPLAY_HOLD; } ledstatus[row] = 0; return step + 1; } int led_col_on (int step, int col) { if (col == 0) puts ("\r"); memset (ledstatus, 0, sizeof(ledstatus)); banner ("Turning on LED col %d", col + 1); for (int dhi = 0; dhi < DISPLAY_HOLD_ITERATIONS / 4; ++dhi) { for (int row = 0; row < NLEDROWS; ++row) ledstatus[row] |= 1 << col; DISPLAY_HOLD; } ledstatus[col] = 0; return step + 1; } int switch_scan (int step, int ignored) { int path_idx = 0, led_row = 0, delay = 0; puts ("\r"); banner ("Reading the switches. Toggle any pattern desired. " "Ctrl-C to quit.\r\n"); memset (ledstatus, 0, sizeof(ledstatus)); for (int i = 0; i < NROWS; ++i) lastswitchstatus[i] = switchstatus[i]; for (;;) { if (delay++ >= 30) { delay = 0; ledstatus[led_row] = 0; ledstatus[led_row = (path[path_idx] >> 4) - 1] = 04000 >> ((path[path_idx] & 0x0F) - 1); sleep_us (1); KEY_CHECK; if (++path_idx >= sizeof (path) / sizeof (path[0])) path_idx = 0; } if (lastswitchstatus[0] != switchstatus[0] || lastswitchstatus[1] != switchstatus[1] || lastswitchstatus[2] != switchstatus[2]) { for (int i = 0; i < NROWS; ++i) { printf ("%04o ", ~switchstatus[i] & 07777); lastswitchstatus[i] = switchstatus[i]; } printf ("\r\n"); } usleep (1000); } return step + 1; } void start_gpio (void) { assert (sizeof (lastswitchstatus == switchstatus)); // Tell the GPIO thread we're updating the display via direct // ledstatus[] manipulation instead of set_pidp8i_leds calls. pidp8i_simple_gpio_mode = 1; // Create GPIO thread if (start_pidp8i_gpio_thread ("test program") != 0) { exit (EXIT_FAILURE); } } // Tell ncurses we want character-at-a-time input without echo, // non-blocking reads, and no input interpretation. void init_ncurses (void) { initscr (); nodelay (stdscr, TRUE); keypad (stdscr, TRUE); noecho (); cbreak (); clear (); refresh (); } void run_actions (void) { // Define action sequence struct action actions[] = { { all_leds_on, 0, 0 }, { all_leds_off, 1, 0 }, { led_row_on, 2, 0 }, { led_row_on, 3, 1 }, { led_row_on, 4, 2 }, { led_row_on, 5, 3 }, { led_row_on, 6, 4 }, { led_row_on, 7, 5 }, { led_row_on, 8, 6 }, { led_row_on, 9, 7 }, { led_col_on, 10, 0 }, { led_col_on, 11, 1 }, { led_col_on, 12, 2 }, { led_col_on, 13, 3 }, { led_col_on, 14, 4 }, { led_col_on, 15, 5 }, { led_col_on, 16, 6 }, { led_col_on, 17, 7 }, { led_col_on, 18, 8 }, { led_col_on, 19, 9 }, { led_col_on, 20, 10 }, { led_col_on, 21, 11 }, { switch_scan, 22, 0 }, }; const size_t num_actions = sizeof(actions) / sizeof(actions[0]); // Run actions int i = 0; while (i < num_actions) { i = (actions[i].ph)(i, actions[i].arg); if (i == num_actions) i = 0; if (i == -1) i = num_actions - 1; } } static void emergency_shut_down (int signum) { // Shut ncurses down before we call printf, so it's down at the // bottom. This duplicates part of the graceful shutdown path, // which is why it checks whether it's necessary. endwin (); printf ("\r\nExiting pidp8i-test, signal %d: %s\n\n", signum, strsignal (signum)); exit (2); // continues in graceful_shut_down } static void graceful_shut_down () { if (!isendwin()) endwin (); turn_off_pidp8i_leds (); } static void register_shut_down_handlers () { struct sigaction sa; memset (&sa, 0, sizeof (sa)); sa.sa_handler = emergency_shut_down; sigaction (SIGINT, &sa, 0); atexit (graceful_shut_down); } int main (int argc, char *argv[]) { start_gpio (); if ((argc < 2) || (strcmp (argv[1], "-v") != 0)) { register_shut_down_handlers (); init_ncurses (); run_actions (); } return 0; } |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | #!/bin/bash # bosi - The Binary OS Image creation/update script # # Copyright © 2016-2017 by Warren Young # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR # THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above shall # not be used in advertising or otherwise to promote the sale, use or # other dealings in this Software without prior written authorization from # those authors. # Display the usage message function usage() { cat <<USAGE usage: $0 <verb> [tag] The available verbs are init, build, prepare, shrink, image, and finish. You may include a tag parameter with the 'image' and 'finish' verbs to override the default tag ('ils') used in image and zip file outputs. See RELEASE-PROCESS.md for more info. USAGE exit 1 } verb="$1" tag="$2" test -n "$verb" || usage test -z "$tag" && tag=ils nu=pidp8i nh=/home/$nu repo=pidp8i dldir="$HOME/tangentsoft.com/dl" os=jessie-lite img=$dldir/pidp8i-$(date +%Y.%m.%d)-$tag-$os.img greadlink=$(type -p greadlink || type -p readlink) this=$($greadlink -f $0) topdir="$($greadlink -f "$(dirname "$this")"/..)" # Initial steps function do_init() { if [ "$USER" != "root" ] then echo "The init step has to be run as root. The explanation is" echo "given in the section for 'init' in RELEASE-PROCESS.md." echo exit 1 fi set -x apt-get update && apt-get -y upgrade || true test -f /usr/include/curses.h || apt-get -y install libncurses-dev test -h /media/usb || apt-get -y install usbmount if [ -z "$(type -p fossil)" ] then bn=fossil-release tb=$bn.tar.gz wget -O $tb https://fossil-scm.org/index.html/tarball/$bn?uuid=release apt-get -y install libssl-dev ( tar xf $tb && cd $bn && ./configure && make -j3 && make install ) chown -R pi.pi $bn rm $tb fi if [ ! -e "$nh" ] then # First pass on a clean SD card: rename 'pi' user and group to # 'pidp8i' and rename its home directory to match. usermod -l $nu -d $nh -m pi groupmod -n $nu pi fi sed -i.orig \ -e 's/^FS_MOUNTO.*/FS_MOUNTOPTIONS="-fstype=vfat,dmask=0000,fmask=0000"/' \ /etc/usbmount/usbmount.conf reboot } # Clone repo and build the software under [new] pidp8i account function do_build() { if [ "$USER" != "$nu" ] then echo "The build step has to be run as $nu." echo exit 1 fi set -x if [ ! -d museum ] then mkdir -p museum $repo fossil clone https://tangentsoft.com/$repo museum/$repo.fossil fi cd $repo if [ -r ChangeLog.md ] then fossil revert # just in case fossil update release else fossil open ~/museum/$repo.fossil release ./configure fi tools/mmake sudo make install || true # don't care about return code sudo reboot } # This script prepares the OS's configuration to a clean first boot state. function do_prepare() { if [ "$USER" != "$nu" ] then echo "The prepare step has to be run as $nu." echo exit 1 fi set -x history -c ; rm -f ~/.bash_history sudo systemctl stop pidp8i || true # avoid sim hogging CPU sudo systemctl enable sshd || true # disabled by default sudo shred -u /etc/ssh/*key* || true # allow multiple passes sudo dphys-swapfile uninstall || true sudo dd if=/dev/zero of=/junk bs=1M || true # it *will* error-out! sudo rm -f /junk encpass=$(openssl passwd -1 edsonDeCastro1968) sudo usermod -p $encpass pidp8i sudo passwd -e pidp8i sudo poweroff } # Shrink the filesystem on the OS SD card we're about to image to just a # bit bigger than required to hold its present contents. # # The extra 100 megs in the arithmetic below accounts for the /boot # partition, since the `resizepart` command takes a partition end value, # not a size value. # # We don't calculate the actual end of the /boot partition and use that # value because we want a bit of slack space to buy time for an end user # who neglects to expand the card image into the free space available on # their SD card after first boot. function do_shrink() { test "$USER" = "root" || exec sudo $this shrink set -x umount /dev/sda2 || true # might auto-mount, might not e2fsck -f /dev/sda2 # resize2fs demands it # Pack it down tight blocks=$( resize2fs -M /dev/sda2 2>&1 | grep 'blocks long' | grep -wo '[0-9]\+' ) if [ "$blocks" -gt 0 ] then # And now give it a bit of breathing room parted /dev/sda resizepart 2 $(($blocks * 4096 + 10**8))b resize2fs /dev/sda2 poweroff else echo "Failed to extract new filesystem size from resize2fs!" echo exit 1 fi } # This script images the OS SD card in a USB reader on a Mac OS X box. function do_image() { while read line do case $line in /dev/*) dev=$(echo $line | cut -f1 -d' ') ;; 0:*) case $line in *FDisk_partition_scheme*) ;; *) dev= ;; # can't be the OS SD card esac ;; 1:*) case $line in *Windows_FAT_32\ boot*) ;; *) dev= ;; # can't be the OS SD card esac ;; 2:*) case $line in *Linux\ Untitled*) break ;; # found it! *) dev= ;; # can't be the OS SD card esac ;; esac done < <(diskutil list) if [ -z "$dev" ] then echo "Failed to find OS SD card!" echo exit 1 fi echo echo "-------------------------------------------------------" diskutil info "$dev" echo "-------------------------------------------------------" echo read -p "Is that the OS SD card? [y/N]: " answer case $answer in [Yy]*) ;; *) exit 1 esac rdev=${dev/disk/rdisk} # speeds zeroing and re-imaging mf=/tmp/MANIFEST.txt readme=/tmp/README.md cp "$topdir/doc/OS-images.md" $readme set -x diskutil unmountDisk $dev # it auto-mounted sudo time dd if=$rdev bs=1m of=$img sum=($(shasum -a 256 "$img")) bytes=($(wc -c $img)) cat > $mf <<MF SHA-256 hash and size of ${sum[1]}: Hash: ${sum[0]} Size: ${bytes[0]} MF imgdir="$(dirname "$img")" sed -i '' -e "s_$imgdir/__" "$mf" # nix local paths in manifest unix2dos $mf # might be opened on Windows time zip -9j $img.zip $img $mf $readme rm -f $mf $readme # Now re-image the card, starting with a zeroed card to ensure a # clean test. Ignore the end-of-device error from the zero step. sudo time dd if=/dev/zero of=$rdev bs=1m || true sudo time dd if=$img of=$rdev bs=1m diskutil unmountDisk $dev || true # Paragon ExtFS might be installed } # Clean up after the above function do_finish() { set -x rmtrash $img cd $dldir/.. make synch } # Main routine set -e case "$verb" in in*) do_init ;; bu*) do_build ;; pr*) do_prepare ;; sh*) do_shrink ;; im*) do_image ;; fi*) do_finish ;; *) usage ;; esac |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #!/bin/bash ######################################################################## # corecount - Prints the number of CPU cores found on this system # # Copyright © 2017 by Warren Young # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR # THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above shall # not be used in advertising or otherwise to promote the sale, use or # other dealings in this Software without prior written authorization from # those authors. ######################################################################## sys="$(uname -s)" if [ -r /proc/cpuinfo ] then # It's a Linux box grep -Ec '^processor\s+:' /proc/cpuinfo elif [ "$sys" = "Darwin" -o "$sys" = "FreeBSD" -o "$sys" = "OpenBSD" -o "$sys" = "NetBSD" ] then # It's a macOS or BSD box /usr/sbin/sysctl -n hw.ncpu else # No known way to find out, so report only 1 core echo 1 fi |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | #!/usr/bin/env perl ######################################################################## # mkbootscript - Generate boot/*.script from obj/*.lst. See the usage # message below for more details. # # Copyright © 2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## use strict; use warnings; use File::Basename; # Parse command line my $outPath = '../boot'; if (@ARGV == 0 || ! -r $ARGV[0]) { print <<USAGE; usage: $0 <somefile.lst> Given a palbart listing file, transform its contents into a SIMH boot script named after the listing file. Comments in the listing file are variously translated to either comments or echo statements in the boot script. Output is stored in $outPath/somefile.script relative to the listing file, as makes sense when translating obj/*.lst files produced from examples/*.pal files. USAGE exit 1; } # Globals my $keepComments = 1; # keep header comments; ignore the rest my (@comments, @directives); my $firstAddr; my %core; my $inFile = $ARGV[0]; my $bni = basename($inFile); my $outFile = join('/', ( dirname($inFile), $outPath, $bni )); $outFile =~ s{\.lst$}{.script}; my $oneLiner = $bni; # use input file name as one-liner fall-back # Parse the input file my $comment; open my $lst, '<', $inFile or die "Cannot read $inFile: $!\n"; while (<$lst>) { chomp; my ($line, $addr, $val, $tail) = m{ ^\s+ # ignore leading whitespace (\d+\s+) # first number on the line must be a line number (\d+)? # if followed by another number, it's an address \s* # ignore space between addr and val (\d+)? # ...and the value to store at that address (.*) # everything else on the line $ }x; my ($lineIsEmpty) = m{^\s+\d+\s*$}; next unless $lineIsEmpty || $tail; ($comment) = $tail =~ m{/\s*(.*)$} if $tail; if (defined $line and int($line) == 1 and defined $comment) { # Save the comment on the first line as a one-line description # of what the program does, emitted to the console by SIMH when # running our output script unless we find a "SIMH: echo..." # directive later on in that file, which overrides it. $oneLiner = $comment; $oneLiner =~ s{ - }{: }; $oneLiner =~ s{([\w-]+).pal}{"$1" example}; } elsif ($keepComments and defined $lineIsEmpty) { # The first blank line in the input file will appear in the # listing as a file containing only a line number. Stop saving # comments, since everything after this would be comments on # individual source lines, which don't get copied into output. $keepComments = 0; } elsif (defined $addr and defined $val) { # Save address and value to our core image $firstAddr = oct($addr) if not defined $firstAddr; $core{oct($addr)} = oct($val); } elsif ($keepComments and defined $comment and defined $line) { # It's a header comment line if ($comment =~ m{^SIMH: }) { # It's a directive to SIMH, so save it separately push @directives, substr($comment, 6); } else { # Nothing special, so just save the text portion push @comments, $comment; } } } close $lst; # Remove leading and trailing blank comment lines while (@comments and length($comments[0]) == 0) { shift @comments; } while (@comments and length($comments[$#comments]) == 0) { pop @comments; } # Write parsed data into output file open my $scr, '>', $outFile or die "Cannot write $outFile: $!\n"; for my $c (@comments) { print $scr "; $c\n"; } print $scr ";\n"; my $foundEcho; for my $d (@directives) { print $scr $d, "\n"; $foundEcho = 1 if $d =~ m{^echo }; } print $scr "echo Running $oneLiner...\n" unless $foundEcho; for my $a (sort { $a <=> $b } keys %core) { printf $scr "dep %05o %04o\n", $a, $core{$a}; } printf $scr "go %05o\n", $firstAddr; close $scr; print "Converted $inFile to $outFile\n"; |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #!/bin/bash ######################################################################## # mkrel - Automatically merge trunk changes into the release branch # for a new public release of the software. Also tags the trunk with # the date of release, so old releases can be easily checked out. # # Copyright © 2016-2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## set -e tag=v$(date +%Y%m%d) fossil update && fossil ci --tag $tag -m "Tagged release $tag" && cd ../release && fossil update && fossil merge $tag && ! fossil status | grep -q '^CONFLICT' && tools/mmake && fossil diff --command 'colordiff -wu' | less && fossil ci -m "Merged trunk changes for $tag into release branch" |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #!/bin/bash ######################################################################## # mmake - Runs make -jN where N is 1.5x the number of CPU cores # # Copyright © 2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## make -j$(($("$(dirname "$0")"/corecount) * 15 / 10)) "$@" |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #!/bin/bash # # restyle - A wrapper around indent(1) to produce the code style # documented in the HACKERS.md file. # # Copyright © 2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. if indent --version 2>&1 | grep -q 'GNU indent' then # It's GNU indent here, so start with K&R, then: # # - nce: don't cuddle else # - cli4: indent case statement labels 4 spaces # - nlp: don't align continued statements at the opening parenthesis # - pcs: put a space before the opening parenthesis of a function call # - di1: don't line up variable types and names in separate columns # - i4: use 4-space indents # - l100: allow lines up to 100 columns before forcibly breaking them # - ncs: don't put a space between a cast and its operand # - ss: add a space before semicolon with empty loop body # - nbbo: don't break long lines before || and && operators indent -kr \ -nce -cli4 -nlp -pcs -di1 -i4 -l100 \ -nut -ncs -ss -nbbo "$@" else # BSD `indent` does't understand the `-kr` option, so we need to use # the following alternative on BSD and macOS systems: indent \ -nce -cli4 -nlp -pcs -di1 -i4 -l100 \ -bap -ncdb -nfc1 -npsl -nsc "$@" fi |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | #!/bin/bash ######################################################################## # simh-update - Attempt to automatically merge in the latest upstream # SIMH 4 changes from the GitHub repository. # # Copyright © 2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## SRCDIR="@srcdir@" SRCSUBDIR="$SRCDIR/src" PRGNAME="$(basename "$0")" WORKDIR="@builddir@/$PRGNAME-temp" OUR_SIMH_DIR="$WORKDIR/simh/ours" CURR_SIMH_DIR="$WORKDIR/simh/curr" LOGFILE="$WORKDIR/output.log" PATCHFILE="$WORKDIR/pidp8i.patch" OLD_SGCID=$(grep ^SGCID "@srcdir@"/Makefile.in | cut -f2 -d=) SOFFICE=/Applications/LibreOffice.app/Contents/MacOS/soffice # If LibreOffice isn't here, we can't convert DOC to PDF below. if [ ! -x "$SOFFICE" ] then cat <<USAGE Sorry, this must be run on a system where LibreOffice is installed as $SOFFICE. TODO: Find this same program in other places. USAGE exit 1 fi # If we don't have the Git worktree sub-command, we're probably running # this on Jessie, which ships Git 2.1.4. if ! git help worktree &> /dev/null then cat <<ERROR Sorry, this must be run on a system with the "git worktree" feature, which first shipped in Git 2.5. ERROR exit 1 fi # Set up working directory rm -rf "$WORKDIR" mkdir -p "$WORKDIR" # From here on, send all output to the log file. # Code based on http://stackoverflow.com/a/20564208/142454 exec 1<&- exec 2<&- exec 1<>"$LOGFILE" exec 2>&1 function say() { echo "$@" >> /dev/tty } # Bail on errors so we don't have to test everything. Ideally, nothing # from here on will fail. If it does, the log file will explain it. # Code based on http://stackoverflow.com/a/185900/142454 function error() { lineno="$1" message="$2" code="${3:-1}" if [ -n "$message" ] ; then message=": $message" ; fi read -r -d '%' errmsg <<ERROR Error on or near line $lineno, code ${code}$message! (See log file for more info: $LOGFILE) % ERROR say say "$errmsg" say exit $code } trap 'error ${LINENO}' ERR # Deal with uncommitted changes in $SRCSUBDIR cd "$SRCSUBDIR/.." # we need the src/ prefix to do this test properly! if [ $(fossil status | grep '^EDITED.*src/' | wc -l) -gt 0 ] then if [ "$1" = "-f" ] then say "Tossing uncommitted changes in $SRCSUBDIR..." fossil revert $(fossil status | grep '^EDITED.*src/' | cut -f 2- -d' ') shift else read -r -d '%' errmsg <<ERROR Cowardly refusing to update SIMH to the current upstream version while there are uncommitted changes in $SRCSUBDIR. Say make simh-update-f or pass -f to force those changes to be tossed. % ERROR say say "$errmsg" say exit 3 fi fi cd "@builddir@" # Retreive the tip-of-master and $OLD_SGCID versions of SIMH say Retreiving upstream SIMH versions... mkdir -p "$OUR_SIMH_DIR" mkdir -p "$CURR_SIMH_DIR" git clone https://github.com/simh/simh "$CURR_SIMH_DIR" pushd "$CURR_SIMH_DIR" NEW_SGCID=$(git rev-parse HEAD) say "Pulled ${NEW_SGCID:0:8} as curr; prev is ${OLD_SGCID:0:8}." git worktree add "$OUR_SIMH_DIR" $OLD_SGCID popd # Copy over updated versions of the docs and replace them in the Fossil # unversioned area. We simplify the upstream naming scheme in the # transfer, dropping unnecessary prefixes and suffixes. pushd "$SRCDIR" for fs in pdp8_doc simh_faq simh_doc do ft=$(echo $fs | sed -e 's/simh_//' -e 's/_doc//') test "$ft" = "doc" && ft=main pdfout=doc/simh/$ft.pdf pdftmp="$fs.pdf" say -n "Converting upstream $fs.doc to $pdfout..." if [ ! -e "$pdfout" ] ; then touch $pdfout ; fi # complaint squisher if "$SOFFICE" --convert-to pdf "$CURR_SIMH_DIR/doc/$fs.doc" && [ -s "$pdfout" != -s "$pdftmp" ] then # The upstream doc has apparently changed, since the PDF output # file is a different size. Replace our public version. # # We can't use cmp or similar here because a bunch of metadata # change each time we re-render the PDF, even if the source doc # is unchanged. There are proper PDF comparison tools, but none # preinstalled everywhere, and we don't want to make one of # those tools a dependency of this script. Size comparison # suffices for our purposes, since most any substantial text # change will change the output file size. say "changes detected." mv "$pdftmp" "$pdfout" fossil uv add "$pdfout" else say "unchanged." fi done say "Syncing new PDFs..." fossil uv sync popd # Rename upstream Git paths to match our *.in files so that our produced # patches are made against those higher-level versions. If we didn't do # this, we'd have to manually resubstitute variables for absolute paths. # # Filter out Makefile.in because we don't want to try and patch the # upstream plain Makefile to work with autosetup. It complicates the # resulting patch file to no purpose. say Renaming upstream files to match our \*.in variants... find "$SRCSUBDIR" -name \*.in -print | grep -v Makefile.in | while read f do inf="${f#$SRCSUBDIR/}" # make path fully relative genf="${inf%.in}" # remove .in from the end if [ -f "$OUR_SIMH_DIR/$genf" ] then mv "$OUR_SIMH_DIR/$genf" "$OUR_SIMH_DIR/$inf" mv "$CURR_SIMH_DIR/$genf" "$CURR_SIMH_DIR/$inf" fi # else, it's a *.in file specific to our code base, not a # parameterized version of an upstream file done # Produce a patch file for modifying the upstream $OLD_SGCID version to # merge in our local changes. # # For some reason, diff(1) returns an error when we do this, at least on # OS X. Perhaps it is not happy about the fact that the file set in # each tree is different? Regardless of reason, we must check for a # non-empty patch file to determine whether an actual error occurred. say Producing clean patch file from upstream ${OLD_SGCID:0:8} version say to our local PiDP-8/I version... if ! diff -ru "$OUR_SIMH_DIR" "$SRCSUBDIR" | grep -v '^Only in' > "$PATCHFILE" && [ ! -s "$PATCHFILE" ] then error $LINENO "patch generation failed" 2 fi # For each file in src that is also present in the current upstream # version of SIMH, overwrite our version. find "$SRCSUBDIR" -type f -print | while read f do base="${f#$SRCSUBDIR}" upstream="$CURR_SIMH_DIR/$base" test -e "$upstream" && cp "$upstream" "$f" done # Now try to apply the patch we made above to the upstream files. patch -p0 < "$PATCHFILE" # No error, so save the new tip-of-master Git commit ID and rebuild say "Patch appears to have applied cleanly. Attempting a rebuild..." sed -e "s/^SGCID=.*/SGCID=$NEW_SGCID/" -i tmp @srcdir@/Makefile.in tools/mmake # Restore stdout and let the human test it say "Build completed without error. Running default bootscript to test it..." say say "(Nuke $WORKDIR when finished.)" say exec 1<&- exec 1<>/dev/tty exec make run |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #!/usr/bin/env perl ######################################################################## # tools/version - Print a string summarizing the software version # # Copyright © 2017 Warren Young # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the names of the authors above # shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written # authorization from those authors. ######################################################################## use strict; use warnings; use Cwd 'abs_path'; use File::Basename; my $topdir = dirname($0) . '/..'; if (not -e "$topdir/.fslckout") { # We're not within a Fossil checkout, so try to get the version # number from the top directory name. $topdir = basename(abs_path($topdir)); my ($v) = $topdir =~ m{v\d+}; print 'pkg:', ($v ? $v : 'vUNKNOWN'), "\n"; exit 0; } # Get version info from Fossil my ($branch, $checkout, $version, $comment); open my $s, '-|', 'fossil status 2> /dev/null' or die "Failed to run fossil status!\n"; while (<$s>) { chomp; my ($attr, $value) = split /:\s+/; if ($attr eq 'checkout') { my @elems = split ' ', $value; $checkout = substr($elems[0], 0, 10); } elsif ($attr eq 'tags') { my @tags = split /, /, $value; for my $t (@tags) { if ($t =~ m{^v\d+}) { $version = $t; } else { $branch = $t; } } } elsif ($attr eq 'comment') { $comment = $value; } } die "The fossil status command in $0 failed!\n" unless close $s; ($version) = $comment =~ m{(v\d+)} if $branch eq 'release'; print $branch, ':', ($version || "id[$checkout]"); |