mirror of
https://github.com/simh/simh.git
synced 2026-01-25 19:56:25 +00:00
Notes For V2.8
1. New Features
1.1 Directory and documentation
- Only common files (SCP and libraries) are in the top level
directory. Individual simulator files are in their individual
directories.
- simh_doc.txt has been split up. simh_doc.txt now documents
only SCP. The individual simulators are documented in separate
text files in their own directories.
- mingw_build.bat is a batch file for the MINGW/gcc environment
that will build all the simulators, assuming the root directory
structure is at c:\sim.
- Makefile is a UNIX make file for the gcc environment that will
build all the simulators, assuming the root directory is at
c:\sim.
1.2 SCP
- DO <file name> executes the SCP commands in the specified file.
- Replicated registers in unit structures can now be declared as
arrays for examine, modify, save, and restore. Most replicated
unit registers (for example, mag tape position registers) have
been changed to arrays.
- The ADD/REMOVE commands have been replaced by SET unit ONLINE
and SET unit OFFLINE, respectively.
- Register names that are unique within an entire simulator do
not have to be prefaced with the device name.
- The ATTACH command can attach files read only, either under
user option (-r), or because the attached file is ready only.
- The SET/SHOW capabilities have been extended. New forms include:
SET <dev> param{=value}{ param ...}
SET <unit> param{=value}{ param ...}
SHOW <dev> {param param ...}
SHOW <unit> {param param ...}
- Multiple breakpoints have been implemented. Breakpoints are
set/cleared/displayed by:
BREAK addr_list{[count]}
NOBREAK addr_list
SHOW BREAK addr_list
1.3 PDP-11 simulator
- Unibus map implemented, with 22b RP controller (URH70) or 18b
RP controller (URH11) (in debug).
- All DMA peripherals rewritten to use map.
- Many peripherals modified for source sharing with VAX.
- RQDX3 implemented.
- Bugs fixed in RK11 and RL11 write check.
1.4 PDP-10 simulator
- ITS 1-proceed implemented.
- Bugs fixed in ITS PC sampling and LPMR
1.5 18b PDP simulator
- Interrupts split out to multiple levels to allow easier
expansion.
1.5 IBM System 3 Simulator
- Written by Charles (Dutch) Owen.
1.6 VAX Simulator (in debug)
- Simulates MicroVAX 3800 (KA655) with 16MB-64MB memory, RQDX3,
RLV12, TSV11, DZV11, LPV11, PCV11.
- CDROM capability has been added to the RQDX3, to allow testing
with VMS hobbyist images.
1.7 SDS 940 Simulator (not tested)
- Simulates SDS 940, 16K-64K memory, fixed and moving head
disk, magtape, line printer, console.
1.8 Altair Z80
- Revised from Charles (Dutch) Owen's original by Peter Schorn.
- MITS 8080 with full Z80 simulation.
- 4K and 8K BASIC packages, Prolog package.
1.9 Interdata
The I4 simulator has been withdrawn for major rework. Look for
a complete 16b/32b Interdata simulator sometime next year.
2. Release Notes
2.1 SCP
SCP now allows replicated registers in unit structures to be
modelled as arrays. All replicated register declarations have
been replaced by register array declarations. As a result,
save files from prior revisions will generate errors after
restoring main memory.
2.2 PDP-11
The Unibus map code is in debug. The map was implemented primarily
to allow source sharing with the VAX, which requires a DMA map.
DMA devices work correctly with the Unibus map disabled.
The RQDX3 simulator has run a complete RSTS/E SYSGEN, with multiple
drives, and booted the completed system from scratch.
2.3 VAX
The VAX simulator will run the boot code up to the >>> prompt. It
can successfully process a SHOW DEVICE command. It runs the HCORE
instruction diagnostic. It can boot the hobbyist CD through SYSBOOT
and through the date/time dialog and restore the hobbyist CD, using
standalone backup. On the boot of the restored disk, it gets to the
date/time dialog, and then crashes.
2.4 SDS 940
The SDS 940 is untested, awaiting real code.
2.5 GCC Optimization
At -O2 and above, GCC does not correctly compile the simulators which
use setjmp-longjmp (PDP-11, PDP-10, VAX). A working hypothesis is
that optimized state maintained in registers is being used in the
setjmp processing routine. On the PDP-11 and PDP-10, all of this
state has been either made global, or volatile, to encourage GCC to
keep the state up to date in memory. The VAX is still vulnerable.
3. Work list
3.1 SCP
- Better ENABLE/DISABLE.
3.2 PDP-11 RQDX3
Software mapped mode, RCT read simulation, VMS debug.
This commit is contained in:
committed by
Mark Pizzolato
parent
654937fc88
commit
701f0fe028
950
S3/haltguide.txt
Normal file
950
S3/haltguide.txt
Normal file
@@ -0,0 +1,950 @@
|
||||
IBM System/3 Model 8/10 SCP
|
||||
|
||||
**********
|
||||
Halt Guide
|
||||
**********
|
||||
|
||||
This following list is my own reformatting and rewording of the
|
||||
official IBM Halt Guide for the Model 8/10 SCP.
|
||||
|
||||
The halts are those displayed on the message display unit. The
|
||||
list is in alphabetical order for easy reference.
|
||||
|
||||
When the system halts, the two 7-segment displays will display the
|
||||
halt as listed here, and the system console (or printer if the log
|
||||
device is the printer) will print the "SCP Message" below. To
|
||||
respond to the halt, deposit one of the valid response numbers
|
||||
(0 thru 3) into the SR, and then use the C command to continue.
|
||||
|
||||
Unless otherwise stated, a response of 0 means to continue and accept
|
||||
the error, 1 means to retry the operation or re-read the statement in
|
||||
error, 2 means to cancel the job and retain added records (if any) and
|
||||
3 means to end the job and discard any added records in files.
|
||||
|
||||
This is a listing of those halts likely to be encountered using SCP on
|
||||
the simuator, it is not the complete list of all possible halts.
|
||||
|
||||
Halt SCP Message Description
|
||||
---- ----------- -----------
|
||||
|
||||
00 Invalid response to another halt. Deposit a valid
|
||||
value (0 thru 3) in SR.
|
||||
|
||||
0A A 5448 Disk Unit not ready.
|
||||
|
||||
0C 5448 Disk Equipment Check
|
||||
|
||||
0E Permanent disk error during logging.
|
||||
|
||||
0F ID0FXX 23 Invalid cylinder number on disk operation.
|
||||
XX = Disk Drive.
|
||||
|
||||
0H ID0HXX 23 Invalid sector number on disk operation
|
||||
XX = Disk Drive.
|
||||
|
||||
0Y IK0Y0X 123 3741 Error. X: 1=not ready 2=wrong mode
|
||||
3=parity error 5=record length error
|
||||
|
||||
0 ID0 XX 23 Disk Data Check
|
||||
XX = Disk Drive.
|
||||
|
||||
0- ID0-XX Invalid disk operation code: Start cancels job.
|
||||
XX = Disk Drive.
|
||||
|
||||
10 3 No input file allocate, user error.
|
||||
|
||||
11 0 23 Square root of a negative field
|
||||
|
||||
12 0 23 Divide Overflow
|
||||
|
||||
13 0 23 Divide by zero
|
||||
|
||||
14 0 23 Varible index zero of out of range
|
||||
|
||||
15 0 23 Sequenced table is out of sequence
|
||||
|
||||
16 0 23 (RPG) OBject tables expected. /* Read.
|
||||
|
||||
17 0 23 (RPG) Object table exceeds specified length
|
||||
|
||||
18 0 23 (RPG) Terminal errors in source program.
|
||||
|
||||
19 0 3 (RPG) Warning errors in source program. 0=continue.
|
||||
|
||||
1A 3 (RPG) Out of core memory
|
||||
|
||||
1C 23 Unidentified halt has been issued. Probable system
|
||||
error.
|
||||
|
||||
1E 0 3 (RPG) Demand file at end of file.
|
||||
|
||||
1F 23 (RPG) End of file or end of extent. If during RPG
|
||||
compilation, expand $SOURCE or $WORK.
|
||||
|
||||
1H 0 23 Duplicate keys found during build of indexed file.
|
||||
0=skip this record and continue.
|
||||
|
||||
1J 0 23 Out of sequence keys during build of indexed file.
|
||||
0=skip this record and continue.
|
||||
|
||||
1L 0 23 Key changed during record update. User error.
|
||||
0=continue, do not update record.
|
||||
|
||||
1P 01 Forms in printer need positioning.
|
||||
|
||||
1U 123 No record found on direct or indexed file.
|
||||
|
||||
1Y 0 23 (RPG) Invalid numeric data to DSPLY statement.
|
||||
|
||||
1 0 3 Object program ready to punch tables.
|
||||
|
||||
20 1 3 Disk Sort: Invalid header and no // SOURCE
|
||||
|
||||
21 01 3 Disk Sort: Name on // SOURCE not found
|
||||
|
||||
22 0 2 Disk Sort: Warning errors found.
|
||||
|
||||
23 3 Disk Sort: Unrecoverable error.
|
||||
|
||||
25 3 Disk Sort: Terminal errors in sort statements.
|
||||
|
||||
27 0 Disk Sort: In debug mode, finished pass.
|
||||
|
||||
2C 0 3 Disk Sort: No Input Records selected.
|
||||
|
||||
2E 3 Disk Sort: Workfile too small.
|
||||
|
||||
2F 23 Disk Sort: Output file too small.
|
||||
|
||||
2L DT2LY2 3 Tape Record too large to process.
|
||||
DT2LY7 3 No FILE statement for tape file open.
|
||||
DT2LY9 3 No enough storage for tape operation
|
||||
DT2LTC 3 Invalid tape header length
|
||||
DT2LYF 123 Incorrect block length read from tape
|
||||
|
||||
2P Permanent tape error.
|
||||
|
||||
2U 12 Tape unit is write protected.
|
||||
|
||||
2Y 3 Invalid device specification in object.
|
||||
|
||||
2- 0 3 First statement was not a Tape Sort header.
|
||||
|
||||
30 EG30 3 Space not available on R1 or F1.
|
||||
UB30A1 0 3 Active files exist on output disk
|
||||
UB30AF 0 3 Active files exist on 5448 disk
|
||||
UB30H1 0 3 Wrong capacity or uninitialized pack
|
||||
UB30NS 3 No 5448 disk for $PCOPY
|
||||
UB30TP 0 3 Pack change required.
|
||||
UC30AF 3 Active or system files on target
|
||||
UC30BD 3 Volume label cannot be read
|
||||
UC30SP 3 Not enough space for work file
|
||||
UP30AF 3 Active or system files on target
|
||||
|
||||
31 UI31AF 0 3 Active or system files on target
|
||||
0=proceed to next unit to initialize
|
||||
UI30WP 01 3 Wrong pack, name does not match.
|
||||
|
||||
32 UB32Bx 01 3 5444 pack is not a $PCOPY backup pack.
|
||||
UB32NP 01 3 Unit specified is not a $PCOPY pack.
|
||||
UC32BD 3 FROM pack is a TO pack from an interrupted
|
||||
COPYPACK run.
|
||||
UC32BP 3 Output pack is a $PCOPY output pack.
|
||||
Must be initialized or reset by a RESET
|
||||
statement to be used.
|
||||
UC32DS 3 Packs FROM and TO are different sizes.
|
||||
|
||||
33 UI33PU 0 3 Pack defective, cannot be initialized.
|
||||
|
||||
34 Ux34 1 3 Keyword in a utility control statement is invalid.
|
||||
|
||||
35 UC35xx 1 3 Error in $COPY or $KCOPY control statement.
|
||||
|
||||
36 UI36CE 0 3 CE track defective on unit F1.
|
||||
|
||||
37 UC37xx 0 3 Pack change required. xx: FP=mount on R1,
|
||||
IP=pack on COPYIN, OP=pack on COPYO.
|
||||
|
||||
38 UA38XX 0 3 Wrong pack mounted.
|
||||
UB38DA 01 3 Dates do not match.
|
||||
UB38DM 01 3 2nd 5444 pack not from same backup set as 1st.
|
||||
UB38IP 01 3 PACKIN keyword pack not same as pack mounted.
|
||||
UB38OP 01 3 PACKO keyword not same as pack mounted.
|
||||
|
||||
3A UC3Axx 3 Key out of sequence (DP), invalid high key (HK),
|
||||
out of space to copy file (XE), or disk I/O error.
|
||||
|
||||
3C UC3CCS 3 COPYFILE out of core.
|
||||
UC3CNF 3 Module not found, name is logged as R XXXXXX.
|
||||
|
||||
3E UC3EOX 0 3 COPYFILE output not as big as size of input.
|
||||
|
||||
3F UC3Fxx 1 3 Error in COPYFILE statement.
|
||||
|
||||
3J UC3Fxx 3 Invalid specification for Copy/Dump.
|
||||
|
||||
3P UC3Pxx 1 3 Error in COPYPACK, RESET, or LABELS statement.
|
||||
|
||||
3Y UI3YIS 0 3 Requested secondary init when primary required.
|
||||
|
||||
3 UI3 xx 1 3 Error in VOL statement.
|
||||
|
||||
40 DD40 3 File has been referenced as an output or add file
|
||||
and the file is already allocated.
|
||||
|
||||
4A DD4A 3 File had already been opened and is re-opened.
|
||||
|
||||
4C DD4C 3 Multivolumne file spec error.
|
||||
|
||||
4E DD4E 3 FILE indicates a multivolule file being built,
|
||||
but program compiled for single volume.
|
||||
|
||||
4F DD4F 3 Print buffers not aligned in program.
|
||||
|
||||
4H DD4H 0 3 Unordered load specified for ISAM. Ordered load
|
||||
must be specified on RPG file specs.
|
||||
|
||||
4J DD4J 3 All file specs have been checked and there were
|
||||
errors.
|
||||
|
||||
4L DD4L 3 Referenced file already allocated.
|
||||
|
||||
4P DD4P 3 Prgram/FILE statement mismatch.
|
||||
|
||||
4U DD4U 3 File referenced as update, already allocated.
|
||||
|
||||
4Y DD4Y 3 File has an incorrect device specification.
|
||||
|
||||
4 DD4 3 No FILE specification for referenced file.
|
||||
|
||||
4' DD4' 3 Attempting reference to a file in 2 levels, one or
|
||||
both using RETAIN-S.
|
||||
|
||||
50 UA50ID 2 Bad track which can't be reassigned.
|
||||
|
||||
51 UR51 12 Can't use Alternate Track program in procedure.
|
||||
|
||||
52 ML52 12 EOJ for Card List program.
|
||||
|
||||
53 IU53 1 3 Number of VOL statements does not agree with number
|
||||
of units on UIN statement.
|
||||
|
||||
54 EO54 3 End-of-file.
|
||||
|
||||
55 UF55xx 1 3 Error in SCRATCH or REMOVE statement.
|
||||
|
||||
56 UA56TS 0 3 ASSIGN track is over disk capacity.
|
||||
UA56XX 0 3 Unit specified is uninitialized.
|
||||
|
||||
57 UF57WP 01 3 File delete program. Wrong pack is mounted.
|
||||
0: Mount correct pack and continue. 1:
|
||||
correct statement and retry.
|
||||
|
||||
5A UA5Axx 012 Alternate track assignment error.
|
||||
|
||||
5C MR5Cxx 1 3 Invalid reformat specs.
|
||||
|
||||
5F UF5Fxx 1 3 Error in DISPLAY statement.
|
||||
|
||||
5H UA5HEU 0123 Primary track is still defective.
|
||||
|
||||
5L UF5LAF 0 3 PRogram try to delete files that are being used by
|
||||
another program.
|
||||
UF5LNF 0 3 File not found.
|
||||
UF5LTM 23 Too many files specified. Max is 40.
|
||||
|
||||
5U UI5Uxx 1 3 Error in UIN statement.
|
||||
|
||||
5Y UR5Yxx 1 3 Error in REBUILD statment.
|
||||
|
||||
5 UA5 xx 1 3 Error in ALT statement.
|
||||
|
||||
5- 3 Tape Sort error occurred.
|
||||
|
||||
5' UF5'N1 0 3 Pack cannot be used. Not inited.
|
||||
UF5'NU 0 3 Pack was used as TO pack on a COPYPACK job
|
||||
that required early termination. Can only
|
||||
be used for another COPYPACK job.
|
||||
|
||||
60 LM60SY 0 3 Cannot remove or change library size on pack
|
||||
from which $MAINT was loaded.
|
||||
|
||||
61 LM61EP 0 3 Trying to copy a system to a library that is
|
||||
1) not empty, 2) not allocated with large enough
|
||||
SWA, or 3) not allocated with enough space.
|
||||
LM61NS 0 3 System does not exist on FROM pack.
|
||||
|
||||
62 LM62CS 01 3 Check Sum error.
|
||||
LM62DR Can't determine if REMOVE is data or control.
|
||||
LM62EF FROM, TO, or AFTER statement does not exist or
|
||||
is out of sequence.
|
||||
LM62ND NO data records following INSERT or REPLACE.
|
||||
LM62SQ Records are out of sequence.
|
||||
LM62TP Incorrect type record.
|
||||
|
||||
63 LM63DE 0 3 Directory entry error. Name can't be found or
|
||||
attributes don't match, or attempt to remove
|
||||
dir entry with MODIFY.
|
||||
|
||||
64 LM64DS 0 3 Syntax error in ALLOCATE.
|
||||
|
||||
65 LM65UN 0 3 Pack not properly initialized.
|
||||
|
||||
66 LA66xx 3 Error with LOAD * function.
|
||||
|
||||
67 EL67NL 0 3 Library does not exist.
|
||||
|
||||
68 EL68DF 0 3 No room in library or directory.
|
||||
|
||||
69 XX69HE 3 Disk I/O Error while using library.
|
||||
|
||||
6A LM6Axx 1 3 $MAINT has detected a syntax error on a control
|
||||
statement. xx gives a hint of what might be wrong.
|
||||
AL: SOURCE or OBJECT missing or invalid
|
||||
AZ: SYSTEM missing or invalid
|
||||
D2: FROM, TO, or WORK is R2 or F2, not available
|
||||
DK: Duplicate keyword
|
||||
DS: Invalid DIRSIZE
|
||||
FL: Invalid or missing FILE keyword
|
||||
FM: Invalid or missing FROM keyword
|
||||
IK: Invalid keyword
|
||||
IN: Invalid INCR keyword
|
||||
IS: first 3 columns must be // blank
|
||||
IV: Invalid statement identifier
|
||||
LB: Invalid LIBRARY keyword
|
||||
LS: Invalid LIST keyword
|
||||
NK: No keywords
|
||||
NM: Invalid NAME keyword
|
||||
NU: Invalid NEWNAME keyword
|
||||
OM: Invalid OMIT keyword
|
||||
RL: Invalid RECL keyword
|
||||
RS: Invalid RESER keyword
|
||||
RT: Invalid RETAIN keyword
|
||||
SF: INvalid SEQFLD keyword
|
||||
SQ: Invalid FROM, TO, or AFTER in MODIFY mode
|
||||
XC: Invalid record.
|
||||
XD: Duplicate keyword
|
||||
XF: $$SYFG could not be found.
|
||||
XL: LIBRARY keyword missing
|
||||
XM: NAME keyword missing
|
||||
XN: NAME parameter is invalid
|
||||
XP: Library does not exist on this pack
|
||||
XS: Syntax error
|
||||
XT: Invalid library type
|
||||
XV: INvalid operation
|
||||
|
||||
6C LM6CSP 0 3 Not enough space on pack.
|
||||
LM6CSW 0 3 Space not available for work file.
|
||||
|
||||
6E LM6EOF 0 3 Overflow in seq field during RESER.
|
||||
LM6EDP 0 3 Entry with same name already exists in library.
|
||||
|
||||
6H EL6HDT 0 3 Trying to replace perm with temp entry.
|
||||
LM6HDP 0 3 NEWNAME is already in library.
|
||||
|
||||
6J LM6JCC 0 3 Control statements are missing.
|
||||
|
||||
6L UA6L 3 Log device is required for this program.
|
||||
|
||||
6Y LM6YNN 1 3 No NEWNAME when copying to same library.
|
||||
|
||||
6 LM6 BC 3 Invalid character in source record.
|
||||
LM6 CM 0 3 Invalid object deck.
|
||||
LM6 ND 0 3 No data between COPY and CEND.
|
||||
|
||||
6- LM6-BC 01 Entry containing a blank card being placed in
|
||||
library. 0: accept, 1: skip and read next card.
|
||||
|
||||
6' LM6'CE 1 3 // CEND expected but not found. 1: Retry,
|
||||
provide CEND. NOTE: For option 3, if a module
|
||||
was being replaced, it may have been deleted but
|
||||
new module not loaded.
|
||||
|
||||
70 CR70 3 Too many overrides for procedure. Max is 25.
|
||||
|
||||
71 CR71 0 3 OCL Syntax Error.
|
||||
|
||||
73 CR73 0 // PARTITION given in invalid location.
|
||||
|
||||
74 CR74 3 /& between LOAD and RUN or CALL and RUN.
|
||||
|
||||
75 CR75 23 Extraneous statement.
|
||||
|
||||
76 CR76 0 3 // Missing from OCL statement.
|
||||
|
||||
77 CR77 23 Invalid OCL statement identifier.
|
||||
|
||||
78 CR78 0 3 Unknown OCL keyword.
|
||||
|
||||
79 CR79 23 Continuation expected but not received.
|
||||
|
||||
7A CR7A 3 A second LOAD or CALL found before run, or a
|
||||
CALL in procedure overrides.
|
||||
|
||||
7C CR7C 0 3 // COMPILE found between jobs.
|
||||
|
||||
7E CR7E 0 3 // DATE found between jobs. 0: Ignore and continue.
|
||||
|
||||
7F CR7F 0 3 // FILE found between jobs. Must go between
|
||||
// LOAD or // CALL and // RUN statements.
|
||||
|
||||
7H CR7H 0 3 // SWITCH found between jobs.
|
||||
|
||||
7J CR7J 23 // READER found between LOAD or CALL and RUN.
|
||||
|
||||
7L CI7Lxx 23 Error when reading a tape file.
|
||||
|
||||
7P New print chain expected. Load it and press START.
|
||||
|
||||
7U CR7U 3 RUN statement not preceeded by LOAD or CALL.
|
||||
|
||||
7Y CI7Yxx 23 Error outputing a tape file.
|
||||
|
||||
7 CR7 3 Too many utility control statements, max is 25.
|
||||
|
||||
7- CR7- 0 // PARTITION was read but system does not support
|
||||
Dual Programming.
|
||||
|
||||
7' Error during tape processing.
|
||||
|
||||
80 CR80 0 // DATE card has not been entered.
|
||||
|
||||
81 CR81 23 Error in LOAD statement.
|
||||
|
||||
83 CR83 23 Error in LOAD * statement.
|
||||
|
||||
84 CR84 23 Error in CALL statement
|
||||
|
||||
85 CR85 23 Second SWITCH statement found.
|
||||
|
||||
86 CR86 23 Invalid paramter in switch statement.
|
||||
|
||||
88 CR88 1 3 Procedure not found.
|
||||
|
||||
89 CR89 01 // DATE has already been given.
|
||||
0 - accept the new date as the date.
|
||||
1 - leave the old date as the current date.
|
||||
|
||||
8A CR8A01 0 Invalid date specified.
|
||||
CR8A02 0 DATE parameter missing.
|
||||
|
||||
8C CR8C 23 Second DATE found.
|
||||
|
||||
8E CR8E01 23 Date specified incorrectly.
|
||||
|
||||
8F CR8Fxx 23 Invalid BSCA statement.
|
||||
|
||||
8H CR8H 3 More than 9 levels of procedures have been called.
|
||||
|
||||
8J CR8J 0 Invalid // READER parameter.
|
||||
|
||||
8L CR8L 0 Desired system input device being used by other
|
||||
program.
|
||||
|
||||
8P CR8P 0 Output device not defined.
|
||||
|
||||
8U CU8UIP 23 Invalid HIKEY in FILE statement: non-numeric.
|
||||
CR8UKL Parameter length mismatch.
|
||||
CR8ULO Key greater than 29.
|
||||
CR8UPL HIKEY-P greater than 15.
|
||||
CR8USQ HIKEY parameters not in sequence.
|
||||
|
||||
8Y CR8Y 0 Not logging can be done. Log turned off by
|
||||
other program level.
|
||||
|
||||
8- CR8- 0 3 Logging requested but cannot be done.
|
||||
|
||||
90 CR90 0 // PAUSE statement read. Check printer or console
|
||||
for instructions and continue. PAUSE was outside
|
||||
LOAD and RUN.
|
||||
|
||||
91 CR90 0 // PAUSE statement read. Check printer or console
|
||||
for instructions and continue. PAUSE was inside
|
||||
LOAD and RUN.
|
||||
|
||||
92 CR92 23 COMPILE already recieved for this job.
|
||||
|
||||
93 CR93 23 Error in COMPILE statement.
|
||||
|
||||
94 CR94 23 Error in COMPILE statement.
|
||||
|
||||
95 CR95 23 Error in COMPILE statement.
|
||||
|
||||
96 CR96 0 23 System error. An OCL error was found, but the system
|
||||
cannot resolve the error.
|
||||
|
||||
97 CR97 0 Error in LOG statement.
|
||||
|
||||
98 CR98 23 Error in LOG statement.
|
||||
|
||||
99 CR99 0 23 Error in LOG statement.
|
||||
|
||||
9A CR9A 23 Indicated action on last OCL statement read will
|
||||
be ignored due to previous errors detected.
|
||||
|
||||
9C CR9Cxx 123 Incorrect tape volume online.
|
||||
|
||||
9E CR9E 0 Logging device being used by other program level.
|
||||
|
||||
9F CR9F 0 23 Logging device in use by other program.
|
||||
|
||||
9H CR9H 23 Log device in use.
|
||||
|
||||
9J CR9J 0 Error in FORMS statement.
|
||||
|
||||
9L CR9L 0 23 Error in FORMS statement.
|
||||
|
||||
9P CR9P 23 Error in FORMS statement.
|
||||
|
||||
9U CR9U 0 3 Other program has gotten a // IMAGE or other
|
||||
program level is using the printer.
|
||||
|
||||
9Y CR9Y 0 23 Logging device not sysgenned or CCP has it.
|
||||
|
||||
9 CR9 0 23 Same as 9Y.
|
||||
|
||||
9- CR9- 0 3 Other program level received a // FORMS or
|
||||
other level using the printer.
|
||||
|
||||
9' CR9' 0 Same as 9Y.
|
||||
|
||||
A0 CRa0xx 23 Syntax error in FILE statement.
|
||||
|
||||
A1 CRA1xx 23 Keyword error in FILE statement.
|
||||
|
||||
A2 CRA2xx 23 Parameter error on FILE statement.
|
||||
xx gives parameter:
|
||||
01 NAME, 02 UNIT, 03 PACK, 04 LABEL,
|
||||
05 RETAIN, 06 DATE, 07 RECORDS, 08 TRACKS,
|
||||
09 LOCATION, AS ASCII, BL BLKL, CV CONVERT,
|
||||
DF DEFER, DN DENSITY, EN END, PT PARITY,
|
||||
RC RECL, RF RECFM, RL REEL, SP SPLIT,
|
||||
TN TRANSLATE.
|
||||
|
||||
A3 CRA3xx 23 Missing Parameter on FILE statement, xx =
|
||||
NN: NAME, NP: PACK, NU: UNIT, OP: no
|
||||
parameters.
|
||||
|
||||
A4 CRA4xx 23 Invalid parameter combination in FILE statement:
|
||||
AS: ASCII-YES and RECFM-D/DB on 7-track tape
|
||||
AV: ASCII-YES and RECFB-V/VB
|
||||
AY: RECFM-D/DB without ASCII-YES
|
||||
CT: CONVERT-ON and TRANSLATE
|
||||
DI: UNIT says tape but disk parameters given
|
||||
DN: DENSITY-800 not supported.
|
||||
FS: RECFM is fexed and block or rec len less than 18
|
||||
IL: Incorrected RECL or BLKL for RECFM
|
||||
IP: SPLIT or LOCATION used with RECORDS / TRACKS.
|
||||
IR: LABEL, DATE or RETAIN wirh REEL-NL or REEL-NS
|
||||
NS: Not all units are 7-track
|
||||
PC: CONVERT-ON and PARITY-EVEN
|
||||
RC: CONVERT-ON not given with RECFM-V/VB for 7-track
|
||||
SD: DENSITY-1600 invalid for 7-track
|
||||
SL: LOCATION missing or invalid for SPLIT.
|
||||
SM: SPLIT invalid for multivolume files.
|
||||
ST: 7-track paras with 9-track unit
|
||||
SU: SPlit can't be used with 5444
|
||||
TL: TRACKS/LOCATION invalid with unit
|
||||
TP: UNIT is disk but tape paras given
|
||||
TR: TRACKS and RECORDS both given
|
||||
|
||||
A6 CRA6xx 23 Error in FILE statement for multivolumne files.
|
||||
|
||||
A7 CRA7xx 23 Error in IMAGE statement.
|
||||
|
||||
A8 CRA8xx 0 Error in IMAGE statements o disk.
|
||||
|
||||
A9 CRA9xx 0 23 Same as A8.
|
||||
|
||||
AA CRAAxx 23 Same as A8.
|
||||
|
||||
AC CRAC 0 Invalid hex character in chain image.
|
||||
|
||||
AE CRAE 0 23 Same as AC.
|
||||
|
||||
AF CRAF 23 Same as AC.
|
||||
|
||||
AH CRAH 0 Error in IMAGE statement.
|
||||
|
||||
AJ CRAJ 0 23 Same as AH
|
||||
|
||||
AL CRALxx 0 Error in PARTITION statement.
|
||||
|
||||
AP CRMN 0 3 Either reocvery option has has been selected during
|
||||
a job, or OCL errors have occurred for this job.
|
||||
0: Continue iwth next job, or no data cards in
|
||||
reader for this job, otherwise, 3 to cancel.
|
||||
|
||||
AU CRAUxx 23 Error in PARTITION statement.
|
||||
|
||||
A CRA 23 Total number of volumes for a FILE statement
|
||||
exceeds 40 (!).
|
||||
|
||||
A- CRA-xx 0 23 Error in PARTITION statement.
|
||||
|
||||
A' CRA' 3 No space remaining is System work area. Too many
|
||||
FILE statements are in this job.
|
||||
|
||||
C1-C9 IFC1 123 1442 Check, various causes.
|
||||
|
||||
CL UDCLxx 1 3 5445 Data Interchange Utility error
|
||||
|
||||
E7 DKE7 0 3 Incorrect record length for attached 3741
|
||||
|
||||
E8 UTE8xx 1 3 Error in Tape Init VOL statement.
|
||||
|
||||
E9 UTE9xy 0 3 Error during Tape Init Processing.
|
||||
|
||||
F8 DDF8 3 RPG--LIne counter specs omitted and skip past
|
||||
page size for printer.
|
||||
|
||||
F9 CIF9xy 23 Tape drive not available, x = drive #.
|
||||
|
||||
FA CIFA 3 Program requesting Data Recorder, unsupported.
|
||||
|
||||
FC CIFC 3 Program requesting CRT, unsupported.
|
||||
|
||||
FE DDFE 0 3 Program requesting line line on printer that
|
||||
exceeds sysgen value.
|
||||
|
||||
FF RPQ routine error. Press start to continue.
|
||||
|
||||
FH CIFH 123 BSCA line not supported.
|
||||
|
||||
FJ CIFJ01 123 1442 not supported but requested
|
||||
CIFJ02 123 3741 not supported but requested
|
||||
|
||||
FL CIFL 123 Printer/keyboard not supported or unavailable.
|
||||
|
||||
FP CIFP 123 Printer not supported or allocated to other level
|
||||
|
||||
FU CIFU 123 MFCU not supported or allocated to other level
|
||||
|
||||
FY CIFY 23 Device is not supported or in use.
|
||||
|
||||
F CIF 23 Conflict with a resource being used by other level.
|
||||
|
||||
H0-H9 0 23 RPG Programmed halt indicator is on.
|
||||
|
||||
HA CIHA 3 Out of space on $SOURCE during compile.
|
||||
|
||||
HC CIHC 3 Program given on LOAD statement not found.
|
||||
|
||||
HE Hardware error. Simulator has messed up.
|
||||
|
||||
HF CIHF 0 3 // COMPILE read but not required.
|
||||
|
||||
HJ CIHJ01 1 3 Program not found on removable unit, 1:
|
||||
mount new unit and retry.
|
||||
CIHJ02 3 Program not found, but removable unit in use.
|
||||
|
||||
HL CIHL 3 Inquiry request made but program is wrong type.
|
||||
|
||||
HP CIHP 3 Insufficient main storage for program.
|
||||
LMHP 3 $MAINT function out of storage. NOTE: After the
|
||||
cancel, IPL from the system pack or the pack will
|
||||
be unusable.
|
||||
|
||||
HU CIHUxx 3 Source program not found on disk. IF a 1 option
|
||||
is present, you can mount a new removeable pack.
|
||||
|
||||
HY CCHYNN 0 A checkpoint is received and accepted.
|
||||
|
||||
H CCH NN 0 23 A restart has been requested.
|
||||
|
||||
H' CIH' 3 An uninitialized pack has been referenced.
|
||||
|
||||
J0-J9 123 Record with specified match field out of sequence.
|
||||
This is an RPG error, the 2nd digit indicates which
|
||||
RPG file statement the error applies to in the
|
||||
source program. 0=greater than statement 9,
|
||||
otherwise indicates the file statement number.
|
||||
|
||||
JA CIJA 3 Trying to laod a program that requires or allows
|
||||
inquiry while another inquiry program is running
|
||||
in the other level.
|
||||
|
||||
JC CIJCxx 3 Program cannot be run for this reason (xx):
|
||||
01: Must be dedicated and other level active
|
||||
02: Program in other level must be dedicated
|
||||
03: $$RSTR cannot run in level 2
|
||||
04: CHeckpointed program not allowed in level 2
|
||||
05: Program can't run while checkpoint active
|
||||
|
||||
JE CIJE 0 3 Level 1 partition too small.
|
||||
|
||||
JF CIJF 3 Attempt to start inquiry program but keyboard
|
||||
in use.
|
||||
|
||||
JH CIJF 3 Attempt to start program which allows interrupts in
|
||||
level 2.
|
||||
|
||||
JJ CIJJ 3 No object library on pack requested for load.
|
||||
|
||||
JL CIJL 3 Not enough storage for program. DPF only.
|
||||
|
||||
JP System input device in use by other level.
|
||||
|
||||
JU 0123 Cancel request made from interrupt key. 0: ignore
|
||||
1: continue, request ignored
|
||||
|
||||
JY CIJYRD 0 2 Inquiry request made and accepted.
|
||||
|
||||
J- 3 Attempt to run a CCP program, but CCP not running.
|
||||
|
||||
J' 01 3 Inquiry request is completed, interrupted program
|
||||
can now resume.
|
||||
|
||||
L0-L9 123 RPG. Unidentified record, 2nd digit gives file
|
||||
statement number in source program 1-9, 0 means
|
||||
greater than 9. Can also occur if record is out
|
||||
of sequence.
|
||||
|
||||
LA CILA 23 Too little storage for number of files in program.
|
||||
|
||||
LC CILC 23 Too little storage for requested allocation.
|
||||
|
||||
LE CILE 23 No FILE or an incorrect FILE for a file requested
|
||||
by current program.
|
||||
|
||||
LH CILH 23 No space given for an output file on FILE statement.
|
||||
|
||||
LJ CILJ 23 Attempt to output to existing permanent file.
|
||||
|
||||
LL CILL 0 23 Attempt to output over an existing temporary file.
|
||||
|
||||
LP CILP 23 File already exists.
|
||||
|
||||
LU CILU 123 Pack name requested but wrong pack mounted. 1:
|
||||
retry after mounting correct pack.
|
||||
|
||||
LY CILYxx 23 Attempt to allocate space that isn't available.
|
||||
xx=02 means space not available in split cylinder
|
||||
area.
|
||||
|
||||
L LML CP 01 3 $MAINT detected attempt to modify a program on
|
||||
a pack with an active checkpoint.
|
||||
|
||||
L- CIL- 3 Attempt to add a split cylinder to a split cyl
|
||||
file while other level is fiddling with a split
|
||||
cylinder file.
|
||||
|
||||
L' CIl' 23 Trying to allocate a split cylinder file before
|
||||
allocating the first split cylinder file in a group.
|
||||
|
||||
P1-P8 Printer hardware errors, should not occur in sim.
|
||||
|
||||
PC IPPC 0 23 Unprintable character.
|
||||
|
||||
PH CIPH 23 LOCATION plus TRACKS goes past end of pack.
|
||||
|
||||
PJ CIPJxx 1 A Pack is to be remounted, pack name printed before
|
||||
half code, xx= unit.
|
||||
|
||||
PU CIPU 3 Duplicate file names in the FILE statements.
|
||||
|
||||
PY CIPY01 3 ISAM file requires at least 2 tracks.
|
||||
CIPY02 3 ISAM file can't be split cylinder.
|
||||
|
||||
P' CIP'xx 23 Too many scratch or work files.
|
||||
|
||||
U0-U9 0123 RPG. Unidentified record in file, 2nd digit of
|
||||
halt is file statement in RPG source, 0= greater
|
||||
than 9.
|
||||
|
||||
UA CIUA 3 Attempt to create a multivolume file in
|
||||
invalid.
|
||||
|
||||
UC CIUC 3 The printed actived file cannot be found in the
|
||||
list of scratch files.
|
||||
|
||||
UE CIUExx 1 3 PACK parameter does not match pack name on unit.
|
||||
xx = Unit referenced.
|
||||
1 = Mount another pack and continue.
|
||||
|
||||
UF CIUF 3 Disk file referenced by name and date not found.
|
||||
|
||||
UH CIUH 3 Attempt to create multivolume file failed,
|
||||
because name alreayd exists.
|
||||
|
||||
UJ CIUJ 3 A LOCATION was specified for an existing disk file
|
||||
and the file exists but not at that location.
|
||||
|
||||
UL CIUL 3 File on // FILE statement not found, and no size
|
||||
in TRACKS or RECORDS was given.
|
||||
|
||||
UP CIUP 3 Permanent file referenced with RETAIN-S
|
||||
|
||||
UU CIUU 3 Disk Pack not available.
|
||||
|
||||
UY CIUY 3 File is a System/3 BASIC file which must be unique.
|
||||
|
||||
U CIU 3 Existing file: TRACKS/RECORDS or LOCATION mismatch.
|
||||
|
||||
U- General CCP halt. Press start to see subhalt.
|
||||
Refer to CCP manual for more info.
|
||||
|
||||
U' CIU' 23 VTOC is full, or more than 2 multivolume files per
|
||||
pack, or more than 2 ISAM files using HIKEY
|
||||
parameter.
|
||||
|
||||
YH CRYH 0 3 Cards are being punched, but card read from
|
||||
reader was not blank. This means you are trying to
|
||||
punch with a file attached to the CDR device.
|
||||
Unattach the file and take the zero option.
|
||||
|
||||
0 (blank 0) FILE WRITE switch in off position.
|
||||
|
||||
1 (blank 1) Permanent DIsk I/O Error
|
||||
|
||||
2 RC 211 3 COBOL. Out of room on $WORK.
|
||||
RC 212 3 Out of room on $SOURCE.
|
||||
RC 213 3 Out of room on $WORKX.
|
||||
RC 214 3 Subprogram name table greater than 20.
|
||||
RC 219 0 3 C or E level diagnostics during compile.
|
||||
RC 2A1 23 Subscript invalid
|
||||
RC 2A2 23 Negative exponent or 0 degrees in program
|
||||
RC 2F1 23 MFCU File not open or opened improperly
|
||||
RC 2F2 23 1442 File not open or opened improperly
|
||||
RC 2F3 23 1403/5203 File not open or opened improperly
|
||||
RC 2F4 23 5444 Disk File not open or opened improperly
|
||||
RC 2F5 23 5444 File not open or opened improperly
|
||||
RC 2F7 23 5444 File not open or opened improperly
|
||||
RC 2F8 23 Tape File not open or opened improperly
|
||||
RC 2H1 23 OPEN attempted after CLOSE WITH LOCK
|
||||
RC 2H2 23 Error during ACCEPT
|
||||
RC 2H3 23 $$STOP not found
|
||||
RC 2H4 23 CHeckpoint could not be taken.
|
||||
RC 2H5 23 $$STIC not found for ACCEPT
|
||||
RC 2H6 23 Parameter mismatch CALL and USING
|
||||
RC 2H7 23 ACCEPT after /& read
|
||||
RC 2H8 23 OPEN for a file already OPEN
|
||||
RC 2 0 3 Too little core for compile
|
||||
RC 2 1 3 PROCEDURE or DATA division not found.
|
||||
RC 2 3 3 Program has more than 65535 statements (!)
|
||||
RC 2 4 3 Source name on COMPILE statement not found
|
||||
|
||||
3 R 3XX 0 3 COBOL Stop literal. XX is user-specified.
|
||||
0 continues program 3 cancels.
|
||||
|
||||
4 VF 4NF 3 Program not found. Program library and
|
||||
not printed before halt message.
|
||||
|
||||
6 RF 6XX 0 23 FORTRAN stop statement.
|
||||
|
||||
7 RF 701 23 Source member on COMPILE not found
|
||||
RF 702 23 Object program too large for core.
|
||||
|
||||
8 CS 8 1 3 System input device allocated to other level.
|
||||
|
||||
9 CS 9 1 3 System input device has an error. This usually
|
||||
means the card hopper is empty (i.e. EOF on the
|
||||
file attached to the reader but SCP wants more
|
||||
input).
|
||||
|
||||
A DC A 123 Number of characters entered from keyboard
|
||||
incorrect.
|
||||
|
||||
C DD C 0 23 Unprintable character for printer/keyboard.
|
||||
|
||||
E DC E 123 Hardware error, PKB
|
||||
|
||||
F DC F 0 23 End of forms, PKB
|
||||
|
||||
L DD L 0 3 Records with duplicate keys have been loaded
|
||||
into ISAM file. Each dup key is logged followed
|
||||
by blank P halt. 0: continue. Index will
|
||||
contain duplicate keys. 3: cancel, file is
|
||||
not usable, reload it.
|
||||
|
||||
P DD P 0 3 Duplicate key encountered. The key is printed
|
||||
on the log. 0: continue, halt will recur for
|
||||
any other duplicates, then blank L appears.
|
||||
|
||||
U DD U 3 Disk I/O error while sorting ISAM index.
|
||||
|
||||
Y DD Y 3 System error during file termination.
|
||||
|
||||
-0 DD-0XX 3 ISAM multivolume file being used and high key
|
||||
not found for current columme, or does not agree
|
||||
with HIKEY spec. XX=unit number.
|
||||
|
||||
-1 DD-1XX 123 Halt -P occurred and option 0 taken. But, the
|
||||
pack mounted is not a part of volume set.
|
||||
|
||||
-2 DD-2XX 123 Multivolume load sequence error.
|
||||
|
||||
-3 DD-3XX 123 Multivolume load sequence error.
|
||||
|
||||
-4 DD-4XX 0123 Warning that one or more volumes are about to be
|
||||
bypassed.
|
||||
|
||||
-5 DD-5XX 123 Multivolume file not found. 1: mount correct pack.
|
||||
|
||||
-6 DD-6XX 0 23 Warning. ENd of volume and HIKEY not found.
|
||||
|
||||
-7 DD-7XX 1 3 -A halt and option 1 taken. But the pack referenced
|
||||
does not match pack name.
|
||||
|
||||
-8 DD-8XX 3 Multivolume file referenced but file isn't
|
||||
multivolume.
|
||||
|
||||
-9 DD-9XX 3 Add to a multivolumen file, but last pack not
|
||||
mounted.
|
||||
|
||||
-A DD-AXX 1 3 Add to existing multivolume filebut no room.
|
||||
|
||||
-C DD-CXX 3 Multivolume file error. Probably out of sequence
|
||||
volume mounts.
|
||||
|
||||
-E DD-EXX 123 Next volume cannot be processed, because the
|
||||
location is not available or space is not available
|
||||
or there are scratch files on the pack.
|
||||
|
||||
-F DD-Fxx 123 Finished a volume, next cannot be processed, mount
|
||||
the correct pack or cancel.
|
||||
|
||||
-H DD-Hxx 3 HIKEY length does not match file.
|
||||
|
||||
-J DD-Jxx 01 3 First volume referenced is not volumme 1. 0:
|
||||
continue with this volume, 1: mount another pack.
|
||||
|
||||
-L DD-Lxx 3 Output to multivolume, but file isn't multivolume
|
||||
or referenced volume isn't first one of set.
|
||||
|
||||
-P DD-PXX 0123 Mount next volume. XX=unit number. 0: continue
|
||||
bypassing volumes, 1: mount next volume.
|
||||
|
||||
-U DD-UXX 1 3 Halt -J just occurred and 0 or 1 taken. But the
|
||||
pack name is incorrect or the file isn't found.
|
||||
|
||||
- DD- 123 Multivolume key error. Key too low or high for
|
||||
volume.
|
||||
|
||||
-' DD-' 123 Sequential add to multivolume file, but HIKEY
|
||||
record missing on previous volume.
|
||||
|
||||
'0 GM'0DE 3 SYSGEN. I/O Error on reader.
|
||||
GM'0EX 3 SYSGEN. End of extent on MACOUT or $SOURCE.
|
||||
GM'0IC 1 3 SYSGEN. Option dependent on a preceding option, the
|
||||
preceding one was omitted or invalid.
|
||||
GM'0ID 1 3 SYSGEN invalid delimiter.
|
||||
GM'0IK 1 3 SYSGEN invalid keyword.
|
||||
GM'0IR 1 3 SYSGEN invalid option.
|
||||
GM'0IS 1 3 SYSGEN sequence error.
|
||||
GM'0NF 1 3 SYSGEN entry in cols 8-12 not found.
|
||||
GM'0NS 3 SYSGEN Requested source program not found.
|
||||
GM'0EM 1 3 SYSGEN. END statement not found.
|
||||
GM'0NP 3 SYSGEN. Module $SGXP2, $SGXP3, $SGXP4, $SGXP5, or
|
||||
$SGXP6 missing for sysgen, or $MPXP2, $MPXP3 or
|
||||
$MPXP4 missing for macro processor.
|
||||
|
||||
'1 GG'1 3 System Generation Errors.
|
||||
|
||||
'2 0 3 Error during macro processor run.
|
||||
|
||||
'3 3 Invalid 5445 disk label record.
|
||||
|
||||
'4 GG'4EX 3 Out of room on Sysgen, or disk error.
|
||||
|
||||
----------------------- End of haltguide.txt ---------------------------
|
||||
78
S3/readme_s3.txt
Normal file
78
S3/readme_s3.txt
Normal file
@@ -0,0 +1,78 @@
|
||||
Welcome to the IBM System/3 Model 10 SIMH simulator.
|
||||
---------------------------------------------------
|
||||
|
||||
To compile under linux:
|
||||
|
||||
cc s3*.c scp*.c sim_rev.c -o s3
|
||||
|
||||
This code can be compiled and run as a console application using
|
||||
Microsoft Visual C++.
|
||||
|
||||
|
||||
|
||||
To IPL the provided SCP distribution disk:
|
||||
|
||||
./s3
|
||||
sim> at r1 m10scp.dsk
|
||||
sim> at f1 f1f1f1.dsk
|
||||
sim> at lpt print.txt
|
||||
sim> d sr 5471
|
||||
sim> boot r1
|
||||
|
||||
|
||||
// DATE 06/14/01
|
||||
// NOHALT
|
||||
// LOAD $MAINT,R1
|
||||
// RUN
|
||||
// COPY FROM-R1,LIBRARY-ALL,NAME-DIR,TO-PRINT
|
||||
// END
|
||||
|
||||
|
||||
(A printout of the libraries and directories on the SCP DTR
|
||||
disk will be in the file print.txt)
|
||||
|
||||
|
||||
The text file "system3.txt" gives details on the simulators
|
||||
implementation of System/3 hardware.
|
||||
|
||||
A write up on the use of the SCP and the OCL job control language is
|
||||
in the text file "userguide.txt". This includes examples of using the
|
||||
utility programs, and a tutorial guiding you thru a sysgen.
|
||||
|
||||
A nearly complete listing of all possible SCP halts is in the
|
||||
document "haltguide.txt".
|
||||
|
||||
IMPORTANT NOTES:
|
||||
|
||||
1) How to correct typing errors when using the System/3 console:
|
||||
If you make an error, press ESC, which will cancel the current
|
||||
line being typed and print a quote in position 1. Then you
|
||||
can use CTRL/R to retype characters up until the error, then
|
||||
type correctly. Or simply retype the line. BACKSPACE DOES NOT
|
||||
WORK with the SCP.
|
||||
|
||||
2) While the simulator allows disk images to be independently
|
||||
attached to any disk unit, on the real hardware R1 and F1 were on
|
||||
a single spindle, and R2 and F2 likewise. It is not possible using
|
||||
SCP to attach R1 without attaching a disk image to F1 also, because
|
||||
SCP will always look at F1 even when IPLed off R1.
|
||||
|
||||
The OS distributed with the simulator is version 16 of the Model
|
||||
10 SCP. This is sysgenned with support only for R1 and F1. If you
|
||||
do a sysgen to support R2 amd F2 also, you must have images attached
|
||||
to all 4 disks when you IPL, because SCP looks at all drives when
|
||||
it starts up, and you will get an "Unattached Unit" error if you
|
||||
fail to have one attached.
|
||||
|
||||
3) The 1442 card reader had in reality one card input hopper
|
||||
and two stackers. This means the same path is used for reading and
|
||||
punching cards. When punching cards, SCP does a read operation
|
||||
and inspects the card read for blanks, and if it is not blank,
|
||||
issues a YH halt. SCP will not punch data onto non-blank cards.
|
||||
This feature causes problems in the simulator, and as a result
|
||||
if you punch cards from SCP, YOU MUST not have any file attached
|
||||
to the CDR device. Leaving this device unattached presents an
|
||||
infinite supply of blank cards to SCP for punching.
|
||||
|
||||
|
||||
-- End of README_S3.txt --
|
||||
434
S3/s3_cd.c
Normal file
434
S3/s3_cd.c
Normal file
@@ -0,0 +1,434 @@
|
||||
/* s3_cd.c: IBM 1442 card reader/punch
|
||||
|
||||
Copyright (c) 2001 Charles E. Owen
|
||||
Copyright (c) 1993-2001, 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.
|
||||
|
||||
cdr card reader
|
||||
cdp card punch
|
||||
cdp2 card punch stacker 2
|
||||
|
||||
Normally, cards are represented as ASCII text streams terminated by newlines.
|
||||
This allows cards to be created and edited as normal files. Set the EBCDIC
|
||||
flag on the card unit allows cards to be read or punched in EBCDIC format,
|
||||
suitable for binary data.
|
||||
|
||||
*/
|
||||
|
||||
#include "s3_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
extern uint8 M[];
|
||||
extern char ebcdic_to_ascii[256];
|
||||
extern char ascii_to_ebcdic[256];
|
||||
int32 s1sel, s2sel;
|
||||
char rbuf[CBUFSIZE]; /* > CDR_WIDTH */
|
||||
t_stat cdr_svc (UNIT *uptr);
|
||||
t_stat cdr_boot (int32 unitno);
|
||||
t_stat cdr_attach (UNIT *uptr, char *cptr);
|
||||
t_stat cd_reset (DEVICE *dptr);
|
||||
|
||||
int32 DAR; /* Data address register */
|
||||
int32 LCR; /* Length Count Register */
|
||||
int32 lastcard = 0; /* Last card switch */
|
||||
int32 carderr = 0; /* Error switch */
|
||||
int32 pcherror = 0; /* Punch error */
|
||||
int32 notready = 0; /* Not ready error */
|
||||
int32 cdr_ebcdic = 0; /* EBCDIC mode on reader */
|
||||
int32 cdp_ebcdic = 0; /* EBCDIC mode on punch */
|
||||
|
||||
/* Card reader data structures
|
||||
|
||||
cdr_dev CDR descriptor
|
||||
cdr_unit CDR unit descriptor
|
||||
cdr_reg CDR register list
|
||||
*/
|
||||
|
||||
UNIT cdr_unit = {
|
||||
UDATA (&cdr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), 100 };
|
||||
|
||||
REG cdr_reg[] = {
|
||||
{ FLDATA (LAST, lastcard, 0) },
|
||||
{ FLDATA (ERR, carderr, 0) },
|
||||
{ FLDATA (NOTRDY, notready, 0) },
|
||||
{ HRDATA (DAR, DAR, 16) },
|
||||
{ HRDATA (LCR, LCR, 16) },
|
||||
{ FLDATA (EBCDIC, cdr_ebcdic, 0) },
|
||||
{ FLDATA (S2, s2sel, 0) },
|
||||
{ DRDATA (POS, cdr_unit.pos, 31), PV_LEFT },
|
||||
{ DRDATA (TIME, cdr_unit.wait, 24), PV_LEFT },
|
||||
{ BRDATA (BUF, rbuf, 8, 8, CDR_WIDTH) },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE cdr_dev = {
|
||||
"CDR", &cdr_unit, cdr_reg, NULL,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &cd_reset,
|
||||
&cdr_boot, &cdr_attach, NULL };
|
||||
|
||||
/* CDP data structures
|
||||
|
||||
cdp_dev CDP device descriptor
|
||||
cdp_unit CDP unit descriptor
|
||||
cdp_reg CDP register list
|
||||
*/
|
||||
|
||||
UNIT cdp_unit = {
|
||||
UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) };
|
||||
|
||||
REG cdp_reg[] = {
|
||||
{ FLDATA (ERR, pcherror, 0) },
|
||||
{ FLDATA (EBCDIC, cdp_ebcdic, 0) },
|
||||
{ FLDATA (S2, s2sel, 0) },
|
||||
{ FLDATA (NOTRDY, notready, 0) },
|
||||
{ HRDATA (DAR, DAR, 16) },
|
||||
{ HRDATA (LCR, LCR, 16) },
|
||||
{ DRDATA (POS, cdp_unit.pos, 31), PV_LEFT },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE cdp_dev = {
|
||||
"CDP", &cdp_unit, cdp_reg, NULL,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &cd_reset,
|
||||
NULL, NULL, NULL };
|
||||
|
||||
/* Stacker data structures
|
||||
|
||||
stack_dev STACK device descriptor
|
||||
stack_unit STACK unit descriptors
|
||||
stack_reg STACK register list
|
||||
*/
|
||||
|
||||
UNIT stack_unit[] = {
|
||||
{ UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } };
|
||||
|
||||
REG stack_reg[] = {
|
||||
{ DRDATA (POS0, stack_unit[0].pos, 31), PV_LEFT },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE stack_dev = {
|
||||
"CDP2", stack_unit, stack_reg, NULL,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &cd_reset,
|
||||
NULL, NULL, NULL };
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/* 1442: master routine */
|
||||
|
||||
int32 crd (int32 op, int32 m, int32 n, int32 data)
|
||||
{
|
||||
int32 iodata;
|
||||
switch (op) {
|
||||
case 0: /* SIO 1442 */
|
||||
/* if (n == 1)
|
||||
return STOP_IBKPT; */
|
||||
switch (data) { /* Select atacker */
|
||||
case 0x00:
|
||||
break;
|
||||
case 0x01:
|
||||
s2sel = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (n) {
|
||||
case 0x00: /* Feed */
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
case 0x01: /* Read only */
|
||||
if (cdr_ebcdic)
|
||||
iodata = read_card(0, 1);
|
||||
else
|
||||
iodata = read_card(0, 0);
|
||||
break;
|
||||
case 0x02: /* Punch and feed */
|
||||
iodata = punch_card(0, 0);
|
||||
break;
|
||||
case 0x03: /* Read Col Binary */
|
||||
iodata = read_card(0, 1);
|
||||
break;
|
||||
case 0x04: /* Punch no feed */
|
||||
iodata = punch_card(0, 1);
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
return iodata;
|
||||
case 1: /* LIO 1442 */
|
||||
switch (n) {
|
||||
case 0x00: /* Load LCR */
|
||||
LCR = data & 0xffff;
|
||||
break;
|
||||
case 0x04:
|
||||
DAR = data & 0xffff;
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
return SCPE_OK;
|
||||
case 2: /* TIO 1442 */
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x00: /* Error */
|
||||
if (carderr || pcherror || notready)
|
||||
iodata = 1;
|
||||
if ((cdr_unit.flags & UNIT_ATT) == 0)
|
||||
iodata = 1; /* attached? */
|
||||
break;
|
||||
case 0x02: /* Busy */
|
||||
if (sim_is_active (&cdr_unit))
|
||||
iodata = 1;
|
||||
break;
|
||||
default:
|
||||
return (STOP_INVDEV << 16);
|
||||
}
|
||||
return ((SCPE_OK << 16) | iodata);
|
||||
case 3: /* SNS 1442 */
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x01:
|
||||
break;
|
||||
case 0x02:
|
||||
break;
|
||||
case 0x03:
|
||||
if (carderr)
|
||||
iodata |= 0x80;
|
||||
if (lastcard)
|
||||
iodata |= 0x40;
|
||||
if (pcherror)
|
||||
iodata |= 0x20;
|
||||
if ((cdr_unit.flags & UNIT_ATT) == 0)
|
||||
iodata |= 0x08;
|
||||
if (notready)
|
||||
iodata |= 0x08;
|
||||
break;
|
||||
case 0x04:
|
||||
iodata = DAR;
|
||||
break;
|
||||
default:
|
||||
return (STOP_INVDEV << 16);
|
||||
}
|
||||
iodata |= ((SCPE_OK << 16) & 0xffff0000);
|
||||
return (iodata);
|
||||
case 4: /* APL 1442 */
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x00: /* Error */
|
||||
if (carderr || pcherror || notready)
|
||||
iodata = 1;
|
||||
if ((cdr_unit.flags & UNIT_ATT) == 0)
|
||||
iodata = 1; /* attached? */
|
||||
break;
|
||||
case 0x02: /* Busy */
|
||||
if (sim_is_active (&cdr_unit))
|
||||
iodata = 1;
|
||||
break;
|
||||
default:
|
||||
return (STOP_INVDEV << 16);
|
||||
}
|
||||
return ((SCPE_OK << 16) | iodata);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Card read routine
|
||||
mod 0 = ASCII read
|
||||
mod 1 = EBCDIC read
|
||||
*/
|
||||
|
||||
t_stat read_card (int32 ilnt, int32 mod)
|
||||
{
|
||||
int32 i, cnt;
|
||||
t_stat r;
|
||||
|
||||
if (sim_is_active (&cdr_unit)) { /* busy? */
|
||||
sim_cancel (&cdr_unit); /* cancel */
|
||||
if (r = cdr_svc (&cdr_unit)) return r; /* process */
|
||||
}
|
||||
|
||||
if (((cdp_unit.flags & UNIT_ATT) != 0 ||
|
||||
(stack_unit[0].flags & UNIT_ATT) != 0) && /* Punch is attached and */
|
||||
(cdr_unit.flags & UNIT_ATT) == 0) { /* reader is not --- */
|
||||
for (i = 0; i < 80; i++) { /* Assume blank cards in hopper */
|
||||
PutMem(DAR, 0x40);
|
||||
DAR++;
|
||||
}
|
||||
sim_activate (&cdr_unit, cdr_unit.wait); /* activate */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if ((cdr_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */
|
||||
|
||||
lastcard = carderr = notready = s1sel = s2sel = 0; /* default stacker */
|
||||
|
||||
for (i = 0; i < CBUFSIZE; i++) rbuf[i] = 0x20; /* clear buffer */
|
||||
if (mod) {
|
||||
for (i = 0; i < 80; i++) {
|
||||
rbuf[i] = fgetc(cdr_unit.fileref); /* Read EBCDIC */
|
||||
}
|
||||
} else {
|
||||
fgets (rbuf, CBUFSIZE, cdr_unit.fileref); /* read Ascii */
|
||||
}
|
||||
if (feof (cdr_unit.fileref)) { /* eof? */
|
||||
notready = 1;
|
||||
return STOP_NOCD;
|
||||
}
|
||||
if (ferror (cdr_unit.fileref)) { /* error? */
|
||||
perror ("Card reader I/O error");
|
||||
clearerr (cdr_unit.fileref);
|
||||
carderr = 1;
|
||||
return SCPE_OK; }
|
||||
cdr_unit.pos = ftell (cdr_unit.fileref); /* update position */
|
||||
i = getc (cdr_unit.fileref); /* see if more */
|
||||
if (feof (cdr_unit.fileref)) lastcard = 1; /* eof? set flag */
|
||||
fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET);
|
||||
for (i = 0; i < 80; i++) {
|
||||
if (mod == 0) { /* If ASCII mode... */
|
||||
if (rbuf[i] == '\n' || /* remove ASCII CR/LF */
|
||||
rbuf[i] == '\r' ||
|
||||
rbuf[i] == 0x00)
|
||||
rbuf[i] = ' ';
|
||||
rbuf[i] = ascii_to_ebcdic[rbuf[i]]; /* convert to EBCDIC */
|
||||
}
|
||||
PutMem(DAR, rbuf[i]); /* Copy to main memory */
|
||||
DAR++;
|
||||
}
|
||||
sim_activate (&cdr_unit, cdr_unit.wait); /* activate */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Card reader service. If a stacker select is active, copy to the
|
||||
selected stacker. Otherwise, copy to the normal stacker. If the
|
||||
unit is unattached, simply exit.
|
||||
*/
|
||||
|
||||
t_stat cdr_svc (UNIT *uptr)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
if (s2sel) uptr = &stack_unit[0]; /* stacker 1? */
|
||||
else uptr = &stack_unit[0]; /* then default */
|
||||
if ((uptr -> flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
|
||||
for (i = 0; i < CDR_WIDTH; i++) rbuf[i] = ebcdic_to_ascii[rbuf[i]];
|
||||
for (i = CDR_WIDTH - 1; (i >= 0) && (rbuf[i] == ' '); i--) rbuf[i] = 0;
|
||||
rbuf[CDR_WIDTH] = 0; /* null at end */
|
||||
fputs (rbuf, uptr -> fileref); /* write card */
|
||||
fputc ('\n', uptr -> fileref); /* plus new line */
|
||||
if (ferror (uptr -> fileref)) { /* error? */
|
||||
perror ("Card stacker I/O error");
|
||||
clearerr (uptr -> fileref);
|
||||
}
|
||||
uptr -> pos = ftell (uptr -> fileref); /* update position */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Card punch routine
|
||||
|
||||
mod: not used
|
||||
*/
|
||||
|
||||
t_stat punch_card (int32 ilnt, int32 mod)
|
||||
{
|
||||
int32 i, colcount;
|
||||
static char pbuf[CDP_WIDTH + 1]; /* + null */
|
||||
UNIT *uptr;
|
||||
|
||||
if (s2sel) uptr = &stack_unit[0]; /* stack 2? */
|
||||
else uptr = &cdp_unit; /* normal output */
|
||||
if ((uptr -> flags & UNIT_ATT) == 0) { /* Attached? */
|
||||
notready = 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
pcherror = s1sel = notready = 0; /* clear flags */
|
||||
|
||||
colcount = 128 - LCR;
|
||||
for (i = 0; i < colcount; i++) { /* Fetch data */
|
||||
if (cdp_ebcdic)
|
||||
pbuf[i] = GetMem(DAR) & 0xff;
|
||||
else
|
||||
pbuf[i] = ebcdic_to_ascii[GetMem(DAR)];
|
||||
DAR++;
|
||||
}
|
||||
for (i = CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--) pbuf[i] = 0;
|
||||
pbuf[CDP_WIDTH] = 0; /* trailing null */
|
||||
if (!cdp_ebcdic) {
|
||||
fputs (pbuf, uptr -> fileref); /* output card */
|
||||
fputc ('\n', uptr -> fileref); /* plus new line */
|
||||
} else {
|
||||
for (i = 0; i < 80; i++) {
|
||||
fputc(pbuf[i], uptr -> fileref);
|
||||
}
|
||||
}
|
||||
if (ferror (uptr -> fileref)) { /* error? */
|
||||
perror ("Card punch I/O error");
|
||||
clearerr (uptr -> fileref);
|
||||
pcherror = 1;
|
||||
}
|
||||
uptr -> pos = ftell (uptr -> fileref); /* update position */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Select stack routine
|
||||
|
||||
Modifiers have been checked by the caller
|
||||
Modifiers are 1, 2, for the respective stack
|
||||
*/
|
||||
|
||||
t_stat select_stack (int32 ilnt, int32 mod)
|
||||
{
|
||||
if (mod == 1) s1sel = 1;
|
||||
else if (mod == 2) s2sel = 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Card reader/punch reset */
|
||||
|
||||
t_stat cd_reset (DEVICE *dptr)
|
||||
{
|
||||
lastcard = carderr = notready = pcherror = 0; /* clear indicators */
|
||||
s1sel = s2sel = 0; /* clear stacker sel */
|
||||
sim_cancel (&cdr_unit); /* clear reader event */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Card reader attach */
|
||||
|
||||
t_stat cdr_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
carderr = lastcard = notready = 0; /* clear last card */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
t_stat cdr_boot (int32 unitno)
|
||||
{
|
||||
cdr_ebcdic = 1;
|
||||
DAR = 0;
|
||||
LCR = 80;
|
||||
read_card(0, 1);
|
||||
return SCPE_OK;
|
||||
}
|
||||
1825
S3/s3_cpu.c
Normal file
1825
S3/s3_cpu.c
Normal file
File diff suppressed because it is too large
Load Diff
97
S3/s3_defs.h
Normal file
97
S3/s3_defs.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* ibms3_defs.h: IBM System/3 simulator definitions
|
||||
|
||||
Copyright (c) 2001, Charles E. Owen
|
||||
Copyright (c) 1993-2001, 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.
|
||||
|
||||
*/
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_RSRV 1 /* must be 1 */
|
||||
#define STOP_HALT 2 /* HALT */
|
||||
#define STOP_IBKPT 3 /* breakpoint */
|
||||
#define STOP_INVOP 4 /* program check - invalid op */
|
||||
#define STOP_INVQ 5 /* Prog check - invalid Q */
|
||||
#define STOP_INVADDR 6 /* Prog check - invalid addr */
|
||||
#define STOP_INVDEV 7 /* Prog check - invalid dev cmd */
|
||||
#define STOP_NOCD 8 /* ATTN card reader */
|
||||
#define RESET_INTERRUPT 77 /* special return from SIO */
|
||||
|
||||
/* Memory */
|
||||
|
||||
#define MAXMEMSIZE 65536 /* max memory size */
|
||||
#define AMASK (MAXMEMSIZE - 1) /* logical addr mask */
|
||||
#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
|
||||
#define MAX_DECIMAL_DIGITS 31 /* max size of a decimal number */
|
||||
#define CDR_WIDTH 80 /* Max card size */
|
||||
#define CDP_WIDTH 80 /* Punch width */
|
||||
#define LPT_WIDTH 132
|
||||
#define CCT_LNT 132
|
||||
|
||||
#define DSK_SECTSIZE 256 /* Sector length */
|
||||
#define DSK_CYLSIZE 256*48 /* Cylinder length */
|
||||
|
||||
/* I/O structure
|
||||
|
||||
The I/O structure is tied together by dev_table, indexed by
|
||||
the device number. Each entry in dev_table consists of
|
||||
|
||||
level Interrupt level for device (0-7)
|
||||
priority Priority for device (1-8)
|
||||
routine IOT action routine
|
||||
*/
|
||||
|
||||
struct ndev {
|
||||
int32 level; /* interrupt level */
|
||||
int32 pri; /* Device priority */
|
||||
int32 (*routine)(); /* dispatch routine */
|
||||
};
|
||||
|
||||
/* Structure to define operation codes */
|
||||
|
||||
struct opdef {
|
||||
char op[6]; /* Mnemonic for op */
|
||||
int32 opmask; /* Bits set on in opcode */
|
||||
int32 q; /* Qbyte */
|
||||
int32 form; /* Forms are:
|
||||
0 - 1-byte hex operand
|
||||
1 - 1-byte register addr, A-Addr
|
||||
2 - A-addr,B-addr,Qbyte
|
||||
3 - A-addr,Qbyte
|
||||
4 - da,m,n
|
||||
5 - da,m,n,cc
|
||||
6 - da,m,n,A-addr
|
||||
7 - 1-address implict Q
|
||||
8 - 2-address implict Q */
|
||||
int32 group; /* Group Code:
|
||||
0 - Command Format (0xFx)
|
||||
1 - 1-address A (0x<C,D,E>x)
|
||||
2 - 2-address (0x<0,1,2,4,5,6,8,9,A>x)
|
||||
3 - 1-address B (0x<3,7,B>x) */
|
||||
};
|
||||
|
||||
779
S3/s3_disk.c
Normal file
779
S3/s3_disk.c
Normal file
@@ -0,0 +1,779 @@
|
||||
/* s3_disk.c: IBM 5444 Disk Drives
|
||||
|
||||
Copyright (c) 2001 Charles E. Owen
|
||||
Copyright (c) 1993-2001, 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.
|
||||
|
||||
r1 Removeable disk 1
|
||||
f1 Fixed disk 1
|
||||
r2 Removeable disk 2
|
||||
f2 Fixed disk 2
|
||||
*/
|
||||
|
||||
#include "s3_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
extern uint8 M[];
|
||||
extern int32 IAR[], level;
|
||||
extern FILE *trace;
|
||||
extern int32 debug_reg;
|
||||
char dbuf[DSK_SECTSIZE]; /* Disk buffer */
|
||||
t_stat r1_svc (UNIT *uptr);
|
||||
t_stat r1_boot (int32 unitno);
|
||||
t_stat r1_attach (UNIT *uptr, char *cptr);
|
||||
t_stat r1_reset (DEVICE *dptr);
|
||||
t_stat f1_svc (UNIT *uptr);
|
||||
t_stat f1_boot (int32 unitno);
|
||||
t_stat f1_attach (UNIT *uptr, char *cptr);
|
||||
t_stat f1_reset (DEVICE *dptr);
|
||||
t_stat r2_svc (UNIT *uptr);
|
||||
t_stat r2_boot (int32 unitno);
|
||||
t_stat r2_attach (UNIT *uptr, char *cptr);
|
||||
t_stat r2_reset (DEVICE *dptr);
|
||||
t_stat f2_svc (UNIT *uptr);
|
||||
t_stat f2_boot (int32 unitno);
|
||||
t_stat f2_attach (UNIT *uptr, char *cptr);
|
||||
t_stat f2_reset (DEVICE *dptr);
|
||||
|
||||
char opstr[5][5] = { "SIO", "LIO", "TIO", "SNS", "APL" };
|
||||
|
||||
int32 DDAR[2]; /* Data address register */
|
||||
int32 DCAR[2]; /* Disk Control Address Register */
|
||||
int32 diskerr[2] = { 0, 0 }; /* Error status */
|
||||
int32 notrdy[2] = { 0, 0 }; /* Not ready error */
|
||||
int32 seekbusy[2] = { 0, 0 }; /* Drive busy flags */
|
||||
int32 seekhead[2] = { 0, 0 }; /* Disk head 0,1 */
|
||||
int32 found[2] = { 0, 0 }; /* Scan found bit */
|
||||
int32 RIDsect[2] = { 0, 0 }; /* for Read ID */
|
||||
|
||||
/* Disk data structures
|
||||
|
||||
xy_dev CDR descriptor
|
||||
xy_unit CDR unit descriptor
|
||||
xy_reg CDR register list
|
||||
|
||||
x = F or R
|
||||
y = 1 or 2
|
||||
*/
|
||||
|
||||
UNIT r1_unit = {
|
||||
UDATA (&r1_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
|
||||
|
||||
REG r1_reg[] = {
|
||||
{ FLDATA (NOTRDY, notrdy[0], 0) },
|
||||
{ FLDATA (SEEK, seekbusy[0], 0) },
|
||||
{ HRDATA (DAR, DDAR[0], 16) },
|
||||
{ HRDATA (CAR, DCAR[0], 16) },
|
||||
{ HRDATA (ERR, diskerr[0], 16) },
|
||||
{ DRDATA (CYL, r1_unit.u3, 8) },
|
||||
{ DRDATA (HEAD, seekhead[0], 8) },
|
||||
{ DRDATA (POS, r1_unit.pos, 31), PV_LEFT },
|
||||
{ DRDATA (TIME, r1_unit.wait, 24), PV_LEFT },
|
||||
{ BRDATA (BUF, dbuf, 8, 8, 256) },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE r1_dev = {
|
||||
"R1", &r1_unit, r1_reg, NULL,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &r1_reset,
|
||||
&r1_boot, &r1_attach, NULL };
|
||||
|
||||
UNIT f1_unit = {
|
||||
UDATA (&f1_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
|
||||
|
||||
REG f1_reg[] = {
|
||||
{ FLDATA (NOTRDY, notrdy[0], 0) },
|
||||
{ FLDATA (SEEK, seekbusy[0], 0) },
|
||||
{ HRDATA (DAR, DDAR[0], 16) },
|
||||
{ HRDATA (CAR, DCAR[0], 16) },
|
||||
{ HRDATA (ERR, diskerr[0], 16) },
|
||||
{ DRDATA (CYL, f1_unit.u3, 8) },
|
||||
{ DRDATA (HEAD, seekhead[0], 8) },
|
||||
{ DRDATA (POS, f1_unit.pos, 31), PV_LEFT },
|
||||
{ DRDATA (TIME, f1_unit.wait, 24), PV_LEFT },
|
||||
{ BRDATA (BUF, dbuf, 8, 8, 256) },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE f1_dev = {
|
||||
"F1", &f1_unit, f1_reg, NULL,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &f1_reset,
|
||||
&f1_boot, &f1_attach, NULL };
|
||||
|
||||
UNIT r2_unit = {
|
||||
UDATA (&r2_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
|
||||
|
||||
REG r2_reg[] = {
|
||||
{ FLDATA (NOTRDY, notrdy[1], 0) },
|
||||
{ FLDATA (SEEK, seekbusy[1], 0) },
|
||||
{ HRDATA (DAR, DDAR[1], 16) },
|
||||
{ HRDATA (CAR, DCAR[1], 16) },
|
||||
{ HRDATA (ERR, diskerr[1], 16) },
|
||||
{ DRDATA (CYL, r2_unit.u3, 8) },
|
||||
{ DRDATA (HEAD, seekhead[1], 8) },
|
||||
{ DRDATA (POS, r2_unit.pos, 31), PV_LEFT },
|
||||
{ DRDATA (TIME, r2_unit.wait, 24), PV_LEFT },
|
||||
{ BRDATA (BUF, dbuf, 8, 8, 256) },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE r2_dev = {
|
||||
"R2", &r2_unit, r2_reg, NULL,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &r2_reset,
|
||||
&r2_boot, &r2_attach, NULL };
|
||||
|
||||
UNIT f2_unit = {
|
||||
UDATA (&f2_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
|
||||
|
||||
REG f2_reg[] = {
|
||||
{ FLDATA (NOTRDY, notrdy[1], 0) },
|
||||
{ FLDATA (SEEK, seekbusy[1], 0) },
|
||||
{ HRDATA (DAR, DDAR[1], 16) },
|
||||
{ HRDATA (CAR, DCAR[1], 16) },
|
||||
{ HRDATA (ERR, diskerr[1], 16) },
|
||||
{ DRDATA (CYL, f2_unit.u3, 8) },
|
||||
{ DRDATA (HEAD, seekhead[1], 8) },
|
||||
{ DRDATA (POS, f2_unit.pos, 31), PV_LEFT },
|
||||
{ DRDATA (TIME, f2_unit.wait, 24), PV_LEFT },
|
||||
{ BRDATA (BUF, dbuf, 8, 8, 256) },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE f2_dev = {
|
||||
"F2", &f2_unit, f2_reg, NULL,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &f2_reset,
|
||||
&f2_boot, &f2_attach, NULL };
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/* 5444: master routines */
|
||||
|
||||
int32 dsk1 (int32 op, int32 m, int32 n, int32 data)
|
||||
{
|
||||
int32 r;
|
||||
|
||||
r = dsk(0, op, m, n, data);
|
||||
return (r);
|
||||
}
|
||||
|
||||
int32 dsk2 (int32 op, int32 m, int32 n, int32 data)
|
||||
{
|
||||
int32 r;
|
||||
|
||||
r = dsk(1, op, m, n, data);
|
||||
return (r);
|
||||
}
|
||||
|
||||
/* 5444: operational routine */
|
||||
|
||||
int32 dsk (int32 disk, int32 op, int32 m, int32 n, int32 data)
|
||||
{
|
||||
int32 iodata, i, j, u, sect, nsects, addr, r, c, res;
|
||||
int32 F, C, S, N, usave;
|
||||
UNIT *uptr;
|
||||
|
||||
u = m;
|
||||
if (disk == 1) u += 2;
|
||||
F = GetMem(DCAR[disk]+0); /* Flag bits */
|
||||
C = GetMem(DCAR[disk]+1); /* Cylinder */
|
||||
S = GetMem(DCAR[disk]+2); /* Sector */
|
||||
N = GetMem(DCAR[disk]+3); /* Number of sectors */
|
||||
switch (u) {
|
||||
case 0:
|
||||
uptr = r1_dev.units;
|
||||
break;
|
||||
case 1:
|
||||
uptr = f1_dev.units;
|
||||
break;
|
||||
case 2:
|
||||
uptr = r2_dev.units;
|
||||
break;
|
||||
case 3:
|
||||
uptr = f2_dev.units;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (debug_reg & 0x02)
|
||||
fprintf(trace, "==> %04X %s %01X,%d,%04X DAR=%04X CAR=%04X C=%02X, S=%02X, N=%02X\n",
|
||||
IAR[level],
|
||||
opstr[op],
|
||||
m, n, data,
|
||||
DDAR[disk],
|
||||
DCAR[disk],
|
||||
C, S, N);
|
||||
|
||||
switch (op) {
|
||||
|
||||
/* SIO 5444 */
|
||||
case 0:
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT;
|
||||
diskerr[disk] = 0; /* SIO resets errors */
|
||||
found[disk] = 0; /* ... and found bit */
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x00: /* Seek */
|
||||
if (S & 0x80)
|
||||
seekhead[disk] = 1;
|
||||
else
|
||||
seekhead[disk] = 0;
|
||||
if (S & 1) {
|
||||
uptr -> u3 += N;
|
||||
} else {
|
||||
uptr -> u3 -= N;
|
||||
}
|
||||
if (uptr -> u3 < 0)
|
||||
uptr -> u3 = 0;
|
||||
if (uptr -> u3 > 203) {
|
||||
uptr -> u3 = 0;
|
||||
diskerr[disk] |= 0x0100;
|
||||
if (debug_reg & 0x02)
|
||||
fprintf(trace, "==> Seek Past End of Disk\n");
|
||||
}
|
||||
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
|
||||
/* Seek arms are the same for both disks on a drive:
|
||||
update the other arm */
|
||||
|
||||
usave = uptr -> u3;
|
||||
if (u == 0) uptr = f1_dev.units;
|
||||
if (u == 1) uptr = r1_dev.units;
|
||||
if (u == 2) uptr = f2_dev.units;
|
||||
if (u == 3) uptr = r2_dev.units;
|
||||
uptr -> u3 = usave;
|
||||
|
||||
seekbusy[disk] = 1;
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
|
||||
case 0x01: /* Read */
|
||||
switch (data) {
|
||||
case 0: /* Read data */
|
||||
sect = (S >> 2) & 0x3F;
|
||||
nsects = N + 1;
|
||||
addr = DDAR[disk];
|
||||
|
||||
for (i = 0; i < nsects; i++) {
|
||||
r = read_sector(uptr, dbuf, sect);
|
||||
if (r != 1 || uptr->u3 != C) {
|
||||
diskerr[disk] |= 0x0800;
|
||||
break;
|
||||
}
|
||||
for (j = 0; j < DSK_SECTSIZE; j++) {
|
||||
PutMem(addr, dbuf[j]);
|
||||
addr++;
|
||||
}
|
||||
|
||||
if ((sect == 55) ) { /* HJS MODS */
|
||||
S = sect;
|
||||
N = nsects - i - 2;
|
||||
if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
|
||||
DDAR[disk] = addr & 0xFFFF; /* HJS mod */
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
sect++;
|
||||
S = sect - 1;
|
||||
N = nsects - i - 2;
|
||||
if (sect == 24)
|
||||
sect = 32;
|
||||
}
|
||||
DDAR[disk] = addr & 0xFFFF; /* HJS mod */
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
case 1: /* Read ID */
|
||||
if (uptr -> u3 > 0 && uptr -> u3 < 4)
|
||||
PutMem(DCAR[disk], 1);
|
||||
else
|
||||
PutMem(DCAR[disk], 0);
|
||||
PutMem(DCAR[disk]+1, uptr -> u3);
|
||||
PutMem(DCAR[disk]+2, RIDsect[disk]);
|
||||
RIDsect[disk]++;
|
||||
if (RIDsect[disk] > 23)
|
||||
RIDsect[disk] = 32;
|
||||
if (RIDsect[disk] > 55)
|
||||
RIDsect[disk] = 0;
|
||||
break;
|
||||
case 2: /* Read Diagnostic */
|
||||
iodata = STOP_INVDEV;
|
||||
break;
|
||||
case 3: /* Verify */
|
||||
sect = (S >> 2) & 0x3F;
|
||||
nsects = N + 1;
|
||||
addr = DDAR[disk];
|
||||
for (i = 0; i < nsects; i++) {
|
||||
r = read_sector(uptr, dbuf, sect);
|
||||
if (r != 1 || uptr->u3 != C) {
|
||||
diskerr[disk] |= 0x0800;
|
||||
break;
|
||||
}
|
||||
if ((sect == 55) ) { /* HJS MODS */
|
||||
S = sect;
|
||||
N = nsects - i - 2;
|
||||
if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
}
|
||||
sect++;
|
||||
S = sect - 1;
|
||||
N = nsects - i - 2;
|
||||
if (sect == 24)
|
||||
sect = 32;
|
||||
}
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
break;
|
||||
case 0x02: /* Write */
|
||||
switch (data) {
|
||||
case 0: /* Write Data */
|
||||
sect = (S >> 2) & 0x3F;
|
||||
nsects = N + 1;
|
||||
addr = DDAR[disk];
|
||||
for (i = 0; i < nsects; i++) {
|
||||
for (j = 0; j < DSK_SECTSIZE; j++) {
|
||||
dbuf[j] = GetMem(addr);
|
||||
addr++;
|
||||
}
|
||||
r = write_sector(uptr, dbuf, sect);
|
||||
if (r != 1 || uptr->u3 != C) {
|
||||
diskerr[disk] |= 0x0400;
|
||||
break;
|
||||
}
|
||||
if ((sect == 55) ) { /* HJS MODS */
|
||||
S = sect;
|
||||
N = nsects - i - 2;
|
||||
if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
}
|
||||
sect++;
|
||||
S = sect - 1;
|
||||
N = nsects - i - 2;
|
||||
if (sect == 24)
|
||||
sect = 32;
|
||||
}
|
||||
DDAR[disk] = addr & 0xFFFF; /* HJS mod */
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
break;
|
||||
case 1: /* Write identifier */
|
||||
if (seekhead[disk] == 0)
|
||||
S = 0;
|
||||
else
|
||||
S = 0x80;
|
||||
N = 23;
|
||||
|
||||
sect = (S >> 2) & 0x3F;
|
||||
nsects = N + 1;
|
||||
addr = DDAR[disk];
|
||||
for (i = 0; i < nsects; i++) {
|
||||
for (j = 0; j < DSK_SECTSIZE; j++) {
|
||||
dbuf[j] = GetMem(addr);
|
||||
}
|
||||
r = write_sector(uptr, dbuf, sect);
|
||||
if (r != 1) {
|
||||
diskerr[disk] |= 0x0400;
|
||||
break;
|
||||
}
|
||||
if ((sect == 55) ) {
|
||||
S = sect;
|
||||
N = nsects - i - 2;
|
||||
if (N > 0) diskerr[disk] |= 0x0020;
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
}
|
||||
sect++;
|
||||
S = sect - 1;
|
||||
N = nsects - i - 2;
|
||||
if (sect == 24)
|
||||
sect = 32;
|
||||
}
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
break;
|
||||
case 0x03: /* Scan */
|
||||
sect = (S >> 2) & 0x3F;
|
||||
nsects = N + 1;
|
||||
addr = DDAR[disk];
|
||||
for (i = 0; i < nsects; i++) {
|
||||
r = read_sector(uptr, dbuf, sect);
|
||||
if (r != 1 || uptr->u3 != C) {
|
||||
diskerr[disk] |= 0x0800;
|
||||
break;
|
||||
}
|
||||
res = 0;
|
||||
for (j = 0; j < DSK_SECTSIZE; j++) {
|
||||
c = GetMem(addr);
|
||||
if (j != 0xff) {
|
||||
if (dbuf[i] < c)
|
||||
res = 1;
|
||||
if (dbuf[i] > c)
|
||||
res = 3;
|
||||
}
|
||||
addr++;
|
||||
}
|
||||
if (res == 0)
|
||||
found[disk] = 1;
|
||||
if (res == data)
|
||||
break;
|
||||
if ((sect == 55) ) { /* HJS MODS */
|
||||
S = sect;
|
||||
N = nsects - i - 2;
|
||||
if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
}
|
||||
sect++;
|
||||
S = sect - 1;
|
||||
N = nsects - i - 2;
|
||||
if (sect == 24)
|
||||
sect = 32;
|
||||
}
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
return iodata;
|
||||
|
||||
/* LIO 5444 */
|
||||
case 1:
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT;
|
||||
switch (n) {
|
||||
case 0x04: /* Data Addr */
|
||||
DDAR[disk] = data;
|
||||
break;
|
||||
case 0x06: /* Control Addr */
|
||||
DCAR[disk] = data;
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
return SCPE_OK;
|
||||
case 2: /* TIO 5444 */
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT << 16;
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x00: /* Error */
|
||||
if (diskerr[disk] || notrdy[disk])
|
||||
iodata = 1;
|
||||
if ((uptr -> flags & UNIT_ATT) == 0)
|
||||
iodata = 1;
|
||||
break;
|
||||
case 0x02: /* Busy */
|
||||
if (sim_is_active (uptr))
|
||||
iodata = 1;
|
||||
break;
|
||||
case 0x04:
|
||||
if (found[disk])
|
||||
iodata = 1;
|
||||
break;
|
||||
default:
|
||||
return (STOP_INVDEV << 16);
|
||||
}
|
||||
return ((SCPE_OK << 16) | iodata);
|
||||
|
||||
/* SNS 5444 */
|
||||
case 3:
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT << 16;
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x01:
|
||||
break;
|
||||
case 0x02:
|
||||
iodata = diskerr[disk];
|
||||
if (notrdy[disk])
|
||||
iodata |= 0x4000;
|
||||
if ((uptr -> flags & UNIT_ATT) == 0)
|
||||
iodata |= 0x4000;
|
||||
if (seekbusy[disk])
|
||||
iodata |= 0x0010;
|
||||
if (uptr -> u3 == 0)
|
||||
iodata |= 0x0040;
|
||||
break;
|
||||
case 0x03:
|
||||
iodata = 0;
|
||||
break;
|
||||
case 0x04:
|
||||
iodata = DDAR[disk];
|
||||
break;
|
||||
case 0x06:
|
||||
iodata = DCAR[disk];
|
||||
break;
|
||||
default:
|
||||
return (STOP_INVDEV << 16);
|
||||
}
|
||||
iodata |= ((SCPE_OK << 16) & 0xffff0000);
|
||||
return (iodata);
|
||||
|
||||
/* APL 5444 */
|
||||
case 4:
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT << 16;
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x00: /* Error */
|
||||
if (diskerr[disk] || notrdy[disk])
|
||||
iodata = 1;
|
||||
if ((uptr -> flags & UNIT_ATT) == 0)
|
||||
iodata = 1;
|
||||
break;
|
||||
case 0x02: /* Busy */
|
||||
if (sim_is_active (uptr))
|
||||
iodata = 1;
|
||||
break;
|
||||
default:
|
||||
return (STOP_INVDEV << 16);
|
||||
}
|
||||
return ((SCPE_OK << 16) | iodata);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disk unit service. If a stacker select is active, copy to the
|
||||
selected stacker. Otherwise, copy to the normal stacker. If the
|
||||
unit is unattached, simply exit.
|
||||
*/
|
||||
|
||||
t_stat r1_svc (UNIT *uptr)
|
||||
{
|
||||
seekbusy[0] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f1_svc (UNIT *uptr)
|
||||
{
|
||||
seekbusy[0] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat r2_svc (UNIT *uptr)
|
||||
{
|
||||
seekbusy[1] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f2_svc (UNIT *uptr)
|
||||
{
|
||||
seekbusy[1] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Disk reset */
|
||||
|
||||
t_stat r1_reset (DEVICE *dptr)
|
||||
{
|
||||
diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */
|
||||
found[0] = 0;
|
||||
sim_cancel (&r1_unit); /* clear event */
|
||||
r1_unit.u3 = 0; /* cylinder 0 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f1_reset (DEVICE *dptr)
|
||||
{
|
||||
diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */
|
||||
found[0] = 0;
|
||||
sim_cancel (&f1_unit); /* clear event */
|
||||
f1_unit.u3 = 0; /* cylinder 0 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat r2_reset (DEVICE *dptr)
|
||||
{
|
||||
diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */
|
||||
found[1] = 0;
|
||||
sim_cancel (&r2_unit); /* clear event */
|
||||
r2_unit.u3 = 0; /* cylinder 0 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f2_reset (DEVICE *dptr)
|
||||
{
|
||||
diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */
|
||||
found[1] = 0;
|
||||
sim_cancel (&f2_unit); /* clear event */
|
||||
f2_unit.u3 = 0; /* cylinder 0 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Disk unit attach */
|
||||
|
||||
t_stat r1_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */
|
||||
found[0] = 0;
|
||||
uptr -> u3 = 0; /* cylinder 0 */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
t_stat f1_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */
|
||||
found[0] = 0;
|
||||
uptr -> u3 = 0; /* cylinder 0 */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
t_stat r2_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */
|
||||
found[1] = 0;
|
||||
uptr -> u3 = 0; /* cylinder 0 */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
t_stat f2_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */
|
||||
found[1] = 0;
|
||||
uptr -> u3 = 0; /* cylinder 0 */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
t_stat r1_boot (int32 unitno)
|
||||
{
|
||||
int i;
|
||||
r1_unit.u3 = 0;
|
||||
read_sector(r1_dev.units, dbuf, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
M[i] = dbuf[i];
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f1_boot (int32 unitno)
|
||||
{
|
||||
int i;
|
||||
f1_unit.u3 = 0;
|
||||
read_sector(f1_dev.units, dbuf, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
M[i] = dbuf[i];
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat r2_boot (int32 unitno)
|
||||
{
|
||||
int i;
|
||||
r2_unit.u3 = 0;
|
||||
read_sector(r2_dev.units, dbuf, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
M[i] = dbuf[i];
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f2_boot (int32 unitno)
|
||||
{
|
||||
int i;
|
||||
f2_unit.u3 = 0;
|
||||
read_sector(f2_dev.units, dbuf, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
M[i] = dbuf[i];
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Raw Disk Data In/Out */
|
||||
|
||||
int32 read_sector(UNIT *uptr, char *dbuf, int32 sect)
|
||||
{
|
||||
static int32 rtn, realsect;
|
||||
static long pos;
|
||||
|
||||
/* calculate real sector no */
|
||||
if (sect > 23)
|
||||
realsect = sect - 8;
|
||||
else
|
||||
realsect = sect;
|
||||
/* physically read the sector */
|
||||
pos = DSK_CYLSIZE * uptr -> u3;
|
||||
pos += DSK_SECTSIZE * realsect;
|
||||
rtn = fseek(uptr -> fileref, pos, 0);
|
||||
rtn = fread(dbuf, DSK_SECTSIZE, 1, uptr -> fileref);
|
||||
return (rtn);
|
||||
}
|
||||
|
||||
int32 write_sector(UNIT *uptr, char *dbuf, int32 sect)
|
||||
{
|
||||
static int32 rtn, realsect;
|
||||
static long pos;
|
||||
|
||||
/* calculate real sector no */
|
||||
if (sect > 23)
|
||||
realsect = sect - 8;
|
||||
else
|
||||
realsect = sect;
|
||||
if (uptr -> u3 == 0 && realsect == 32)
|
||||
rtn = 0;
|
||||
/* physically write the sector */
|
||||
pos = DSK_CYLSIZE * uptr -> u3;
|
||||
pos += DSK_SECTSIZE * realsect;
|
||||
rtn = fseek(uptr -> fileref, pos, 0);
|
||||
rtn = fwrite(dbuf, DSK_SECTSIZE, 1, uptr -> fileref);
|
||||
return (rtn);
|
||||
}
|
||||
349
S3/s3_lp.c
Normal file
349
S3/s3_lp.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/* s3_lp.c: IBM 1403 line printer simulator
|
||||
|
||||
Copyright (c) 2001 Charles E. Owen
|
||||
Copyright (c) 1993-2001, 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 1403 line printer
|
||||
|
||||
*/
|
||||
|
||||
#include "s3_defs.h"
|
||||
|
||||
extern uint8 M[];
|
||||
extern char bcd_to_ascii[64];
|
||||
extern int32 iochk, ind[64];
|
||||
int32 cct[CCT_LNT] = { 03 };
|
||||
int32 cctlnt = 66, cctptr = 0, lines = 0, lflag = 0;
|
||||
t_stat lpt_reset (DEVICE *dptr);
|
||||
t_stat lpt_attach (UNIT *uptr, char *cptr);
|
||||
t_stat space (int32 lines, int32 lflag);
|
||||
extern unsigned char ebcdic_to_ascii[256];
|
||||
|
||||
#define UNIT_V_PCHAIN (UNIT_V_UF + 0)
|
||||
#define UNIT_M_PCHAIN 03
|
||||
#define M_UCS 00 /* Universal */
|
||||
#define M_PCF 00 /* full */
|
||||
#define M_PCA 01 /* business */
|
||||
#define M_PCH 02 /* Fortran */
|
||||
#define UNIT_PCHAIN (UNIT_M_PCHAIN << UNIT_V_PCHAIN)
|
||||
#define UCS (M_UCS << UNIT_V_PCHAIN)
|
||||
#define PCF (M_PCF << UNIT_V_PCHAIN)
|
||||
#define PCA (M_PCA << UNIT_V_PCHAIN)
|
||||
#define PCH (M_PCH << UNIT_V_PCHAIN)
|
||||
#define GET_PCHAIN(x) (((x) >> UNIT_V_PCHAIN) & UNIT_M_PCHAIN)
|
||||
#define CHP(ch,val) ((val) & (1 << (ch)))
|
||||
|
||||
int32 LPDAR; /* Data Address */
|
||||
int32 LPFLR; /* Forms Length */
|
||||
int32 LPIAR; /* Image address */
|
||||
int32 linectr; /* current line # */
|
||||
int32 lpterror = 0;
|
||||
int32 CC9 = 0;
|
||||
int32 CC12 = 0;
|
||||
|
||||
/* LPT data structures
|
||||
|
||||
lpt_dev LPT device descriptor
|
||||
lpt_unit LPT unit descriptor
|
||||
lpt_reg LPT register list
|
||||
*/
|
||||
|
||||
UNIT lpt_unit = {
|
||||
UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) };
|
||||
|
||||
REG lpt_reg[] = {
|
||||
{ FLDATA (ERR, lpterror, 0) },
|
||||
{ HRDATA (LPDAR, LPDAR, 16) },
|
||||
{ HRDATA (LPFLR, LPFLR, 8) },
|
||||
{ HRDATA (LPIAR, LPIAR, 16) },
|
||||
{ DRDATA (LINECT, linectr, 8) },
|
||||
{ DRDATA (POS, lpt_unit.pos, 31), PV_LEFT },
|
||||
{ BRDATA (CCT, cct, 8, 32, CCT_LNT) },
|
||||
{ DRDATA (LINES, lines, 8), PV_LEFT },
|
||||
{ DRDATA (CCTP, cctptr, 8), PV_LEFT },
|
||||
{ DRDATA (CCTL, cctlnt, 8), REG_RO + PV_LEFT },
|
||||
{ GRDATA (CHAIN, lpt_unit.flags, 10, 2, UNIT_V_PCHAIN), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB lpt_mod[] = {
|
||||
{ UNIT_PCHAIN, UCS, "UCS", "UCS", NULL },
|
||||
{ UNIT_PCHAIN, PCA, "A chain", "PCA", NULL },
|
||||
{ UNIT_PCHAIN, PCH, "H chain", "PCH", NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE lpt_dev = {
|
||||
"LPT", &lpt_unit, lpt_reg, lpt_mod,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &lpt_reset,
|
||||
NULL, NULL, NULL };
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/* Printer: master routine */
|
||||
|
||||
int32 lpt (int32 op, int32 m, int32 n, int32 data)
|
||||
{
|
||||
int32 iodata, c, ec, ac;
|
||||
switch (op) {
|
||||
case 0: /* SIO 1403 */
|
||||
iodata = 0;
|
||||
printf("\0");
|
||||
switch (n) {
|
||||
case 0x00: /* Spacing only */
|
||||
if (data > 0 && data < 4)
|
||||
iodata = carriage_control(2, data);
|
||||
break;
|
||||
case 0x02: /* Print & space */
|
||||
iodata = write_line(0, 0);
|
||||
if (data > 3) data = 0;
|
||||
if (iodata == SCPE_OK)
|
||||
iodata = carriage_control(2, data);
|
||||
break;
|
||||
case 0x04: /* Skip only */
|
||||
iodata = carriage_control(4, data);
|
||||
break;
|
||||
case 0x06: /* Print and skip */
|
||||
iodata = write_line(0, 0);
|
||||
if (iodata == SCPE_OK)
|
||||
iodata = carriage_control(4, data);
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
return iodata;
|
||||
case 1: /* LIO 1403 */
|
||||
switch (n) {
|
||||
case 0x00: /* LPFLR */
|
||||
LPFLR = (data >> 8) & 0xff;
|
||||
break;
|
||||
case 0x04:
|
||||
LPIAR = data & 0xffff;
|
||||
break;
|
||||
case 0x06:
|
||||
LPDAR = data & 0xffff;
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
return SCPE_OK;
|
||||
case 2: /* TIO 1403 */
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x00: /* Not ready/check */
|
||||
if (lpterror)
|
||||
iodata = 1;
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0)
|
||||
iodata = 1;
|
||||
break;
|
||||
case 0x02: /* Buffer Busy */
|
||||
iodata = 0;
|
||||
break;
|
||||
case 0x04: /* Carriage Busy */
|
||||
iodata = 0;
|
||||
break;
|
||||
case 0x06: /* Printer busy */
|
||||
iodata = 0;
|
||||
break;
|
||||
default:
|
||||
return (STOP_INVDEV << 16);
|
||||
}
|
||||
return ((SCPE_OK << 16) | iodata);
|
||||
case 3: /* SNS 1403 */
|
||||
switch (n) {
|
||||
case 0x00: /* Line count */
|
||||
iodata = (linectr << 8);
|
||||
break;
|
||||
case 0x02: /* Timing data */
|
||||
iodata = 0;
|
||||
break;
|
||||
case 0x03: /* Check data */
|
||||
iodata = 0;
|
||||
break;
|
||||
case 0x04: /* LPIAR */
|
||||
iodata = LPIAR;
|
||||
break;
|
||||
case 0x06: /* LPDAR */
|
||||
iodata = LPDAR;
|
||||
break;
|
||||
default:
|
||||
return (STOP_INVDEV << 16);
|
||||
}
|
||||
return ((SCPE_OK << 16) | iodata);
|
||||
case 4: /* APL 1403 */
|
||||
iodata = 0;
|
||||
return ((SCPE_OK << 16) | iodata);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Print routine
|
||||
|
||||
Modifiers have been checked by the caller
|
||||
S = suppress automatic newline
|
||||
*/
|
||||
|
||||
t_stat write_line (int32 ilnt, int32 mod)
|
||||
{
|
||||
int32 i, t, lc, sup;
|
||||
char *pch;
|
||||
static char lbuf[LPT_WIDTH + 1]; /* + null */
|
||||
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT;
|
||||
|
||||
lpterror = 0;
|
||||
lc = LPDAR; /* clear error */
|
||||
for (i = 0; i < LPT_WIDTH; i++) { /* convert print buf */
|
||||
t = M[lc];
|
||||
lbuf[i] = ebcdic_to_ascii[t & 0xff];
|
||||
M[lc] = 0x40; /* HJS MOD */
|
||||
lc++;
|
||||
}
|
||||
for (i = LPT_WIDTH - 1; (i >= 0) && (lbuf[i] == ' '); i--) lbuf[i] = 0;
|
||||
fputs (lbuf, lpt_unit.fileref); /* write line */
|
||||
if (lines) space (lines, lflag); /* cc action? do it */
|
||||
else if (sup == 0) space (1, FALSE); /* default? 1 line */
|
||||
else { fputc ('\r', lpt_unit.fileref); /* sup -> overprint */
|
||||
lpt_unit.pos = ftell (lpt_unit.fileref); } /* update position */
|
||||
lines = lflag = 0; /* clear cc action */
|
||||
if (ferror (lpt_unit.fileref)) { /* error? */
|
||||
perror ("Line printer I/O error");
|
||||
clearerr (lpt_unit.fileref);
|
||||
lpterror = 1; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Carriage control routine
|
||||
|
||||
Parameters:
|
||||
action = 00, skip to channel now
|
||||
= 01, space lines after
|
||||
= 02, space lines now
|
||||
= 03, skip to channel after
|
||||
= 04, skip to line number
|
||||
mod = number of lines or channel number or line number
|
||||
*/
|
||||
|
||||
t_stat carriage_control (int32 action, int32 mod)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT;
|
||||
|
||||
switch (action) {
|
||||
case 0: /* to channel now */
|
||||
if ((mod == 0) || (mod > 12) || CHP (mod, cct[cctptr])) return SCPE_OK;
|
||||
for (i = 1; i < cctlnt + 1; i++) { /* sweep thru cct */
|
||||
if (CHP (mod, cct[(cctptr + i) % cctlnt]))
|
||||
return space (i, TRUE); }
|
||||
return STOP_INVDEV; /* runaway channel */
|
||||
case 1: /* space after */
|
||||
if (mod <= 3) {
|
||||
lines = mod; /* save # lines */
|
||||
lflag = FALSE; /* flag spacing */
|
||||
CC9 = CC12 = 0; }
|
||||
return SCPE_OK;
|
||||
case 2: /* space now */
|
||||
if (mod <= 3) return space (mod, FALSE);
|
||||
return SCPE_OK;
|
||||
case 3: /* to channel after */
|
||||
if ((mod == 0) || (mod > 12)) return SCPE_OK; /* check channel */
|
||||
CC9 = CC12 = 0;
|
||||
for (i = 1; i < cctlnt + 1; i++) { /* sweep thru cct */
|
||||
if (CHP (mod, cct[(cctptr + i) % cctlnt])) {
|
||||
lines = i; /* save # lines */
|
||||
lflag = TRUE; /* flag skipping */
|
||||
return SCPE_OK; }
|
||||
return STOP_INVDEV;
|
||||
case 4: /* To line # */
|
||||
if (mod < 2) {
|
||||
fputs ("\n\f", lpt_unit.fileref); /* nl, ff */
|
||||
linectr = 1;
|
||||
} else {
|
||||
if (mod <= linectr) {
|
||||
fputs ("\n\f", lpt_unit.fileref);
|
||||
linectr = 1;
|
||||
}
|
||||
while (1) {
|
||||
if (linectr == mod)
|
||||
break;
|
||||
space(1, 0);
|
||||
}
|
||||
}
|
||||
return SCPE_OK; }
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Space routine - space or skip n lines
|
||||
|
||||
Inputs:
|
||||
count = number of lines to space or skip
|
||||
sflag = skip (TRUE) or space (FALSE)
|
||||
*/
|
||||
|
||||
t_stat space (int32 count, int32 sflag)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT;
|
||||
cctptr = (cctptr + count) % cctlnt; /* adv cct, mod lnt */
|
||||
if (sflag && CHP (0, cct[cctptr])) { /* skip, top of form? */
|
||||
fputs ("\n\f", lpt_unit.fileref); /* nl, ff */
|
||||
linectr = 1;
|
||||
}
|
||||
else { for (i = 0; i < count; i++) fputc ('\n', lpt_unit.fileref); }
|
||||
lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */
|
||||
CC9 = CHP (9, cct[cctptr]) != 0; /* set indicators */
|
||||
CC12 = CHP (12, cct[cctptr]) != 0;
|
||||
linectr += count;
|
||||
if (linectr > LPFLR)
|
||||
linectr -= LPFLR;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat lpt_reset (DEVICE *dptr)
|
||||
{
|
||||
cctptr = 0; /* clear cct ptr */
|
||||
lines = linectr = lflag = 0; /* no cc action */
|
||||
lpterror = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
t_stat lpt_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
cctptr = 0; /* clear cct ptr */
|
||||
lines = 0; /* no cc action */
|
||||
lpterror = 0;
|
||||
linectr = 0;
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
302
S3/s3_pkb.c
Normal file
302
S3/s3_pkb.c
Normal file
@@ -0,0 +1,302 @@
|
||||
/* s3_pkb.c: System/3 5471 console terminal simulator
|
||||
|
||||
Copyright (c) 2001, Charles E Owen
|
||||
|
||||
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.
|
||||
|
||||
pkb 5471 printer/keyboard
|
||||
*/
|
||||
|
||||
#include "s3_defs.h"
|
||||
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||
t_stat pkb_svc (UNIT *uptr);
|
||||
t_stat pkb_reset (DEVICE *dptr);
|
||||
extern t_stat sim_poll_kbd (void);
|
||||
extern t_stat sim_putchar (int32 out);
|
||||
extern int32 IAR[], level;
|
||||
extern int32 debug_reg;
|
||||
|
||||
/* 5471 data structures
|
||||
|
||||
pkb_dev TTI device descriptor
|
||||
pkb_unit TTI unit descriptor
|
||||
pkb_reg TTI register list
|
||||
pkb_mod TTI/TTO modifiers list
|
||||
*/
|
||||
|
||||
/* Flag bits : (kept in pkb_unit.u3) */
|
||||
|
||||
#define PRT_INTREQ 0x800 /* Printer interrupt pending */
|
||||
#define KBD_INTREQ 0x400 /* Request key interrupt pending */
|
||||
#define KBD_INTEND 0x200 /* End or cancel key interrupt pending */
|
||||
#define KBD_INTKEY 0x100 /* Return or other key interrupt pending */
|
||||
#define KBD_REQLIGHT 0x20 /* Request Pending Indicator (light on/off) */
|
||||
#define KBD_PROLIGHT 0x10 /* Proceed indicator (light on/off) */
|
||||
#define KBD_REQINT 0x04 /* Req key interrupts enabled */
|
||||
#define KBD_KEYINT 0x02 /* Other key interrupts enabled */
|
||||
#define PRT_PRTINT 0x01 /* Printer interrupts enabled */
|
||||
|
||||
/* Keys mapped to 5471 functions */
|
||||
|
||||
int32 key_req = 0x01; /* Request key: ^A */
|
||||
int32 key_rtn = 0x12; /* Return key: ^R */
|
||||
int32 key_can = 0x1B; /* Cancel key: ESC */
|
||||
int32 key_end = 0x0d; /* End key - CR */
|
||||
|
||||
UNIT pkb_unit = { UDATA (&pkb_svc, 0, 0), KBD_POLL_WAIT };
|
||||
|
||||
REG pkb_reg[] = {
|
||||
{ HRDATA (FLAG, pkb_unit.u3, 16) },
|
||||
{ HRDATA (IBUF, pkb_unit.buf, 8) },
|
||||
{ HRDATA (OBUF, pkb_unit.u4, 8) },
|
||||
{ HRDATA (REQKEY, key_req, 8) },
|
||||
{ HRDATA (RTNKEY, key_rtn, 8) },
|
||||
{ HRDATA (CANKEY, key_can, 8) },
|
||||
{ HRDATA (ENDKEY, key_end, 8) },
|
||||
{ DRDATA (POS, pkb_unit.pos, 31), PV_LEFT },
|
||||
{ DRDATA (TIME, pkb_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ NULL } };
|
||||
|
||||
MTAB pkb_mod[] = {
|
||||
{ 0 } };
|
||||
|
||||
DEVICE pkb_dev = {
|
||||
"PKB", &pkb_unit, pkb_reg, pkb_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &pkb_reset,
|
||||
NULL, NULL, NULL };
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/* EBCDIC to ASCII translate table */
|
||||
/*-------------------------------------------------------------------*/
|
||||
unsigned char ebcdic_to_ascii[] = {
|
||||
"\x00\x01\x02\x03\xA6\x09\xA7\x7F\xA9\xB0\xB1\x0B\x0C\x0D\x0E\x0F"
|
||||
"\x10\x11\x12\x13\xB2\xB4\x08\xB7\x18\x19\x1A\xB8\xBA\x1D\xBB\x1F"
|
||||
"\xBD\xC0\x1C\xC1\xC2\x0A\x17\x1B\xC3\xC4\xC5\xC6\xC7\x05\x06\x07"
|
||||
"\xC8\xC9\x16\xCB\xCC\x1E\xCD\x04\xCE\xD0\xD1\xD2\x14\x15\xD3\xFC"
|
||||
"\x20\xD4\x83\x84\x85\xA0\xD5\x86\x87\xA4\xD6\x2E\x3C\x28\x2B\xD7"
|
||||
"\x26\x82\x88\x89\x8A\xA1\x8C\x8B\x8D\xD8\x21\x24\x2A\x29\x3B\x5E"
|
||||
"\x2D\x2F\xD9\x8E\xDB\xDC\xDD\x8F\x80\xA5\x7C\x2C\x25\x5F\x3E\x3F"
|
||||
"\xDE\x90\xDF\xE0\xE2\xE3\xE4\xE5\xE6\x60\x3A\x23\x40\x27\x3D\x22"
|
||||
"\xE7\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\xE8\xE9\xEA\xEC"
|
||||
"\xF0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xF1\xF2\x91\xF3\x92\xF4"
|
||||
"\xF5\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xAD\xA8\xF6\x5B\xF7\xF8"
|
||||
"\x9B\x9C\x9D\x9E\x9F\xB5\xB6\xAC\xAB\xB9\xAA\xB3\xBC\x5D\xBE\xBF"
|
||||
"\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xCA\x93\x94\x95\xA2\xCF"
|
||||
"\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xDA\x96\x81\x97\xA3\x98"
|
||||
"\x5C\xE1\x53\x54\x55\x56\x57\x58\x59\x5A\xFD\xEB\x99\xED\xEE\xEF"
|
||||
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xFE\xFB\x9A\xF9\xFA\xFF"
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/* ASCII to EBCDIC translate table */
|
||||
/*-------------------------------------------------------------------*/
|
||||
unsigned char ascii_to_ebcdic[] = {
|
||||
"\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F"
|
||||
"\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x1A\x27\x22\x1D\x35\x1F"
|
||||
"\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61"
|
||||
"\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F"
|
||||
"\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6"
|
||||
"\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D"
|
||||
"\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96"
|
||||
"\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x6A\xD0\xA1\x07"
|
||||
"\x68\xDC\x51\x42\x43\x44\x47\x48\x52\x53\x54\x57\x56\x58\x63\x67"
|
||||
"\x71\x9C\x9E\xCB\xCC\xCD\xDB\xDD\xDF\xEC\xFC\xB0\xB1\xB2\xB3\xB4"
|
||||
"\x45\x55\xCE\xDE\x49\x69\x04\x06\xAB\x08\xBA\xB8\xB7\xAA\x8A\x8B"
|
||||
"\x09\x0A\x14\xBB\x15\xB5\xB6\x17\x1B\xB9\x1C\x1E\xBC\x20\xBE\xBF"
|
||||
"\x21\x23\x24\x28\x29\x2A\x2B\x2C\x30\x31\xCA\x33\x34\x36\x38\xCF"
|
||||
"\x39\x3A\x3B\x3E\x41\x46\x4A\x4F\x59\x62\xDA\x64\x65\x66\x70\x72"
|
||||
"\x73\xE1\x74\x75\x76\x77\x78\x80\x8C\x8D\x8E\xEB\x8F\xED\xEE\xEF"
|
||||
"\x90\x9A\x9B\x9D\x9F\xA0\xAC\xAE\xAF\xFD\xFE\xFB\x3F\xEA\xFA\xFF"
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/* Console Input: master routine */
|
||||
|
||||
int32 pkb (int32 op, int32 m, int32 n, int32 data)
|
||||
{
|
||||
int32 iodata= 0, c, ec, ac;
|
||||
switch (op) {
|
||||
case 0: /* SIO 5471 */
|
||||
if (n != 0)
|
||||
return STOP_INVDEV;
|
||||
/*printf("%04X SIO %d,%d,%02X\n\r", IAR[level]-4, m, n, data);*/
|
||||
if (m == 0) { /* Keyboard */
|
||||
pkb_unit.u3 &= 0xFC1;
|
||||
pkb_unit.u3 |= data;
|
||||
if (data & 0x01) {
|
||||
pkb_unit.u3 &= ~KBD_INTREQ;
|
||||
pkb_unit.u3 &= ~KBD_INTKEY;
|
||||
pkb_unit.u3 &= ~KBD_INTEND;
|
||||
return RESET_INTERRUPT;
|
||||
}
|
||||
} else { /* Printer */
|
||||
if (data & 0x80) { /* start print bit */
|
||||
if (debug_reg & 0x80)
|
||||
return STOP_IBKPT;
|
||||
ec = pkb_unit.u4 & 0xff;
|
||||
ac = ebcdic_to_ascii[ec];
|
||||
sim_putchar(ac);
|
||||
pkb_unit.u3 |= PRT_INTREQ;
|
||||
}
|
||||
if (data & 0x40) { /* Carr. Return */
|
||||
sim_putchar('\n');
|
||||
sim_putchar('\r');
|
||||
pkb_unit.u3 |= PRT_INTREQ;
|
||||
}
|
||||
pkb_unit.u3 &= 0xFFe;
|
||||
if (data & 0x04) /* Print interrupt flag */
|
||||
pkb_unit.u3 |= PRT_PRTINT;
|
||||
if (data & 0x01) { /* Reset Interrupt */
|
||||
if (level < 8) {
|
||||
if (!(data & 0x80))
|
||||
pkb_unit.u3 &= ~PRT_INTREQ;
|
||||
return RESET_INTERRUPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
case 1: /* LIO 5471 */
|
||||
if (n != 0)
|
||||
return STOP_INVDEV;
|
||||
if (m != 1)
|
||||
return STOP_INVDEV;
|
||||
pkb_unit.u4 = (data >> 8) & 0xff;
|
||||
return SCPE_OK;
|
||||
break;
|
||||
case 2: /* TIO 5471 */
|
||||
return STOP_INVDEV;
|
||||
case 3: /* SNS 5471 */
|
||||
if (n != 1 && n != 3)
|
||||
return (STOP_INVDEV << 16);
|
||||
if (m == 0) { /* Keyboard data */
|
||||
if (n == 1) { /* Sense bytes 0 & 1 */
|
||||
iodata = (pkb_unit.buf << 8) & 0xff00;
|
||||
if (pkb_unit.u3 & KBD_INTREQ)
|
||||
iodata |= 0x80;
|
||||
if (pkb_unit.u3 & KBD_INTEND)
|
||||
iodata |= 0x40;
|
||||
if (pkb_unit.u3 & KBD_INTKEY)
|
||||
iodata |= 0x08;
|
||||
if (pkb_unit.buf == 0x12) /* Return key */
|
||||
iodata |= 0x04;
|
||||
if (pkb_unit.buf == 0x03) /* Cancel key */
|
||||
iodata |= 0x20;
|
||||
if (pkb_unit.buf == 0x0d) /* End key */
|
||||
iodata |= 0x10;
|
||||
iodata |= ((SCPE_OK << 16) & 0xffff0000);
|
||||
} else { /* Sense bytes 2 & 3 */
|
||||
iodata = 0; /* Manual says CE use only */
|
||||
}
|
||||
} else { /* Printer Data */
|
||||
if (n == 1) { /* Sense bytes 0 & 1 */
|
||||
iodata = 0;
|
||||
if (pkb_unit.u3 & PRT_INTREQ)
|
||||
iodata |= 0x80;
|
||||
} else {
|
||||
iodata = 0; /* CE use only */
|
||||
}
|
||||
}
|
||||
iodata |= ((SCPE_OK << 16) & 0xffff0000);
|
||||
return (iodata);
|
||||
case 4: /* APL 5471 */
|
||||
return STOP_INVDEV;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat pkb_svc (UNIT *uptr)
|
||||
{
|
||||
int32 temp, ac, ec;
|
||||
|
||||
sim_activate (&pkb_unit, pkb_unit.wait); /* continue poll */
|
||||
|
||||
if (pkb_unit.u3 & PRT_INTREQ) { /* Printer Interrupt */
|
||||
int_req |= 2;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Keyboard : handle input */
|
||||
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
|
||||
|
||||
ac = temp & 0x7f; /* placed type ASCII char in ac */
|
||||
if (pkb_unit.u3 & KBD_REQINT) {
|
||||
if (ac == key_req) { /* Request Key */
|
||||
pkb_unit.u3 |= KBD_INTREQ;
|
||||
int_req |= 2;
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
if (islower(ac))
|
||||
ac = toupper(ac);
|
||||
ec = ascii_to_ebcdic[ac]; /* Translate */
|
||||
pkb_unit.buf = ec; /* put in buf */
|
||||
pkb_unit.pos = pkb_unit.pos + 1;
|
||||
if (ac == key_end) { /* End key */
|
||||
if (pkb_unit.u3 & KBD_KEYINT) {
|
||||
pkb_unit.u3 |= KBD_INTEND;
|
||||
pkb_unit.buf = 0x0d;
|
||||
int_req |= 2;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (ac == key_can) { /* Cancel key */
|
||||
if (pkb_unit.u3 & KBD_KEYINT) {
|
||||
pkb_unit.u3 |= KBD_INTEND;
|
||||
pkb_unit.buf = 0x03;
|
||||
int_req |= 2;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (ac == key_rtn) { /* Return key */
|
||||
if (pkb_unit.u3 & KBD_KEYINT) {
|
||||
pkb_unit.u3 |= KBD_INTKEY;
|
||||
pkb_unit.buf = 0x12;
|
||||
int_req |= 2;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (pkb_unit.u3 & KBD_KEYINT) { /* Key interupts enabled ? */
|
||||
int_req |= 2; /* Device 1 Interrupt! */
|
||||
pkb_unit.u3 |= KBD_INTKEY; /* Set pending flag */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat pkb_reset (DEVICE *dptr)
|
||||
{
|
||||
pkb_unit.buf = 0;
|
||||
int_req = int_req & ~0x02; /* reset interrupt */
|
||||
sim_activate (&pkb_unit, pkb_unit.wait); /* activate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat pkb_setmod (UNIT *uptr, int32 value)
|
||||
{
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
925
S3/s3_sys.c
Normal file
925
S3/s3_sys.c
Normal file
@@ -0,0 +1,925 @@
|
||||
/* ibms3_sys.c: IBM System/3 system interface
|
||||
|
||||
(C) Copyright 2001 by Charles E. Owen
|
||||
Commercial use prohibited
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "s3_defs.h"
|
||||
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE pkb_dev;
|
||||
extern DEVICE cdr_dev;
|
||||
extern DEVICE cdp_dev;
|
||||
extern DEVICE stack_dev;
|
||||
extern DEVICE lpt_dev;
|
||||
extern DEVICE r1_dev;
|
||||
extern DEVICE f1_dev;
|
||||
extern DEVICE r2_dev;
|
||||
extern DEVICE f2_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern unsigned char M[];
|
||||
extern int32 saved_PC, IAR[];
|
||||
extern char ebcdic_to_ascii[256];
|
||||
extern char *get_glyph (char *cptr, char *gbuf, char term);
|
||||
extern unsigned int32 get_uint (char *cptr, int32 radix, unsigned int32 max,
|
||||
int32 *status);
|
||||
char *parse_addr(char *cptr, char *gbuf, int32 *addr, int32 *addrtype);
|
||||
|
||||
/* SCP data structures
|
||||
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words needed for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
*/
|
||||
|
||||
char sim_name[] = "System/3";
|
||||
|
||||
REG *sim_PC = &cpu_reg[0];
|
||||
|
||||
int32 sim_emax = 6;
|
||||
|
||||
DEVICE *sim_devices[] = { &cpu_dev,
|
||||
&pkb_dev,
|
||||
&cdr_dev,
|
||||
&cdp_dev,
|
||||
&stack_dev,
|
||||
&lpt_dev,
|
||||
&r1_dev,
|
||||
&f1_dev,
|
||||
&r2_dev,
|
||||
&f2_dev,
|
||||
NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
"Unknown error",
|
||||
"Unknown I/O Instruction",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Invalid Opcode",
|
||||
"Invalid Qbyte",
|
||||
"Invalid Address",
|
||||
"Invalid Device Command",
|
||||
"ATTN Card Reader"
|
||||
};
|
||||
|
||||
/* This is the opcode master defintion table. Each possible opcode mnemonic
|
||||
is defined here, with enough information to translate to and from
|
||||
symbolic to binary machine code.
|
||||
First field is the opcode's mnemonic
|
||||
Second field is the hex of the right nybble of the binary opcode
|
||||
Third field is the Q code for those with implicit Q codes
|
||||
Fourth field is the symbolic format of the operands:
|
||||
0 - (Q-byte),(R-byte)
|
||||
1 - (Q-byte),(Address)
|
||||
2 - (Address),(Address),(Qbyte)
|
||||
3 - (Address),(Qbyte)
|
||||
4 - (device),(modifier),(function) -- these 3 make up qbyte
|
||||
5 - (device),(modifier),(function),(control)
|
||||
6 - (device),(modifier),(function),(Address)
|
||||
7 - (displacement) -- Q byte is implicit in opcode
|
||||
8 - (address) -- Qbyte is implicit in opcode
|
||||
9 - (Address),(Address) -- Qbyte is implicit in opcode
|
||||
Fifth Field is the group number:
|
||||
0 - Command Group (left op nybble is F)
|
||||
1 - One Address Operations A (Left Nybble C, D, or E)
|
||||
2 - Two Address Operations (Left Nybble 0,1,2,4,5,6,8,9, or A)
|
||||
3 - One Address Operations B (left Nybble 3, 7, or B)
|
||||
|
||||
There is duplication in this table -- IBM defines different opcodes
|
||||
that resolve to the same binary machine instruction -- e.g. JE and
|
||||
JZ. On input this is no problem, on output, define the one you
|
||||
want to appear first, the second will never appear on output.
|
||||
*/
|
||||
|
||||
int32 nopcode = 75;
|
||||
struct opdef opcode[75] = {
|
||||
"HPL", 0x00,0,0,0, /* Halt Program Level */
|
||||
"A", 0x06,0,1,3, /* Add to Register: A R,AADD */
|
||||
"ST", 0x04,0,1,3, /* Store Register */
|
||||
"L", 0x05,0,1,3, /* Load Register */
|
||||
"LA", 0x02,0,1,1, /* Load Address */
|
||||
"ZAZ", 0x04,0,2,2, /* Zero and Add Zoned */
|
||||
"AZ", 0x06,0,2,2, /* Add Zoned Decimal */
|
||||
"SZ", 0x07,0,2,2, /* Subtract Zoned Decimal */
|
||||
"ALC", 0x0E,0,2,2, /* Add Logical: ALC BADD,AADD,LEN */
|
||||
"SLC", 0x0F,0,2,2, /* Sub Logical: SLC BADD,AADD,LEN */
|
||||
"MVC", 0x0C,0,2,2, /* Move Chars MVX BADD,AADD,LEN */
|
||||
"ED", 0x0A,0,2,2, /* Edit: ED BADD,AADD,LEN */
|
||||
"ITC", 0x0B,0,2,2, /* Insert Chars: ITC BADD,AADD,LEN */
|
||||
"CLC", 0x0D,0,2,2, /* Compare Logical: CLC BADD,AADD,LEN */
|
||||
"MVI", 0x0C,0,3,3, /* Move Immediate */
|
||||
"SBN", 0x0A,0,3,3, /* Set Bits On */
|
||||
"SBF", 0x0B,0,3,3, /* Set Bits Off */
|
||||
"CLI", 0x0D,0,3,3, /* Compare Immediate */
|
||||
"TBN", 0x08,0,3,3, /* Test Bits On */
|
||||
"TBF", 0x09,0,3,3, /* Test Bits Off */
|
||||
"APL", 0x01,0,4,0, /* Advance Program Level */
|
||||
"SIO", 0x03,0,5,0, /* Start I/O */
|
||||
"SNS", 0x00,0,6,3, /* Sense I/O */
|
||||
"LIO", 0x01,0,6,3, /* Load I/O */
|
||||
"TIO", 0x01,0,6,1, /* Test I/O */
|
||||
"J", 0x02,0,7,0, /* Jump Unconditional */
|
||||
"J", 0x02,0x87,7,0, /* Alternate J */
|
||||
"JH", 0x02,132,7,0, /* Jump if High */
|
||||
"JL", 0x02,130,7,0, /* Jump if Low */
|
||||
"JE", 0x02,129,7,0, /* Jump if Equal */
|
||||
"JNH", 0x02,4,7,0, /* Jump if Not High */
|
||||
"JNL", 0x02,2,7,0, /* Jump if Not Low */
|
||||
"JNE", 0x02,1,7,0, /* Jump if Not Equal */
|
||||
"JOZ", 0x02,136,7,0, /* Jump if Overflow Zoned */
|
||||
"JOL", 0x02,160,7,0, /* Jump if Overflow Logical */
|
||||
"JNOZ", 0x02,8,7,0, /* Jump if No Overflow Zoned */
|
||||
"JNOL", 0x02,32,7,0, /* Jump if No Overflow Logical */
|
||||
"JT", 0x02,16,7,0, /* Jump if True */
|
||||
"JF", 0x02,144,7,0, /* Jump if False */
|
||||
"JP", 0x02,132,7,0, /* Jump if Plus */
|
||||
"JM", 0x02,130,7,0, /* Jump if Minus */
|
||||
"JZ", 0x02,129,7,0, /* Jump if Zero */
|
||||
"JNP", 0x02,4,7,0, /* Jump if Not Plus */
|
||||
"JNM", 0x02,2,7,0, /* Jump if Not Minus */
|
||||
"JNZ", 0x02,1,7,0, /* Jump if Not Zero */
|
||||
"NOPJ", 0x02,0x80,7,0, /* Never Jump - NOP */
|
||||
"B", 0x00,0x00,8,1, /* Branch Unconditional */
|
||||
"B", 0x00,0x87,8,1, /* Alternate B */
|
||||
"BH", 0x00,0x84,8,1, /* Branch if High */
|
||||
"BL", 0x00,0x82,8,1, /* Branch if Low */
|
||||
"BE", 0x00,0x81,8,1, /* Branch if Equal */
|
||||
"BNH", 0x00,0x04,8,1, /* Branch if Not High */
|
||||
"BNL", 0x00,0x02,8,1, /* Branch if Not Low */
|
||||
"BNE", 0x00,0x01,8,1, /* Branch if Not Equal */
|
||||
"BOZ", 0x00,0x88,8,1, /* Branch if Overflow Zoned */
|
||||
"BOL", 0x00,0xA0,8,1, /* Branch if Overflow Logical */
|
||||
"BNOZ", 0x00,0x08,8,1, /* Branch if No Overflow Zoned */
|
||||
"BNOL", 0x00,0x20,8,1, /* Branch if No Overflow Logical */
|
||||
"BT", 0x00,0x10,8,1, /* Branch if True */
|
||||
"BF", 0x00,0x90,8,1, /* Branch if False */
|
||||
"BP", 0x00,0x84,8,1, /* Branch if Plus */
|
||||
"BM", 0x00,0x82,8,1, /* Branch if Minus */
|
||||
"BZ", 0x00,0x81,8,1, /* Branch if Zero */
|
||||
"BNP", 0x00,0x04,8,1, /* Branch if Not Plus */
|
||||
"BNM", 0x00,0x02,8,1, /* Branch if Not Minus */
|
||||
"BNZ", 0x00,0x01,8,1, /* Branch if Not Zero */
|
||||
"NOPB", 0x00,0x80,8,1, /* Never Branch - NOP */
|
||||
"MZZ", 0x08,0,9,2, /* Move Zone to Zone */
|
||||
"MNZ", 0x08,1,9,2, /* Move Numeric to Zone */
|
||||
"MZN", 0x08,2,9,2, /* Move Zone to Numeric */
|
||||
"MNN", 0x08,3,9,2, /* Move Numeric to Numeric */
|
||||
"MVX", 0x08,0,2,2, /* Move Hex: MVX BADD,AADD,CODE */
|
||||
"JC", 0x02,0,3,0, /* Jump on Specified Condition bits */
|
||||
"BC", 0x00,0,3,1, /* Branch on Specified Condition */
|
||||
"***", 0x00,0,0,0
|
||||
};
|
||||
|
||||
int32 regcode[15] = { 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
|
||||
0x80, 0xC0, 0xA0, 0x90, 0x88, 0x84, 0x82, 0x81 };
|
||||
|
||||
char regname[15][8] = { "(P2IAR)",
|
||||
"(P1IAR)",
|
||||
"(IAR)",
|
||||
"(ARR)",
|
||||
"(PSR)",
|
||||
"(XR2)",
|
||||
"(XR1)",
|
||||
"(IAR0)",
|
||||
"(IAR1)",
|
||||
"(IAR2)",
|
||||
"(IAR3)",
|
||||
"(IAR4)",
|
||||
"(IAR5)",
|
||||
"(IAR6)",
|
||||
"(IAR7)" };
|
||||
|
||||
/* This is the binary loader. The input file is considered to be
|
||||
a string of literal bytes with no special format. The
|
||||
load starts at the current value of the P1IAR.
|
||||
*/
|
||||
|
||||
int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
{
|
||||
int32 i, addr = 0, cnt = 0;
|
||||
|
||||
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
|
||||
addr = IAR[8];
|
||||
while ((i = getc (fileref)) != EOF) {
|
||||
M[addr] = i & 0xff;
|
||||
addr++;
|
||||
cnt++;
|
||||
} /* end while */
|
||||
printf ("%d Bytes loaded.\n", cnt);
|
||||
return (SCPE_OK);
|
||||
}
|
||||
|
||||
/* Symbolic output
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = pointer to values
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
status = error code
|
||||
*/
|
||||
|
||||
int32 fprint_sym (FILE *of, int32 addr, unsigned int32 *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int32 r;
|
||||
char strg[256];
|
||||
|
||||
strcpy(strg, "");
|
||||
r = printf_sym(of, strg, addr, val, uptr, sw);
|
||||
if (sw & SWMASK ('A'))
|
||||
strcpy(strg, "");
|
||||
else
|
||||
fprintf(of, "%s", strg);
|
||||
return (r);
|
||||
}
|
||||
|
||||
int32 printf_sym (FILE *of, char *strg, int32 addr, unsigned int32 *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int32 cflag, c1, c2, group, len1, len2, inst, adr, aaddr, baddr;
|
||||
int32 oplen, groupno, i, j, vpos, qbyte, da, m, n;
|
||||
char bld[128], bldaddr[32], boperand[32], aoperand[32], regoperand[32];
|
||||
int32 blk[16], blt[16];
|
||||
int32 blkadd;
|
||||
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
c1 = val[0] & 0xff;
|
||||
if (sw & SWMASK ('A')) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
blkadd = addr + (i*16);
|
||||
for (j = 0; j < 16; j++) {
|
||||
blk[j] = M[blkadd+j] & 0xff;
|
||||
c2 = ebcdic_to_ascii[blk[j]];
|
||||
if (c2 < 040 || c2 > 0177 || blk[j] == 07) {
|
||||
blt[j] = '.';
|
||||
} else {
|
||||
blt[j] = c2;
|
||||
}
|
||||
}
|
||||
if (i == 0) {
|
||||
fprintf(of, "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X [%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c]\n ",
|
||||
blk[0], blk[1], blk[2], blk[3], blk[4], blk[5], blk[6], blk[7],
|
||||
blk[8], blk[9], blk[10], blk[11], blk[12], blk[13], blk[14], blk[15],
|
||||
blt[0], blt[1], blt[2], blt[3], blt[4], blt[5], blt[6], blt[7],
|
||||
blt[8], blt[9], blt[10], blt[11], blt[12], blt[13], blt[14], blt[15]);
|
||||
} else {
|
||||
fprintf(of, "%X\t%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X [%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c]\n ",
|
||||
blkadd, blk[0], blk[1], blk[2], blk[3], blk[4], blk[5], blk[6], blk[7],
|
||||
blk[8], blk[9], blk[10], blk[11], blk[12], blk[13], blk[14], blk[15],
|
||||
blt[0], blt[1], blt[2], blt[3], blt[4], blt[5], blt[6], blt[7],
|
||||
blt[8], blt[9], blt[10], blt[11], blt[12], blt[13], blt[14], blt[15]);
|
||||
}
|
||||
}
|
||||
return SCPE_OK; }
|
||||
if (sw & SWMASK ('C')) {
|
||||
c2 = ebcdic_to_ascii[c1];
|
||||
if (c2 < 040 || c2 > 0177) {
|
||||
sprintf(strg, "<%02X>", c1 & 0xff);
|
||||
} else {
|
||||
sprintf (strg, "%c", c2 & 0xff);
|
||||
}
|
||||
return SCPE_OK; }
|
||||
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
|
||||
|
||||
inst = val[0] & 0x0f;
|
||||
len1 = (val[0] >> 6) & 3;
|
||||
len2 = (val[0] >> 4) & 3;
|
||||
group = (val[0] >> 4) & 0x0f;
|
||||
qbyte = val[1];
|
||||
|
||||
/* Get total length of instruction */
|
||||
|
||||
if (group == 0x0f) {
|
||||
oplen = 3;
|
||||
} else {
|
||||
oplen = 2;
|
||||
if (len1 == 0) oplen += 2;
|
||||
if (len1 == 1 || len1 == 2) oplen++;
|
||||
if (len2 == 0) oplen += 2;
|
||||
if (len2 == 1 || len2 == 2) oplen++;
|
||||
}
|
||||
|
||||
/* Find which group it belongs to */
|
||||
|
||||
switch (group) {
|
||||
case 0x0f:
|
||||
groupno = 0;
|
||||
break;
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
case 0x0e:
|
||||
groupno = 1;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x07:
|
||||
case 0x0b:
|
||||
groupno = 3;
|
||||
break;
|
||||
default:
|
||||
groupno = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* find the table entry */
|
||||
|
||||
for (i = 0; i < nopcode; i++) {
|
||||
if (opcode[i].form < 7) { /* Explicit Q */
|
||||
if (opcode[i].group == groupno &&
|
||||
opcode[i].opmask == inst) break;
|
||||
} else { /* Implicit Q */
|
||||
if (opcode[i].group == groupno &&
|
||||
opcode[i].opmask == inst &&
|
||||
opcode[i].q == qbyte) break;
|
||||
}
|
||||
}
|
||||
|
||||
/* print the opcode */
|
||||
|
||||
if (i >= nopcode) {
|
||||
sprintf(strg, "%02X", val[0]);
|
||||
oplen = 1;
|
||||
} else {
|
||||
sprintf(bld, "%s ", opcode[i].op);
|
||||
|
||||
/* Extract the addresses into aaddr and baddr */
|
||||
|
||||
strcpy(aoperand, "ERROR");
|
||||
strcpy(boperand, "ERROR");
|
||||
vpos = 2;
|
||||
aaddr = baddr = 0;
|
||||
switch (len1) {
|
||||
case 0:
|
||||
baddr = ((val[vpos] << 8) & 0xff00) | (val[vpos + 1] & 0x00ff);
|
||||
sprintf(boperand, "%04X", baddr);
|
||||
vpos = 4;
|
||||
break;
|
||||
case 1:
|
||||
baddr = val[vpos] & 255;
|
||||
sprintf(boperand, "(%02X,XR1)", baddr);
|
||||
vpos = 3;
|
||||
break;
|
||||
case 2:
|
||||
baddr = val[vpos] & 255;
|
||||
sprintf(boperand, "(%02X,XR2)", baddr);
|
||||
vpos = 3;
|
||||
break;
|
||||
default:
|
||||
baddr = 0;
|
||||
break;
|
||||
}
|
||||
switch (len2) {
|
||||
case 0:
|
||||
aaddr = ((val[vpos] << 8) & 0xff00) | (val[vpos + 1] & 0x00ff);
|
||||
if (group == 0x0C || group == 0x0D || group == 0x0E)
|
||||
sprintf(boperand, "%04X", aaddr);
|
||||
else
|
||||
sprintf(aoperand, "%04X", aaddr);
|
||||
break;
|
||||
case 1:
|
||||
aaddr = val[vpos] & 255;
|
||||
if (group == 0x0C || group == 0x0D || group == 0x0E)
|
||||
sprintf(boperand, "(%02X,XR1)", aaddr);
|
||||
else
|
||||
sprintf(aoperand, "(%02X,XR1)", aaddr);
|
||||
break;
|
||||
case 2:
|
||||
aaddr = val[vpos] & 255;
|
||||
if (group == 0x0C || group == 0x0D || group == 0x0E)
|
||||
sprintf(boperand, "(%02X,XR2)", aaddr);
|
||||
else
|
||||
sprintf(aoperand, "(%02X,XR2)", aaddr);
|
||||
break;
|
||||
default:
|
||||
aaddr = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Display the operands in the correct format */
|
||||
|
||||
da = (qbyte >> 4) & 0x0f;
|
||||
m = (qbyte >> 3) & 0x01;
|
||||
n = (qbyte) & 0x07;
|
||||
|
||||
switch (opcode[i].form) {
|
||||
case 0:
|
||||
sprintf(bldaddr, "%02X,%02X", qbyte, val[2]);
|
||||
break;
|
||||
case 1:
|
||||
if (inst == 2 || inst == 4 || inst == 5 || inst == 6) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (regcode[i] == qbyte)
|
||||
break;
|
||||
}
|
||||
if (i < 16) {
|
||||
sprintf(bldaddr, "%s,%s", regname[i], boperand);
|
||||
} else {
|
||||
sprintf(bldaddr, "%02X,%s", qbyte, boperand);
|
||||
}
|
||||
} else {
|
||||
sprintf(bldaddr, "%02X,%s", qbyte, boperand);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (inst > 9 || inst == 4 || inst == 6 || inst == 7)
|
||||
qbyte++; /* special +1 for length display */
|
||||
sprintf(bldaddr, "%s,%s,%d", boperand, aoperand, qbyte);
|
||||
break;
|
||||
case 3:
|
||||
if (strcmp(opcode[i].op, "JC") == 0) {
|
||||
sprintf(bldaddr, "%04X,%02X", addr+oplen+val[2], qbyte);
|
||||
} else {
|
||||
sprintf(bldaddr, "%s,%02X", boperand, qbyte);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
sprintf(bldaddr, "%d,%d,%d", da, m, n);
|
||||
break;
|
||||
case 5:
|
||||
sprintf(bldaddr, "%d,%d,%d,%02X", da, m, n, val[2]);
|
||||
break;
|
||||
case 6:
|
||||
sprintf(bldaddr, "%d,%d,%d,%s", da, m, n, boperand);
|
||||
break;
|
||||
case 7:
|
||||
sprintf(bldaddr, "%04X", addr+oplen+val[2]);
|
||||
break;
|
||||
case 8:
|
||||
sprintf(bldaddr, "%s", boperand);
|
||||
break;
|
||||
default:
|
||||
sprintf(bldaddr, "%s,%s", boperand, aoperand);
|
||||
break;
|
||||
}
|
||||
sprintf(strg, "%s%s", bld, bldaddr);
|
||||
}
|
||||
|
||||
return -(oplen - 1);
|
||||
}
|
||||
|
||||
/* 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
|
||||
*/
|
||||
|
||||
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, unsigned int32 *val, int32 sw)
|
||||
{
|
||||
int32 cflag, i = 0, j, k, r, oplen, addtyp, saveaddr, vptr;
|
||||
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) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = (unsigned int) cptr[0];
|
||||
return SCPE_OK; }
|
||||
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = ((unsigned int) cptr[0] << 8) + (unsigned int) cptr[1];
|
||||
return SCPE_OK; }
|
||||
|
||||
/* An instruction: get opcode (all characters until null, comma, left paren,
|
||||
or numeric (including spaces).
|
||||
*/
|
||||
|
||||
while (1) {
|
||||
if (*cptr == ',' || *cptr == '\0' || *cptr == '(' ||
|
||||
isdigit(*cptr))
|
||||
break;
|
||||
gbuf[i] = toupper(*cptr);
|
||||
cptr++;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* kill trailing spaces if any */
|
||||
gbuf[i] = '\0';
|
||||
for (j = i - 1; gbuf[j] == ' '; j--) {
|
||||
gbuf[j] = '\0';
|
||||
}
|
||||
|
||||
/* find opcode in table */
|
||||
for (j = 0; j < nopcode; j++) {
|
||||
if (strcmp(gbuf, opcode[j].op) == 0)
|
||||
break;
|
||||
}
|
||||
if (j >= nopcode) /* not found */
|
||||
return SCPE_ARG;
|
||||
|
||||
oplen = 2; /* start with op & q */
|
||||
|
||||
val[0] = opcode[j].opmask; /* store opcode right nybble */
|
||||
|
||||
switch (opcode[j].form) { /* Get operands based on operand format */
|
||||
case 0: /* Single Byte Operand */
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, ','); /* Get Q Byte */
|
||||
sscanf(gbuf, "%x", &r);
|
||||
val[1] = r;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, 0); /* Get R Byte */
|
||||
sscanf(gbuf, "%x", &r);
|
||||
val[2] = r;
|
||||
oplen = 3;
|
||||
val[0] = 0xf0 | opcode[j].opmask;
|
||||
break;
|
||||
case 1:
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, ',');
|
||||
if (opcode[j].opmask == 2 ||
|
||||
opcode[j].opmask == 4 ||
|
||||
opcode[j].opmask == 5 ||
|
||||
opcode[j].opmask == 6) {
|
||||
if (isdigit(gbuf[0])) {
|
||||
sscanf(gbuf, "%x", &r);
|
||||
} else {
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (strcmp(gbuf, regname[i]) == 0)
|
||||
break;
|
||||
}
|
||||
if (i < 16) {
|
||||
r = regcode[i];
|
||||
} else {
|
||||
return SCPE_ARG;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sscanf(gbuf, "%x", &r);
|
||||
}
|
||||
if (r > 255) return SCPE_ARG;
|
||||
val[1] = r;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
|
||||
switch(addtyp) {
|
||||
case 0:
|
||||
val[2] = (addr >> 8) & 0x00ff;
|
||||
val[3] = addr & 0xff;
|
||||
oplen = 4;
|
||||
if (opcode[j].group == 1)
|
||||
val[0] = 0xC0 | opcode[j].opmask;
|
||||
else
|
||||
val[0] = 0x30 | opcode[j].opmask;
|
||||
break;
|
||||
case 1:
|
||||
val[2] = addr & 0xff;
|
||||
oplen = 3;
|
||||
if (opcode[j].group == 1)
|
||||
val[0] = 0xD0 | opcode[j].opmask;
|
||||
else
|
||||
val[0] = 0x70 | opcode[j].opmask;
|
||||
break;
|
||||
case 2:
|
||||
val[2] = addr & 0xff;
|
||||
oplen = 3;
|
||||
if (opcode[j].group == 1)
|
||||
val[0] = 0xE0 | opcode[j].opmask;
|
||||
else
|
||||
val[0] = 0xB0 | opcode[j].opmask;
|
||||
break;
|
||||
default:
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
oplen = 2;
|
||||
cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
|
||||
switch(addtyp) {
|
||||
case 0:
|
||||
val[2] = (addr >> 8) & 0xff;
|
||||
val[3] = addr & 0xff;
|
||||
oplen += 2;
|
||||
vptr = 4;
|
||||
val[0] = 0x00 | opcode[j].opmask;
|
||||
break;
|
||||
case 1:
|
||||
val[2] = addr & 0xff;
|
||||
oplen += 1;
|
||||
vptr = 3;
|
||||
val[0] = 0x40 | opcode[j].opmask;
|
||||
break;
|
||||
case 2:
|
||||
val[2] = addr & 0xff;
|
||||
oplen += 1;
|
||||
vptr = 3;
|
||||
val[0] = 0x80 | opcode[j].opmask;
|
||||
break;
|
||||
default:
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
}
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
|
||||
switch(addtyp) {
|
||||
case 0:
|
||||
val[vptr] = (addr >> 8) & 0xff;
|
||||
val[vptr+1] = addr & 0xff;
|
||||
oplen += 2;
|
||||
break;
|
||||
case 1:
|
||||
val[vptr] = addr & 0xff;
|
||||
oplen += 1;
|
||||
val[0] = 0x10 | val[0];
|
||||
break;
|
||||
case 2:
|
||||
val[vptr] = addr & 0xff;
|
||||
oplen += 1;
|
||||
val[0] = 0x20 | val[0];
|
||||
break;
|
||||
default:
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
}
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, 0);
|
||||
sscanf(gbuf, "%d", &r);
|
||||
if (opcode[j].opmask > 9 ||
|
||||
opcode[j].opmask == 4 ||
|
||||
opcode[j].opmask == 6 ||
|
||||
opcode[j].opmask == 7) r--; /* special: length -1 */
|
||||
val[1] = r;
|
||||
if (*cptr == ',') cptr++;
|
||||
break;
|
||||
case 3:
|
||||
saveaddr = addr;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
|
||||
switch(addtyp) {
|
||||
case 0:
|
||||
if (opcode[j].group == 0) { /* Group 0 form 3 is JC with explicit Q */
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, 0);
|
||||
sscanf(gbuf, "%x", &r);
|
||||
if ((addr - (saveaddr+3)) > 255 || (addr - (saveaddr+3)) < 1)
|
||||
return SCPE_ARG;
|
||||
val[2] = addr - (saveaddr+3);
|
||||
val[1] = r;
|
||||
val[0] = 0xf0 | opcode[j].opmask;
|
||||
oplen = 3;
|
||||
|
||||
} else {
|
||||
val[2] = (addr >> 8) & 0x00ff;
|
||||
val[3] = addr & 0xff;
|
||||
oplen = 4;
|
||||
if (opcode[j].group == 1)
|
||||
val[0] = 0xC0 | opcode[j].opmask;
|
||||
else
|
||||
val[0] = 0x30 | opcode[j].opmask;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
val[2] = addr & 0xff;
|
||||
oplen = 3;
|
||||
if (opcode[j].group == 1)
|
||||
val[0] = 0xD0 | opcode[j].opmask;
|
||||
else
|
||||
val[0] = 0x70 | opcode[j].opmask;
|
||||
break;
|
||||
case 2:
|
||||
val[2] = addr & 0xff;
|
||||
oplen = 3;
|
||||
if (opcode[j].group == 1)
|
||||
val[0] = 0xE0 | opcode[j].opmask;
|
||||
else
|
||||
val[0] = 0xB0 | opcode[j].opmask;
|
||||
break;
|
||||
default:
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
}
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, 0);
|
||||
sscanf(gbuf, "%x", &r);
|
||||
if (r > 255) return SCPE_ARG;
|
||||
val[1] = r;
|
||||
break;
|
||||
case 4:
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, ',');
|
||||
sscanf(gbuf, "%d", &r);
|
||||
if (r > 15) return SCPE_ARG;
|
||||
val[1] = (r << 4) & 0xf0;
|
||||
val[0] = 0xf0 | opcode[j].opmask;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, ',');
|
||||
sscanf(gbuf, "%d", &r);
|
||||
if (r > 1) return SCPE_ARG;
|
||||
val[1] |= (r << 3) & 0x08;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, 0);
|
||||
sscanf(gbuf, "%d", &r);
|
||||
if (r > 7) return SCPE_ARG;
|
||||
val[1] |= r & 0x07;
|
||||
val[2] = 0;
|
||||
oplen = 3;
|
||||
break;
|
||||
case 5:
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, ',');
|
||||
sscanf(gbuf, "%d", &r);
|
||||
if (r > 15) return SCPE_ARG;
|
||||
val[1] = (r << 4) & 0xf0;
|
||||
val[0] = 0xf0 | opcode[j].opmask;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, ',');
|
||||
sscanf(gbuf, "%d", &r);
|
||||
if (r > 1) return SCPE_ARG;
|
||||
val[1] |= (r << 3) & 0x08;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, ',');
|
||||
sscanf(gbuf, "%d", &r);
|
||||
if (r > 7) return SCPE_ARG;
|
||||
val[1] |= r & 0x07;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, 0);
|
||||
sscanf(gbuf, "%x", &r);
|
||||
if (r > 255) return SCPE_ARG;
|
||||
val[2] = r;
|
||||
oplen = 3;
|
||||
break;
|
||||
case 6:
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, ',');
|
||||
sscanf(gbuf, "%d", &r);
|
||||
if (r > 15) return SCPE_ARG;
|
||||
val[1] = (r << 4) & 0xf0;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, ',');
|
||||
sscanf(gbuf, "%d", &r);
|
||||
if (r > 1) return SCPE_ARG;
|
||||
val[1] |= (r << 3) & 0x08;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, ',');
|
||||
sscanf(gbuf, "%d", &r);
|
||||
if (r > 7) return SCPE_ARG;
|
||||
val[1] |= r & 0x07;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
|
||||
switch(addtyp) {
|
||||
case 0:
|
||||
val[2] = (addr >> 8) & 0x00ff;
|
||||
val[3] = addr & 0xff;
|
||||
oplen = 4;
|
||||
if (opcode[j].group == 1)
|
||||
val[0] = 0xC0 | opcode[j].opmask;
|
||||
else
|
||||
val[0] = 0x30 | opcode[j].opmask;
|
||||
break;
|
||||
case 1:
|
||||
val[2] = addr & 0xff;
|
||||
oplen = 3;
|
||||
if (opcode[j].group == 1)
|
||||
val[0] = 0xD0 | opcode[j].opmask;
|
||||
else
|
||||
val[0] = 0x70 | opcode[j].opmask;
|
||||
break;
|
||||
case 2:
|
||||
val[2] = addr & 0xff;
|
||||
oplen = 3;
|
||||
if (opcode[j].group == 1)
|
||||
val[0] = 0xE0 | opcode[j].opmask;
|
||||
else
|
||||
val[0] = 0xB0 | opcode[j].opmask;
|
||||
break;
|
||||
default:
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, 0);
|
||||
sscanf(gbuf, "%x", &r);
|
||||
if ((r - (addr+3)) > 255 || (r - (addr+3)) < 1) return SCPE_ARG;
|
||||
val[2] = r - (addr+3);
|
||||
val[1] = opcode[j].q;
|
||||
val[0] = 0xf0 | opcode[j].opmask;
|
||||
oplen = 3;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
|
||||
switch(addtyp) {
|
||||
case 0:
|
||||
val[2] = (addr >> 8) & 0x00ff;
|
||||
val[3] = addr & 0xff;
|
||||
oplen = 4;
|
||||
val[0] = 0xC0 | opcode[j].opmask;
|
||||
break;
|
||||
case 1:
|
||||
val[2] = addr & 0xff;
|
||||
oplen = 3;
|
||||
val[0] = 0xD0 | opcode[j].opmask;
|
||||
break;
|
||||
case 2:
|
||||
val[2] = addr & 0xff;
|
||||
oplen = 3;
|
||||
val[0] = 0xE0 | opcode[j].opmask;
|
||||
break;
|
||||
default:
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
}
|
||||
val[1] = opcode[j].q;
|
||||
break;
|
||||
case 9:
|
||||
oplen = 2;
|
||||
val[0] = 0;
|
||||
cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
|
||||
switch(addtyp) {
|
||||
case 0:
|
||||
val[2] = (addr >> 8) & 0xff;
|
||||
val[3] = addr & 0xff;
|
||||
oplen += 2;
|
||||
vptr = 4;
|
||||
val[0] = 0x00 | opcode[j].opmask;
|
||||
break;
|
||||
case 1:
|
||||
val[2] = addr & 0xff;
|
||||
oplen += 1;
|
||||
vptr = 3;
|
||||
val[0] = 0x40 | opcode[j].opmask;
|
||||
break;
|
||||
case 2:
|
||||
val[2] = addr & 0xff;
|
||||
oplen += 1;
|
||||
vptr = 3;
|
||||
val[0] = 0x80 | opcode[j].opmask;
|
||||
break;
|
||||
default:
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
}
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
|
||||
switch(addtyp) {
|
||||
case 0:
|
||||
val[vptr] = (addr >> 8) & 0xff;
|
||||
val[vptr+1] = addr & 0xff;
|
||||
oplen += 2;
|
||||
break;
|
||||
case 1:
|
||||
val[vptr] = addr & 0xff;
|
||||
oplen += 1;
|
||||
val[0] = 0x10 | val[0];
|
||||
break;
|
||||
case 2:
|
||||
val[vptr] = addr & 0xff;
|
||||
oplen += 1;
|
||||
val[0] = 0x20 | val[0];
|
||||
break;
|
||||
default:
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
}
|
||||
val[1] = opcode[j].q;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return (-(oplen-1));
|
||||
}
|
||||
|
||||
char *parse_addr(char *cptr, char *gbuf, int32 *addr, int32 *addrtype)
|
||||
{
|
||||
int32 nybble = 0;
|
||||
char temp[32];
|
||||
|
||||
cptr = get_glyph(cptr, gbuf, ',');
|
||||
if (gbuf[0] == '(') { /* XR relative */
|
||||
strcpy(temp, gbuf+1);
|
||||
sscanf(temp, "%x", addr);
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, ',');
|
||||
nybble = -1;
|
||||
if (strcmp(gbuf, "XR1)") == 0)
|
||||
nybble = 1;
|
||||
if (strcmp(gbuf, "XR2)") == 0)
|
||||
nybble = 2;
|
||||
} else { /* Direct */
|
||||
sscanf(gbuf, "%x", addr);
|
||||
nybble = 0;
|
||||
}
|
||||
*addrtype = nybble;
|
||||
return cptr;
|
||||
}
|
||||
|
||||
472
S3/system3.txt
Normal file
472
S3/system3.txt
Normal file
@@ -0,0 +1,472 @@
|
||||
The IBM System/3 simulator is configured as follows:
|
||||
|
||||
CPU 5410 (Model 10) CPU with 64KB of memory.
|
||||
PKB 5471 Printer/Keyboard console.
|
||||
CDR 1442 Card Reader
|
||||
CDP 1442 Card Punch
|
||||
CDP2 1442 2nd stacker
|
||||
LPT 1403 Line Printer
|
||||
R1 5444 Top Drive (removeable)
|
||||
F1 5444 Top Drive (fixed)
|
||||
R2 5444 Bottom Drive (removeable)
|
||||
F2 5444 Bottom Drive (fixed
|
||||
|
||||
The only CPU options are to set Model 15 mode (not implemented), DPF
|
||||
(Dual Programming Facility, not implemented), and the memory size 8K, 16K,
|
||||
32K, 48K, or 64K.
|
||||
|
||||
CPU registers are the standard System/3 set:
|
||||
|
||||
name size Description
|
||||
|
||||
IAR-P1 16 Instruction Address Register for Program Level 1
|
||||
ARR-P2 16 Address Recall Register for Program Level 1
|
||||
IAR-P2 16 IAR for Program Level 2 (not implemented)
|
||||
ARR-P2 16 ARR for Program Level 2 (not implemented)
|
||||
AAR 16 A-Address Register
|
||||
BAR 16 B-Address Register
|
||||
PSR 16 Program Status Register
|
||||
XR1 16 Index Register 1
|
||||
XR2 16 Index Register 2
|
||||
IAR<0:7> 16 IAR for interrupt level 0 thru 7
|
||||
ARR<0:7> 16 ARR for interrupt level 0 thru 7
|
||||
|
||||
Plus these simulator registers:
|
||||
|
||||
IAR 16 Value of last IAR used.
|
||||
LEVEL 8 Current operating level (8=P1, 9=P2,
|
||||
0 thru 7 = Interrupt level)
|
||||
SR 16 Front Panel switches
|
||||
INT 16 Interrupt Request Flags
|
||||
WRU 8 Simulator Interrupt Character
|
||||
BREAK 17 Breakpoint Address
|
||||
DEBUG 16 Debugging bits:
|
||||
0x01: Write all instructions executed to
|
||||
file trace.log.
|
||||
0x02: Write details of all Disk I/O
|
||||
requests to trace.log.
|
||||
0x80: Breakpoint on first character
|
||||
written to 5471 printer.
|
||||
|
||||
1 5471 Printer/Keyboard
|
||||
|
||||
This is the operator console. It has the following registers:
|
||||
|
||||
FLAG 5471 Flag Bytes
|
||||
IBUF: Input character from keyboard
|
||||
OBUF: Output character to printer
|
||||
POS: Number of characters printed
|
||||
TIME: Delay for device operation
|
||||
REQKEY: ASCII value of key mapped to 5471 REQUEST key
|
||||
RTNKEY: ASCII value of key mapped to 5471 RETURN key
|
||||
ENDKEY: ASCII value of key mapped to 5471 END key
|
||||
CANKEY: ASCII value of key mapped to 5471 CANCEL key
|
||||
|
||||
|
||||
2 1442 Card Reader. This reader reads 80-column cards; the input
|
||||
is usually an ASCII file which is translated to EBCDIC when read,
|
||||
but optionally can be a binary file in EBCDIC format (such as an
|
||||
object program).
|
||||
|
||||
LAST Last card switch
|
||||
ERR Card Reader Error
|
||||
NOTRDY 1442 reader not ready (not attached or past EOF)
|
||||
DAR Data Address Register (shared with punch)
|
||||
LCR Length Count Register (shared with punch)
|
||||
EBCDIC EBCDIC mode flag: if 1, input is 80-col EBCDIC binary.
|
||||
(IPL from 1442 automatically sets this to 1).
|
||||
S2 Stacker 2 is selected when this is 1
|
||||
POS Number of cards read
|
||||
TIME Device Delay
|
||||
|
||||
The real hardware 1442 had only 1 hopper for cards, whether
|
||||
these were used for blank cards for punching, or cards to be
|
||||
read. Cards could be read without a feed cycle, then
|
||||
punched. When punching cards, the SCP does a read of a card,
|
||||
makes sure it is blank, and then punches it. To simulate
|
||||
this without requiring that a stack of blank lines be attached
|
||||
to the card reader device, a special feature of the simulator
|
||||
is this: if no file is attached to the cdr device, but a file
|
||||
is attached to the cdp or the cdp2 devices, any read from the
|
||||
reader will return a blank card -- i.e. when punching, an
|
||||
unattached cdr device is assumed to be loaded with an unlimited
|
||||
supply of blank cards.
|
||||
|
||||
|
||||
3 1442 Card Punch. Normally cards are written to the attached
|
||||
disk file as ASCII with newline/cr delimiters. But an optional
|
||||
flag allows writing as 80-column binary EBCDIC.
|
||||
|
||||
ERR Card Punch Error
|
||||
EBCDIC When this is 1, output will be 80-col EBCDIC.
|
||||
S2 When this is 1, output is placed in stacker 2
|
||||
NOTRDY 1442 punch not ready (not attached)
|
||||
DAR Data Address Register (shared with reader)
|
||||
LCR Length Count Register (shared with reader)
|
||||
POS Number of cards punched
|
||||
TIME Device Delay
|
||||
|
||||
4 1442 Stacker 2. When cards are to be punched in stacker 2,
|
||||
attach a disk file to this device (cdp2) to hold that output.
|
||||
Note: When SCP punches cards, the default is to punch in
|
||||
stacker 2.
|
||||
|
||||
POS0 Number of cards punched.
|
||||
|
||||
5 1403 Printer. This is a 132-column output device, emulating
|
||||
the famous IBM 1403, models 2, 6, and N1. Output is always
|
||||
translated to ASCII with newline/CR delimiters. Page advance
|
||||
is output as a form feed.
|
||||
|
||||
ERR 1403 error flags
|
||||
LPDAR Data Address Register
|
||||
LPFLR Forms Length Register
|
||||
LPIAR Image Address Register
|
||||
LINECT Current Line on form
|
||||
POS Number of lines printed
|
||||
|
||||
6 5444 Disk Drives (R1, R2, F1, F2)
|
||||
|
||||
The 5444 came as a set of two drives, each with two disks. The
|
||||
top disk in a drive was removable, the bottom fixed. The first
|
||||
drive consists of disks R1 and F1, the second drive R2 and F2.
|
||||
Each disk holds 2,467,600 bytes of user data, plus 3 alternate
|
||||
tracks and a CE track. Flagging of alternate tracks is not
|
||||
supported in this version of the simulator.
|
||||
|
||||
NOTRDY Drive not ready (not attached)
|
||||
SEEK Drive is busy with a seek operation
|
||||
DAR Data Address Register
|
||||
CAR Control Address Register
|
||||
ERR Error Flags (16 bits)
|
||||
CYL Current Cylinder (0 thru 203)
|
||||
HEAD Current head (0 or 1)
|
||||
POS Current position in attached disk file
|
||||
TIME Device Delay
|
||||
|
||||
7 Symbolic Display and Input
|
||||
|
||||
The System/3 Simulator supports symbolic display and input.
|
||||
Display is controlled by command line switches:
|
||||
|
||||
(none) display as hex EBCDIC
|
||||
-c display bytes as characters
|
||||
-m display instruction mnemonics.
|
||||
-a display a 256-byte block of memory in both hex and ASCII.
|
||||
|
||||
The symbolic format contains the same elements as the machine
|
||||
language operation, but not always in the same order. The
|
||||
operation code frequently specifies both the opcode and the Q byte,
|
||||
and the top nybble of the opcode is determined by the format of the
|
||||
addresses.
|
||||
|
||||
Addresses take two forms: the direct address in hex, or a relative
|
||||
address specified thusly: (byte,XRx) where 'byte' is a 1-byte
|
||||
offset, and XRx is either XR1 or XR2 for the two index registers.
|
||||
Use these formats when 'address' is indicated below:
|
||||
|
||||
When 'reg' is mentioned, a mnemonic may be used for the register,
|
||||
thusly:
|
||||
|
||||
IAR Instruction Address Register for the current program level
|
||||
ARR Address Recall Register for the current program level
|
||||
P1IAR IAR for Program Level 1
|
||||
P2IAR IAR for Program Level 2
|
||||
PSR Program Status Register
|
||||
XR1 Index Register 1
|
||||
XR2 Index Register 2
|
||||
IARx IAR for the interrupt level x (x = 0 thru 7)
|
||||
|
||||
All other operands mentioned below are single-byte hex, except for
|
||||
the length (len) operand of the two-address instructions, which is a
|
||||
decimal length in the range 1-256.
|
||||
|
||||
In operations where there is a source and a destination, the
|
||||
destination is always operand 1, the source is operand 2.
|
||||
|
||||
No-address formats:
|
||||
------------------
|
||||
|
||||
HPL hex,hex Halt Program Level, the operands are the
|
||||
Q and R bytes.
|
||||
|
||||
|
||||
One-address formats:
|
||||
-------------------
|
||||
|
||||
A reg,address Add to register
|
||||
CLI address,byte Compare Logical Immediate
|
||||
MVI address,byte Move Immediate
|
||||
TBF address,mask Test Bits Off
|
||||
TBN address,mask Test Bits On
|
||||
SBF address,mask Set Bits Off
|
||||
SBN address,mask Set Bits On
|
||||
ST reg,address Store Register
|
||||
L reg,address Load Register
|
||||
LA reg,address Load Address (reg can only be XR1 or XR2)
|
||||
JC address,cond Jump on Condition
|
||||
BC address,cond Branch on Condition
|
||||
|
||||
These operations do not specify a qbyte, it is implicit in the
|
||||
opcode:
|
||||
|
||||
B address Unconditional branch to address
|
||||
BE address Branch Equal
|
||||
BNE address Branch Not Equal
|
||||
BH address Branch High
|
||||
BNH address Branch Not High
|
||||
BL address Branch Low
|
||||
BNL address Branch Not Low
|
||||
BT address Branch True
|
||||
BF address Branch False
|
||||
BP address Branch Plus
|
||||
BM address Branch Minus
|
||||
BNP address Branch Not Plus
|
||||
BNM address Branch Not Minus
|
||||
BZ address Branch Zero
|
||||
BNZ address Branch Not Zero
|
||||
BOZ address Branch Overflow Zoned
|
||||
BOL address Branch Overflow Logical
|
||||
BNOZ address Branch No Overflow Zoned
|
||||
BNOL address Branch No Overflow Logical
|
||||
NOPB address No - never branch
|
||||
|
||||
(substitute J for B above for a set of Jumps -- 1-byte operand (not
|
||||
2), always jumps forward up to 255 bytes from the address following
|
||||
the Jump instruction. In this case, 'address' cannot be less than
|
||||
the current address, nor greater than the current address + 255)
|
||||
|
||||
Two-address formats (first address is destination, len is decimal 1-256):
|
||||
-------------------
|
||||
|
||||
MVC address,address,len Move Characters
|
||||
CLC address,address,len Compare Logical Characters
|
||||
ALC address,address,len Add Logical Characters
|
||||
SLC address,address,len Subtract Logical Characters
|
||||
ED address,address,len Edit
|
||||
ITC address,address,len Insert and Test Characters
|
||||
AZ address,address,len Add Zoned Decimal
|
||||
SZ address,address,len Subtract Zoned Decimal
|
||||
|
||||
MNN address,address Move Numeric to Numeric
|
||||
MNZ address,address Move Numeric to Zone
|
||||
MZZ address,address Move Zone to Zone
|
||||
MZN address,address Move Zone to Numeric
|
||||
|
||||
I/O Format
|
||||
----------
|
||||
|
||||
In the I/O format, there are always 3 fields:
|
||||
|
||||
da - Device Address 0-15 (decimal)
|
||||
m - Modifier 0-1
|
||||
n - Function 0-7
|
||||
|
||||
The meaning of these is entirely defined by the device addressed.
|
||||
|
||||
There may be an optional control byte, or an optional address (based
|
||||
on the type of instruction).
|
||||
|
||||
SNS da,m,n,address Sense I/O
|
||||
LIO da,m,n,address Load I/O
|
||||
TIO da,m,n,address Test I/O
|
||||
|
||||
SIO da,m,n,cc Start I/O -- cc is a control byte
|
||||
|
||||
APL da,m,n Advance Program Level
|
||||
|
||||
|
||||
8 Device Programming.
|
||||
|
||||
Note: On a model 15, interrupts are used for all devices. On
|
||||
other models, interrupts are only used for the printer/keyboard.
|
||||
|
||||
This is a summary of the DA, M, N, and CC codes for all supported
|
||||
devices:
|
||||
|
||||
5471 Printer Keyboard
|
||||
---------------------
|
||||
|
||||
The PKB has 2 visible indicators: Proceed and Request
|
||||
Pending. It has a normal keyboard and 4 special keys:
|
||||
Request, Return, End, and Cancel.
|
||||
|
||||
SIO 1,0,0,XX Start Keyboard Operation, bit masks for XX are:
|
||||
X'20': Request Pending Indicator On
|
||||
X'10': Proceed Indicator On
|
||||
X'04': Request Key Interrupts Enable (1) Disable (0)
|
||||
X'02': Other Key Interrupts Enable (1) Disable (0)
|
||||
X'01': Reset request key and other key interrupts
|
||||
|
||||
SIO 1,1,0,XX Start Printer Operation, bit masks for XX are:
|
||||
X'80': Start Printing
|
||||
X'40': Start Carrier Return
|
||||
X'04': Printer Interrupt Enable(1) or Disable (0)
|
||||
X'01': Reset Printer Interrupt
|
||||
|
||||
LIO 1,1,0,addr Load Printer Output Character
|
||||
addr is address of low-order (highest numbered)
|
||||
byte of two-byte field, and high-order byte
|
||||
(that is, addr - 1) is loaded into output
|
||||
register to print. Printing is done one character
|
||||
at a time.
|
||||
|
||||
SNS 1,0,1,addr Sense Status Bytes 0 and 1:
|
||||
Byte 0 (leftmost) is the character typed in
|
||||
in EBCDIC.
|
||||
Byte 1 is status:
|
||||
X'80': Request key interrupt pending
|
||||
X'40': End or Cancel key interrupt pending
|
||||
X'20': Cancel key pressed
|
||||
X'10': End Key Pressed
|
||||
X'08': Return or data key interrupt pending
|
||||
X'04': Return key pressed
|
||||
|
||||
SNS 1,0,3,addr Sense Status Bytes 2 and 3: returns 0000 in
|
||||
this sim.
|
||||
|
||||
1442 Reader/Punch
|
||||
-----------------
|
||||
|
||||
SIO 5,0,0,XX Feed Card without reading/punching
|
||||
XX is stacker select for all functions: 0 = stacker
|
||||
1 (normal), 1 = stacker 2.
|
||||
|
||||
SIO 5,0,1,XX Read Card
|
||||
SIO 5,0,2,XX Punch and Feed
|
||||
SIO 5,0,3,XX Read Column Binary
|
||||
SIO 5,0,4,XX Punch with no feed
|
||||
|
||||
TIO 5,0,0,addr Branch to addr if not ready or busy
|
||||
TIO 5,0,2,addr Branch to addr if busy
|
||||
TIO 5,0,5,addr (mod 15 only) branch if interrupt pending
|
||||
|
||||
APL 5,0,0 Loop (or switch prog levels) if not ready/busy
|
||||
APL 5,0,2 Loop (or switch) if busy
|
||||
APL 5,0,5 Loop (or switch) if interrupt pending (mod 15 only)
|
||||
|
||||
LIO 5,0,0,addr Load 2-byte field to Length Count Register
|
||||
LIO 5,0,4,addr Load 2-byte field to Data Address Register
|
||||
(DAR is incremented by a read/punch operation and must
|
||||
be reset every card)
|
||||
|
||||
SNS 5,0,1,addr Sense CE indicators (0000 returned in this sim)
|
||||
SNS 5,0,2,addr Sense CE indicators (0000 returned in this sim)
|
||||
SNS 5,0,3,addr Sense Status Indicators: (only simulated bits shown)
|
||||
X'8000': Read Check
|
||||
X'4000': Last Card
|
||||
X'2000': Punch Check
|
||||
X'1000': Data Overrun
|
||||
X'0800': Not Ready
|
||||
|
||||
|
||||
1403 Printer
|
||||
------------
|
||||
|
||||
SIO 14,0,0,XX Line space XX lines (0-3 valid in XX)
|
||||
SIO 14,0,2,XX Print a line space (0-3 valid in XX)
|
||||
SIO 14,0,4,XX Skip Only (line number 1-112 in XX)
|
||||
|
||||
SIO 14,0,6,XX Print and Skip (line number 0-112 in XX)
|
||||
|
||||
TIO 14,0,0,addr Branch to addr if not ready
|
||||
TIO 14,0,2,addr Branch to addr if buffer busy
|
||||
TIO 14,0,3,addr Branch to addr if interrupt pending (mod 15 only)
|
||||
TIO 14,0,4,addr Branch if carriage busy
|
||||
TIO 14,0,6,addr Branch if printer busy
|
||||
|
||||
APL 14,0,0 Loop (or switch prog levels) if not ready/check
|
||||
APL 14,0,2 Loop (or switch) if buffer busy
|
||||
APL 14,0,3 Loop (or switch) if interrupt pending (mod 15 only)
|
||||
APL 14,0,4 Loop (or switch) if carriage busy
|
||||
APL 14,0,6 Loop (or switch) if printer busy
|
||||
|
||||
LIO 14,0,0,addr Load 1 byte to Forms Length Reg at addr-1
|
||||
LIO 14,0,4,addr Load 2 bytes to Chain Image Address Register
|
||||
LIO 14,0,6,addr Load 2 bytes to Data Address Register
|
||||
|
||||
SNS 14,0,0,addr Sense Character Count
|
||||
SNS 14,0,4,addr Sense LPIAR (Image Address Register)
|
||||
SNS 14,0,6,addr Sense LPDAR (data addres register)
|
||||
|
||||
|
||||
5444 Disk Drives
|
||||
----------------
|
||||
|
||||
Each drive has two disks (upper and lower), each disk
|
||||
has two surfaces (upper and lower), each surface has
|
||||
24 256-byte sectors, sectors are number 0 thru 23 on
|
||||
upper surface, 32 thru 55 on lower.
|
||||
|
||||
d = drive, 0 is R1/F1, 1 is R2/F2
|
||||
s = surface, 0 = upper (removable), 1 = lower (fixed)
|
||||
|
||||
The Control register points to the leftmost byte of a 4-byte
|
||||
control field in memory with these bytes:
|
||||
|
||||
F - Flag byte (not supported in this sim)
|
||||
C - Cylinder Address (0-203)
|
||||
S - Sector Number (0-23, or 32-55) in top 6 bits
|
||||
N - Number of sectors minus 1
|
||||
|
||||
These have meaning for all operations except seek, seek uses
|
||||
the fields differently.
|
||||
|
||||
SIO 1d,s,0,XX Seek, XX not used, control field is used:
|
||||
|
||||
F - not used
|
||||
C - not used
|
||||
S - high bit is head to be used 0-upper 1-lower
|
||||
low bit is direction to move 0-back 1-forward
|
||||
N - number of cylinders to move
|
||||
|
||||
SIO 1d,s,1,XX Read, values of XX are as follows:
|
||||
X'00': Read Data
|
||||
X'01': Read Identifier (updates control field, no
|
||||
data is read)
|
||||
X'02': Read Data Diagnostic
|
||||
X'03': Verify (does not read, but checks)
|
||||
|
||||
SIO 1d,s,2,XX Write, values of XX are as follows:
|
||||
X'00': Write Data
|
||||
X'01': Write Identifier (24 sectors with byte at
|
||||
data address register)
|
||||
|
||||
SIO 1d,s,3,XX Scan. All 256 bytes in memory at data
|
||||
address register are compared to disk
|
||||
sectors on current track, except those
|
||||
bytes of X'FF' are not compared. Values of
|
||||
XX are:
|
||||
|
||||
X'00': Scan Equal
|
||||
X'01': Scan Low or Equal
|
||||
X'02': Scan High or Equal
|
||||
|
||||
LIO 1d,0,4,addr Load Data Address Register
|
||||
LIO 1d,0,6,addr Load Disk Control Address Register
|
||||
|
||||
TIO 1d,0,0,addr Branch if not ready/unit check
|
||||
TIO 1d,0,2,addr Branch if busy
|
||||
TIO 1d,0,4,addr Branch if Scan Found
|
||||
|
||||
APL 1d,0,0 Loop if not ready/unit check
|
||||
APL 1d,0,2 Loop if busy
|
||||
APL 1d,0,4 Loop if scan found
|
||||
|
||||
SNS 1d,0,2,addr Sense Status Bytes 0 and 1: (simulated
|
||||
bits only are shown, otehrs are 0):
|
||||
X'1000': equipment check
|
||||
X'0800': data check
|
||||
X'0400': No record found
|
||||
X'0100': Seek Check (past cyl 203)
|
||||
X'0080': Scan equal Hit
|
||||
X'0040': Cylinder 0
|
||||
X'0020': End of Cylinder
|
||||
X'0010': Seek Busy
|
||||
SNS 1d,0,3,addr Sense bytes 2 and 3 (0000 in this sim)
|
||||
SNS 1d,0,4,addr Sense Data Address Register
|
||||
SNS 1d,0,6,addr Sense Control Address Register
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user