mirror of
https://github.com/open-simh/simh.git
synced 2026-01-11 23:53:30 +00:00
S3: Restore original S3 code to branch
This commit is contained in:
parent
adf023bf86
commit
d29c6f43e3
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 --
|
||||
448
S3/s3_cd.c
Normal file
448
S3/s3_cd.c
Normal file
@ -0,0 +1,448 @@
|
||||
/* s3_cd.c: IBM 1442 card reader/punch
|
||||
|
||||
Copyright (c) 2001-2012, 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.
|
||||
|
||||
Except as contained in this notice, the name of Charles E. Owen shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Charles E. Owen.
|
||||
|
||||
cdr card reader
|
||||
cdp card punch
|
||||
cdp2 card punch stacker 2
|
||||
|
||||
19-Mar-12 RMS Fixed declaration of conversion tables (Mark Pizzolato)
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
08-Oct-02 RMS Added impossible function catcher
|
||||
|
||||
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 unsigned char ebcdic_to_ascii[];
|
||||
extern unsigned char ascii_to_ebcdic[];
|
||||
int32 s1sel, s2sel;
|
||||
char rbuf[CBUFSIZE]; /* > CDR_WIDTH */
|
||||
t_stat cdr_svc (UNIT *uptr);
|
||||
t_stat cdr_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat cdr_attach (UNIT *uptr, char *cptr);
|
||||
t_stat cd_reset (DEVICE *dptr);
|
||||
t_stat read_card (int32 ilnt, int32 mod);
|
||||
t_stat punch_card (int32 ilnt, int32 mod);
|
||||
|
||||
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 */
|
||||
|
||||
extern int32 GetMem(int32 addr);
|
||||
extern int32 PutMem(int32 addr, int32 data);
|
||||
|
||||
/* 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, T_ADDR_W), 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, T_ADDR_W), 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, 32), 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 stacker */
|
||||
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;
|
||||
}
|
||||
sim_printf (">>CRD non-existent function %d\n", op);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Card read routine
|
||||
mod 0 = ASCII read
|
||||
mod 1 = EBCDIC read
|
||||
*/
|
||||
|
||||
t_stat read_card (int32 ilnt, int32 mod)
|
||||
{
|
||||
int32 i;
|
||||
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; (size_t)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, DEVICE *dptr)
|
||||
{
|
||||
cdr_ebcdic = 1;
|
||||
DAR = 0;
|
||||
LCR = 80;
|
||||
read_card(0, 1);
|
||||
return SCPE_OK;
|
||||
}
|
||||
1830
S3/s3_cpu.c
Normal file
1830
S3/s3_cpu.c
Normal file
File diff suppressed because it is too large
Load Diff
94
S3/s3_defs.h
Normal file
94
S3/s3_defs.h
Normal file
@ -0,0 +1,94 @@
|
||||
/* s3_defs.h: IBM System/3 simulator definitions
|
||||
|
||||
Copyright (c) 2001-2005, 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.
|
||||
|
||||
Except as contained in this notice, the name of Charles E. Owen shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Charles E. Owen.
|
||||
*/
|
||||
|
||||
#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)(int32, int32, int32, int32); /* 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) */
|
||||
};
|
||||
792
S3/s3_disk.c
Normal file
792
S3/s3_disk.c
Normal file
@ -0,0 +1,792 @@
|
||||
/* s3_disk.c: IBM 5444 Disk Drives
|
||||
|
||||
Copyright (c) 2001-2005, 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.
|
||||
|
||||
Except as contained in this notice, the name of Charles E. Owen shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Charles E. Owen.
|
||||
|
||||
r1 Removeable disk 1
|
||||
f1 Fixed disk 1
|
||||
r2 Removeable disk 2
|
||||
f2 Fixed disk 2
|
||||
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
08-Oct-02 RMS Added impossible function catcher
|
||||
*/
|
||||
|
||||
#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 */
|
||||
int32 dsk (int32 disk, int32 op, int32 m, int32 n, int32 data);
|
||||
int32 read_sector(UNIT *uptr, char *dbuf, int32 sect);
|
||||
int32 write_sector(UNIT *uptr, char *dbuf, int32 sect);
|
||||
t_stat r1_svc (UNIT *uptr);
|
||||
t_stat r1_boot (int32 unitno, DEVICE *dptr);
|
||||
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, DEVICE *dptr);
|
||||
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, DEVICE *dptr);
|
||||
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, DEVICE *dptr);
|
||||
t_stat f2_attach (UNIT *uptr, char *cptr);
|
||||
t_stat f2_reset (DEVICE *dptr);
|
||||
extern int32 GetMem(int32 addr);
|
||||
extern int32 PutMem(int32 addr, int32 data);
|
||||
|
||||
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, T_ADDR_W), 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, 32), 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, 32), 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, 32), 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;
|
||||
/* TIO 5444 */
|
||||
case 2:
|
||||
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;
|
||||
}
|
||||
sim_printf (">>DSK%d non-existent function %d\n", disk, op);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* 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, DEVICE *dptr)
|
||||
{
|
||||
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, DEVICE *dptr)
|
||||
{
|
||||
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, DEVICE *dptr)
|
||||
{
|
||||
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, DEVICE *dptr)
|
||||
{
|
||||
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);
|
||||
}
|
||||
364
S3/s3_lp.c
Normal file
364
S3/s3_lp.c
Normal file
@ -0,0 +1,364 @@
|
||||
/* s3_lp.c: IBM 1403 line printer simulator
|
||||
|
||||
Copyright (c) 2001-2012, 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.
|
||||
|
||||
Except as contained in this notice, the name of Charles E. Owen shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Charles E. Owen.
|
||||
|
||||
lpt 1403 line printer
|
||||
|
||||
19-Mar-12 RMS Fixed declaration of conversion tables (Mark Pizzolato)
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
08-Oct-02 RMS Added impossible function catcher
|
||||
*/
|
||||
|
||||
#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 write_line (int32 ilnt, int32 mod);
|
||||
t_stat space (int32 lines, int32 lflag);
|
||||
t_stat carriage_control (int32 action, int32 mod);
|
||||
extern unsigned char ebcdic_to_ascii[];
|
||||
|
||||
#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, T_ADDR_W), 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;
|
||||
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;
|
||||
}
|
||||
sim_printf (">>LPT non-existent function %d\n", op);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
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 (mod == 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);
|
||||
}
|
||||
313
S3/s3_pkb.c
Normal file
313
S3/s3_pkb.c
Normal file
@ -0,0 +1,313 @@
|
||||
/* s3_pkb.c: System/3 5471 console terminal simulator
|
||||
|
||||
Copyright (c) 2001-2005, 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.
|
||||
|
||||
Except as contained in this notice, the name of Charles E. Owen shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Charles E. Owen.
|
||||
|
||||
pkb 5471 printer/keyboard
|
||||
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
08-Oct-02 RMS Added impossible function catcher
|
||||
*/
|
||||
|
||||
#include "s3_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||
t_stat pkb_svc (UNIT *uptr);
|
||||
t_stat pkb_reset (DEVICE *dptr);
|
||||
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, T_ADDR_W), 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, 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;
|
||||
}
|
||||
sim_printf (">>PKB non-existent function %d\n", op);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
950
S3/s3_sys.c
Normal file
950
S3/s3_sys.c
Normal file
@ -0,0 +1,950 @@
|
||||
/* s3_sys.c: IBM System/3 system interface
|
||||
|
||||
Copyright (c) 2001-2020, 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.
|
||||
|
||||
Except as contained in this notice, the name of Charles E. Owen shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Charles E. Owen.
|
||||
|
||||
06-Jun-20 RMS Fixed declaration of bldaddr (Mark Pizzolato)
|
||||
19-Mar-12 RMS Fixed declaration of conversion tables (Mark Pizzolato)
|
||||
*/
|
||||
|
||||
#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 unsigned char ebcdic_to_ascii[];
|
||||
char *parse_addr(char *cptr, char *gbuf, t_addr *addr, int32 *addrtype);
|
||||
|
||||
int32 printf_sym (FILE *of, char *strg, t_addr addr, uint32 *val,
|
||||
UNIT *uptr, int32 sw);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
t_stat 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
|
||||
*/
|
||||
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, uint32 *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);
|
||||
}
|
||||
|
||||
t_stat printf_sym (FILE *of, char *strg, t_addr addr, uint32 *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int32 c1, c2, group, len1, len2, inst, aaddr, baddr;
|
||||
int32 oplen, groupno, i, j, vpos, qbyte, da, m, n;
|
||||
char bld[128], bldaddr[160], boperand[32], aoperand[32];
|
||||
int32 blk[16], blt[16];
|
||||
int32 blkadd;
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
{
|
||||
int32 cflag, i = 0, j, 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, t_addr *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
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user