mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-24 17:04:19 +00:00
Upload
Digital Research
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
$ set noon
|
||||
$ as68 -l -u -p BDOSIF.s >BDOSIF.lis
|
||||
$ as68 -l -u -p CCPBDOS.s >CCPBDOS.lis
|
||||
$ as68 -l -u -p CCPIF.s >CCPIF.lis
|
||||
$ as68 -l -u -p CCPLOAD.s >CCPLOAD.lis
|
||||
$ as68 -l -u -p EXCEPTN.s >EXCEPTN.lis
|
||||
$ as68 -l -u -p FILETYPS.s >FILETYPS.lis
|
||||
$ as68 -l -u -p PGMLD.s >PGMLD.lis
|
||||
$ as68 -l -u -p STACK.s >STACK.lis
|
||||
180
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosdef.h
Normal file
180
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosdef.h
Normal file
@@ -0,0 +1,180 @@
|
||||
|
||||
/********************************************************
|
||||
* *
|
||||
* CP/M-68K header file *
|
||||
* Copyright (c) 1982 by Digital Research, Inc. *
|
||||
* Structure definitions for BDOS globals *
|
||||
* and BDOS data structures *
|
||||
* *
|
||||
* Desecrated 6-Aug-83 (sw) for type-ahead *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
The BDOS data structures, especially those relating to global variables,
|
||||
are structured in a way that hopefully will enable this BDOS, in the future,
|
||||
to easily become a re-entrant multi-tasking file system. Consequently,
|
||||
the BDOS global variables are divided into two classes. Those that are
|
||||
truly global, even in the case of multiple tasks using the file system
|
||||
concurrently, are simply declared as global variables in bdosmain.c.
|
||||
Only a few "globals" are really global in this sense.
|
||||
|
||||
The majority of the "global" variables are actually state variables that
|
||||
relate to the state of the task using the file system. In CP/M-68K, these
|
||||
are "global", since there's only one task, but in a multi-thread model they're
|
||||
not. This type of variables is put into a data structure, with the
|
||||
intention that in the multi-task environment this structure will be based.
|
||||
|
||||
The following declarations take this philosophy into account, and define
|
||||
a simple structure for the single thread environment while leaving the
|
||||
possibilities open for the multi-thread environment.
|
||||
****************************************************************************/
|
||||
|
||||
#define snglthrd TRUE
|
||||
/* TRUE for single-thread environment
|
||||
FALSE to create based structure for re-entrant model */
|
||||
#if snglthrd
|
||||
#define GBL gbls
|
||||
/* In single thread case, GBL just names
|
||||
the structure */
|
||||
#define BSETUP EXTERN struct stvars gbls;
|
||||
/* and BSETUP defines the extern structure */
|
||||
#endif
|
||||
|
||||
#if ! snglthrd
|
||||
#define GBL (*statep)
|
||||
/* If multi-task, state vars are based */
|
||||
#define BSETUP REG struct stvars *statep; \
|
||||
statep = &gbls;
|
||||
/* set up pointer to state variables */
|
||||
/* This is intended as an example to show the intent */
|
||||
#endif
|
||||
|
||||
|
||||
/* Note that there are a few critical regions in the file system that must
|
||||
execute without interruption. They pertain mostly to the manipulation of
|
||||
the allocation vector. This isn't a problem in a single-thread model, but
|
||||
must be provided for in a multi-tasking file system. Consequently, the
|
||||
primitives LOCK and UNLOCK are defined and used where necessary in the
|
||||
file system. For the single thread model, they are null routines */
|
||||
|
||||
#define LOCK /**/
|
||||
#define UNLOCK /**/
|
||||
/* Be sure LOCK and UNLOCK are implemented to allow recursive calls to LOCK.
|
||||
That is, if a process that calls LOCK already owns the lock, let it proceed,
|
||||
but remember that only the outer-most call to UNLOCK really releases the
|
||||
file system. */
|
||||
|
||||
|
||||
#define VERSION 0x2022 /* Version number for CP/M-68K */
|
||||
#define robit 0 /* read-only bit in file type field of fcb */
|
||||
#define arbit 2 /* archive bit in file type field of fcb */
|
||||
#define SECLEN 128 /* length of a CP/M sector */
|
||||
|
||||
|
||||
/* File Control Block definition */
|
||||
struct fcb
|
||||
{
|
||||
UBYTE drvcode; /* 0 = default drive, 1..16 are drives A..P */
|
||||
UBYTE fname[8]; /* File name (ASCII) */
|
||||
UBYTE ftype[3]; /* File type (ASCII) */
|
||||
UBYTE extent; /* Extent number (bits 0..4 used) */
|
||||
UBYTE s1; /* Reserved */
|
||||
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
|
||||
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
|
||||
union
|
||||
{
|
||||
UBYTE small[16]; /* 16 block numbers of 1 byte */
|
||||
WORD big[8]; /* or 8 block numbers of 1 word */
|
||||
} dskmap;
|
||||
UBYTE cur_rec; /* current record field */
|
||||
UBYTE ran0; /* random record field (3 bytes) */
|
||||
UBYTE ran1;
|
||||
UBYTE ran2;
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of directory entry */
|
||||
struct dirent
|
||||
{
|
||||
UBYTE entry; /* 0 - 15 for user numbers, E5 for empty */
|
||||
/* the rest are reserved */
|
||||
UBYTE fname[8]; /* File name (ASCII) */
|
||||
UBYTE ftype[3]; /* File type (ASCII) */
|
||||
UBYTE extent; /* Extent number (bits 0..4 used) */
|
||||
UBYTE s1; /* Reserved */
|
||||
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
|
||||
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
|
||||
union
|
||||
{
|
||||
UBYTE small[16]; /* 16 block numbers of 1 byte */
|
||||
WORD big[8]; /* or 8 block numbers of 1 word */
|
||||
} dskmap;
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of disk parameter tables */
|
||||
struct dpb /* disk parameter table */
|
||||
{
|
||||
UWORD spt; /* sectors per track */
|
||||
UBYTE bsh; /* block shift factor */
|
||||
UBYTE blm; /* block mask */
|
||||
UBYTE exm; /* extent mask */
|
||||
UBYTE dpbdum; /* dummy byte for fill */
|
||||
UWORD dsm; /* max disk size in blocks */
|
||||
UWORD drm; /* max directory entries */
|
||||
UWORD dir_al; /* initial allocation for dir */
|
||||
UWORD cks; /* number dir sectors to checksum */
|
||||
UWORD trk_off; /* track offset */
|
||||
};
|
||||
|
||||
struct dph /* disk parameter header */
|
||||
{
|
||||
UBYTE *xlt; /* pointer to sector translate table */
|
||||
UWORD hiwater; /* high water mark for this disk */
|
||||
UWORD dum1; /* dummy (unused) */
|
||||
UWORD dum2;
|
||||
UBYTE *dbufp; /* pointer to 128 byte directory buffer */
|
||||
struct dpb *dpbp; /* pointer to disk parameter block */
|
||||
UBYTE *csv; /* pointer to check vector */
|
||||
UBYTE *alv; /* pointer to allocation vector */
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of structure containing "global" state variables */
|
||||
#define TBUFSIZ 126 /*sw # typed-ahead characters */
|
||||
struct stvars
|
||||
{
|
||||
UBYTE kbchar; /* keyboard type-ahead buffer count */
|
||||
UBYTE delim; /* Delimiter for function 9 */
|
||||
BOOLEAN lstecho; /* True if echoing console output to lst: */
|
||||
BOOLEAN echodel; /* Echo char when getting <del> ? */
|
||||
UWORD column; /* CRT column number for expanding tabs */
|
||||
UBYTE *chainp; /* Used for chain to program call */
|
||||
UBYTE curdsk; /* Currently selected disk */
|
||||
UBYTE dfltdsk; /* Default disk (last selected by fcn 14) */
|
||||
UBYTE user; /* Current user number */
|
||||
struct dph *dphp; /* pointer to disk parm hdr for cur disk */
|
||||
struct dirent *dirbufp; /* pointer for directory buff for process */
|
||||
/* stored here so that each process can */
|
||||
/* have a separate dirbuf. */
|
||||
struct dpb *parmp; /* pointer to disk parameter block for cur */
|
||||
/* disk. Stored here to save ref calc */
|
||||
UWORD srchpos; /* position in directory for search next */
|
||||
UBYTE *dmaadr; /* Disk dma address */
|
||||
struct fcb *srchp; /* Pointer to search FCB for function 17 */
|
||||
UBYTE *excvec[18]; /* Array of exception vectors */
|
||||
UBYTE *insptr; /*sw Insertion pointer for typeahead */
|
||||
UBYTE *remptr; /*sw Removal pointer for typeahead */
|
||||
UBYTE t_buff[TBUFSIZ]; /*sw Type-ahead buffer itself */
|
||||
};
|
||||
|
||||
|
||||
/* Console buffer structure declaration */
|
||||
struct conbuf
|
||||
{
|
||||
UBYTE maxlen; /* Maximum length from calling routine */
|
||||
UBYTE retlen; /* Length actually found by BDOS */
|
||||
UBYTE cbuf[]; /* Console data */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
1File: BDOSDEF.H Page 1
|
||||
1
|
||||
2 /********************************************************
|
||||
3 * *
|
||||
4 * CP/M-68K header file *
|
||||
5 * Copyright (c) 1982 by Digital Research, Inc. *
|
||||
6 * Structure definitions for BDOS globals *
|
||||
7 * and BDOS data structures *
|
||||
8 * *
|
||||
9 * Desecrated 6-Aug-83 (sw) for type-ahead *
|
||||
10 * *
|
||||
11 ********************************************************/
|
||||
12
|
||||
13 /**************************************************************************
|
||||
14 The BDOS data structures, especially those relating to global variables,
|
||||
15 are structured in a way that hopefully will enable this BDOS, in the future,
|
||||
16 to easily become a re-entrant multi-tasking file system. Consequently,
|
||||
17 the BDOS global variables are divided into two classes. Those that are
|
||||
18 truly global, even in the case of multiple tasks using the file system
|
||||
19 concurrently, are simply declared as global variables in bdosmain.c.
|
||||
20 Only a few "globals" are really global in this sense.
|
||||
21
|
||||
22 The majority of the "global" variables are actually state variables that
|
||||
23 relate to the state of the task using the file system. In CP/M-68K, these
|
||||
24 are "global", since there's only one task, but in a multi-thread model they're
|
||||
25 not. This type of variables is put into a data structure, with the
|
||||
26 intention that in the multi-task environment this structure will be based.
|
||||
27
|
||||
28 The following declarations take this philosophy into account, and define
|
||||
29 a simple structure for the single thread environment while leaving the
|
||||
30 possibilities open for the multi-thread environment.
|
||||
31 ****************************************************************************/
|
||||
32
|
||||
33 #define snglthrd TRUE
|
||||
34 /* TRUE for single-thread environment
|
||||
35 FALSE to create based structure for re-entrant model */
|
||||
36 #if snglthrd
|
||||
37 #define GBL gbls
|
||||
38 /* In single thread case, GBL just names
|
||||
39 the structure */
|
||||
40 #define BSETUP EXTERN struct stvars gbls;
|
||||
41 /* and BSETUP defines the extern structure */
|
||||
42 #endif
|
||||
43
|
||||
44 #if ! snglthrd
|
||||
45 #define GBL (*statep)
|
||||
46 /* If multi-task, state vars are based */
|
||||
47 #define BSETUP REG struct stvars *statep; \
|
||||
48 statep = &gbls;
|
||||
49 /* set up pointer to state variables */
|
||||
50 /* This is intended as an example to show the intent */
|
||||
51 #endif
|
||||
52
|
||||
53
|
||||
54 /* Note that there are a few critical regions in the file system that must
|
||||
55 execute without interruption. They pertain mostly to the manipulation of
|
||||
56 the allocation vector. This isn't a problem in a single-thread model, but
|
||||
57 must be provided for in a multi-tasking file system. Consequently, the
|
||||
58 primitives LOCK and UNLOCK are defined and used where necessary in the
|
||||
59 file system. For the single thread model, they are null routines */
|
||||
1File: BDOSDEF.H Page 2
|
||||
60
|
||||
61 #define LOCK /**/
|
||||
62 #define UNLOCK /**/
|
||||
63 /* Be sure LOCK and UNLOCK are implemented to allow recursive calls to LOCK.
|
||||
64 That is, if a process that calls LOCK already owns the lock, let it proceed,
|
||||
65 but remember that only the outer-most call to UNLOCK really releases the
|
||||
66 file system. */
|
||||
67
|
||||
68
|
||||
69 #define VERSION 0x2022 /* Version number for CP/M-68K */
|
||||
70 #define robit 0 /* read-only bit in file type field of fcb */
|
||||
71 #define arbit 2 /* archive bit in file type field of fcb */
|
||||
72 #define SECLEN 128 /* length of a CP/M sector */
|
||||
73
|
||||
74
|
||||
75 /* File Control Block definition */
|
||||
76 struct fcb
|
||||
77 {
|
||||
78 UBYTE drvcode; /* 0 = default drive, 1..16 are drives A..P */
|
||||
79 UBYTE fname[8]; /* File name (ASCII) */
|
||||
80 UBYTE ftype[3]; /* File type (ASCII) */
|
||||
81 UBYTE extent; /* Extent number (bits 0..4 used) */
|
||||
82 UBYTE s1; /* Reserved */
|
||||
83 UBYTE s2; /* Module field (bits 0..5), write flag (7) */
|
||||
84 UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
|
||||
85 union
|
||||
86 {
|
||||
87 UBYTE small[16]; /* 16 block numbers of 1 byte */
|
||||
88 WORD big[8]; /* or 8 block numbers of 1 word */
|
||||
89 } dskmap;
|
||||
90 UBYTE cur_rec; /* current record field */
|
||||
91 UBYTE ran0; /* random record field (3 bytes) */
|
||||
92 UBYTE ran1;
|
||||
93 UBYTE ran2;
|
||||
94 };
|
||||
95
|
||||
96
|
||||
97 /* Declaration of directory entry */
|
||||
98 struct dirent
|
||||
99 {
|
||||
100 UBYTE entry; /* 0 - 15 for user numbers, E5 for empty */
|
||||
101 /* the rest are reserved */
|
||||
102 UBYTE fname[8]; /* File name (ASCII) */
|
||||
103 UBYTE ftype[3]; /* File type (ASCII) */
|
||||
104 UBYTE extent; /* Extent number (bits 0..4 used) */
|
||||
105 UBYTE s1; /* Reserved */
|
||||
106 UBYTE s2; /* Module field (bits 0..5), write flag (7) */
|
||||
107 UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
|
||||
108 union
|
||||
109 {
|
||||
110 UBYTE small[16]; /* 16 block numbers of 1 byte */
|
||||
111 WORD big[8]; /* or 8 block numbers of 1 word */
|
||||
112 } dskmap;
|
||||
113 };
|
||||
114
|
||||
115
|
||||
116 /* Declaration of disk parameter tables */
|
||||
117 struct dpb /* disk parameter table */
|
||||
118 {
|
||||
1File: BDOSDEF.H Page 3
|
||||
119 UWORD spt; /* sectors per track */
|
||||
120 UBYTE bsh; /* block shift factor */
|
||||
121 UBYTE blm; /* block mask */
|
||||
122 UBYTE exm; /* extent mask */
|
||||
123 UBYTE dpbdum; /* dummy byte for fill */
|
||||
124 UWORD dsm; /* max disk size in blocks */
|
||||
125 UWORD drm; /* max directory entries */
|
||||
126 UWORD dir_al; /* initial allocation for dir */
|
||||
127 UWORD cks; /* number dir sectors to checksum */
|
||||
128 UWORD trk_off; /* track offset */
|
||||
129 };
|
||||
130
|
||||
131 struct dph /* disk parameter header */
|
||||
132 {
|
||||
133 UBYTE *xlt; /* pointer to sector translate table */
|
||||
134 UWORD hiwater; /* high water mark for this disk */
|
||||
135 UWORD dum1; /* dummy (unused) */
|
||||
136 UWORD dum2;
|
||||
137 UBYTE *dbufp; /* pointer to 128 byte directory buffer */
|
||||
138 struct dpb *dpbp; /* pointer to disk parameter block */
|
||||
139 UBYTE *csv; /* pointer to check vector */
|
||||
140 UBYTE *alv; /* pointer to allocation vector */
|
||||
141 };
|
||||
142
|
||||
143
|
||||
144 /* Declaration of structure containing "global" state variables */
|
||||
145 #define TBUFSIZ 126 /*sw # typed-ahead characters */
|
||||
146 struct stvars
|
||||
147 {
|
||||
148 UBYTE kbchar; /* keyboard type-ahead buffer count */
|
||||
149 UBYTE delim; /* Delimiter for function 9 */
|
||||
150 BOOLEAN lstecho; /* True if echoing console output to lst: */
|
||||
151 BOOLEAN echodel; /* Echo char when getting <del> ? */
|
||||
152 UWORD column; /* CRT column number for expanding tabs */
|
||||
153 UBYTE *chainp; /* Used for chain to program call */
|
||||
154 UBYTE curdsk; /* Currently selected disk */
|
||||
155 UBYTE dfltdsk; /* Default disk (last selected by fcn 14) */
|
||||
156 UBYTE user; /* Current user number */
|
||||
157 struct dph *dphp; /* pointer to disk parm hdr for cur disk */
|
||||
158 struct dirent *dirbufp; /* pointer for directory buff for process */
|
||||
159 /* stored here so that each process can */
|
||||
160 /* have a separate dirbuf. */
|
||||
161 struct dpb *parmp; /* pointer to disk parameter block for cur */
|
||||
162 /* disk. Stored here to save ref calc */
|
||||
163 UWORD srchpos; /* position in directory for search next */
|
||||
164 UBYTE *dmaadr; /* Disk dma address */
|
||||
165 struct fcb *srchp; /* Pointer to search FCB for function 17 */
|
||||
166 UBYTE *excvec[18]; /* Array of exception vectors */
|
||||
167 UBYTE *insptr; /*sw Insertion pointer for typeahead */
|
||||
168 UBYTE *remptr; /*sw Removal pointer for typeahead */
|
||||
169 UBYTE t_buff[TBUFSIZ]; /*sw Type-ahead buffer itself */
|
||||
170 };
|
||||
171
|
||||
172
|
||||
173 /* Console buffer structure declaration */
|
||||
174 struct conbuf
|
||||
175 {
|
||||
176 UBYTE maxlen; /* Maximum length from calling routine */
|
||||
177 UBYTE retlen; /* Length actually found by BDOS */
|
||||
1File: BDOSDEF.H Page 4
|
||||
178 UBYTE cbuf[]; /* Console data */
|
||||
179 };
|
||||
180
|
||||
173
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosif.lis
Normal file
173
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosif.lis
Normal file
@@ -0,0 +1,173 @@
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 1
|
||||
Source File: bdosif.s
|
||||
|
||||
1
|
||||
2 *****************************************************************
|
||||
3 * *
|
||||
4 * CP/M-68K Basic Disk Operating System interface module *
|
||||
5 * For "C" version of CP/M-68K *
|
||||
6 * *
|
||||
7 * Copyright (c) 1982 Digital Research, Inc. *
|
||||
8 * *
|
||||
9 * Version 0.2 -- September 22, 1982 *
|
||||
10 * *
|
||||
11 *****************************************************************
|
||||
12
|
||||
13 * Declare Public Routines
|
||||
14
|
||||
15 .globl _bios1 * 6 BIOS entry points from BDOS
|
||||
16 .globl _bios2
|
||||
17 .globl _bios3
|
||||
18 .globl _bios4
|
||||
19 .globl _bios5
|
||||
20 .globl _bios6
|
||||
21 .globl _traphnd * trap #2 handler
|
||||
22 .globl _swap * byte swapper
|
||||
23 .globl _udiv * unsigned divide routine
|
||||
24
|
||||
25 * Declare external routines
|
||||
26 .globl __bdos * BDOS entry point in bdosmain
|
||||
27
|
||||
28 * The following external references were put in just to make sure that all
|
||||
29 * the BDOS modules were referenced, so we could put them in a library
|
||||
30 .globl _constat * references conbdos.o
|
||||
31 .globl _dirscan * references dskutil.o
|
||||
32 .globl _create * references fileio.o
|
||||
33 .globl _bdosrw * references bdosrw.o
|
||||
34
|
||||
35 biosf = 50
|
||||
36 setsupf = 62
|
||||
37
|
||||
38 _traphnd:
|
||||
39 *
|
||||
40 * first save the registers and
|
||||
41 * check for functions handled by assembly language routines
|
||||
42 *
|
||||
43 00000000 0C40003E cmpi #setsupf,d0
|
||||
44 00000004 672C beq setsup
|
||||
45 00000006 48E77FFE movem.l d1-d7/a0-a6,-(sp)
|
||||
46 0000000A 0C400032 cmpi #biosf,d0
|
||||
47 0000000E 6716 beq bioscall
|
||||
48 *
|
||||
49 * function number is passed in D0
|
||||
50 * byte and word pararmeters are passed in D1.W
|
||||
51 * address parameters are passed in D1.L
|
||||
52 *
|
||||
53 00000010 2F01 move.l d1,-(a7)
|
||||
54 00000012 3F01 move.w d1,-(a7)
|
||||
55 00000014 3F00 move.w d0,-(a7)
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 2
|
||||
Source File: bdosif.s
|
||||
|
||||
56 00000016 4EB900000000 jsr __bdos * call BDOS
|
||||
57 *
|
||||
58 * now restore the regs
|
||||
59 *
|
||||
60 0000001C 48C0 ext.l d0
|
||||
61 0000001E 504F addq #8,sp * fix up the stack
|
||||
62 bdone:
|
||||
63 00000020 4CDF7FFE movem.l (sp)+,a0-a6/d1-d7
|
||||
64 00000024 4E73 rte * return from trap call
|
||||
65
|
||||
66 *
|
||||
67 * direct BIOS call function
|
||||
68 *
|
||||
69 bioscall:
|
||||
70 00000026 2041 move.l d1,a0 * get address of CPB
|
||||
71 00000028 3018 move.w (a0)+,d0
|
||||
72 0000002A 4CD80006 movem.l (a0)+,d1-d2
|
||||
73 0000002E 4E43 trap #3
|
||||
74 00000030 60EE bra bdone
|
||||
75
|
||||
76 *
|
||||
77 * Set supervisor mode procedure
|
||||
78 *
|
||||
79 setsup:
|
||||
80 00000032 00572000 ori #$2000,(sp) * turn on supervisor bit in SR
|
||||
81 00000036 4E73 rte
|
||||
82
|
||||
83 *
|
||||
84 * BIOS Interface Routines
|
||||
85 *
|
||||
86 *
|
||||
87 * Note - there are 6 BIOS entry points from the BDOS, labelled BIOS1 -
|
||||
88 * BIOS6, depending on the parameters passed.
|
||||
89
|
||||
90 _bios5:
|
||||
91 * For BIOS functions sectran and set exception vector
|
||||
92 * Has function number and 2 parameters, a word followed by a long word
|
||||
93 00000038 242F0008 move.l 8(sp),d2 * get 2nd parameter (long word)
|
||||
94 0000003C 600C bra _bios2 * join common routine
|
||||
95
|
||||
96 _bios4:
|
||||
97 * For BIOS function seldsk
|
||||
98 * Has function number followed by 2 word parameters
|
||||
99 0000003E 342F0008 move.w 8(sp),d2 * get 2nd parameter (word)
|
||||
100 00000042 6006 bra _bios2 * join common routine
|
||||
101
|
||||
102 _bios3:
|
||||
103 * For BIOS function set dma
|
||||
104 * Has function number followed by 1 long parameter
|
||||
105 00000044 222F0006 move.l 6(sp),d1 * get long word parameter
|
||||
106 00000048 6004 bra _bios1 * join common routine
|
||||
107
|
||||
108 _bios2:
|
||||
109 * For all BIOS functions with a word parameter
|
||||
110 * Word parameter follows function number
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 3
|
||||
Source File: bdosif.s
|
||||
|
||||
111 0000004A 322F0006 move.w 6(sp),d1 * get 1st parameter (word)
|
||||
112
|
||||
113 _bios6:
|
||||
114 _bios1:
|
||||
115 * For all BIOS functions that have no parameter other than function number
|
||||
116 0000004E 302F0004 move.w 4(sp),d0 * get function number
|
||||
117 00000052 48E71F1E movem.l d3-d7/a3-a6,-(sp)
|
||||
118 * * save C register variables
|
||||
119 00000056 4E43 trap #3 * do BIOS call
|
||||
120 * * returns value in d0
|
||||
121 00000058 4CDF78F8 movem.l (sp)+,d3-d7/a3-a6
|
||||
122 0000005C 4E75 rts
|
||||
123
|
||||
124 *
|
||||
125 * Utility Subroutines
|
||||
126 *
|
||||
127
|
||||
128 _swap:
|
||||
129 * Swap bytes of a word, return swapped value in d0
|
||||
130 0000005E 102F0005 move.b 5(sp),d0
|
||||
131 00000062 E148 lsl #8,d0
|
||||
132 00000064 102F0004 move.b 4(sp),d0
|
||||
133 00000068 4E75 rts
|
||||
134
|
||||
135 _udiv:
|
||||
136 * Unsigned divide routine
|
||||
137 * returns unsigned quotient in D0.W
|
||||
138
|
||||
139 * UWORD udiv( divisor, dividend, remp )
|
||||
140 *
|
||||
141 * REG LONG divisor;
|
||||
142 * UWORD dividend;
|
||||
143 * UWORD *remp /* pointer to remainder (returned) */
|
||||
144
|
||||
145 0000006A 202F0004 move.l 4(sp), d0 * get dividend
|
||||
146 0000006E 80EF0008 divu 8(sp), d0 * do the divide
|
||||
147 00000072 206F000A movea.l 10(sp),a0
|
||||
148 00000076 4840 swap d0
|
||||
149 00000078 3080 move.w d0, (a0) * store remainder
|
||||
150 0000007A 4240 clr.w d0
|
||||
151 0000007C 4840 swap d0 * word quotient in d0
|
||||
152 0000007E 4E75 rts
|
||||
153
|
||||
154 00000080 .end
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 4
|
||||
Source File: bdosif.s
|
||||
|
||||
S y m b o l T a b l e
|
||||
|
||||
__bdos ******** EXT _bdosrw ******** EXT _bios1 0000004E TEXT _bios2 0000004A TEXT
|
||||
_bios3 00000044 TEXT _bios4 0000003E TEXT _bios5 00000038 TEXT _bios6 0000004E TEXT
|
||||
_constat ******** EXT _create ******** EXT _dirscan ******** EXT _swap 0000005E TEXT
|
||||
_traphnd 00000000 TEXT _udiv 0000006A TEXT bdone 00000020 TEXT bioscall 00000026 TEXT
|
||||
biosf 00000032 ABS setsup 00000032 TEXT setsupf 0000003E ABS
|
||||
154
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosif.s
Normal file
154
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosif.s
Normal file
@@ -0,0 +1,154 @@
|
||||
|
||||
*****************************************************************
|
||||
* *
|
||||
* CP/M-68K Basic Disk Operating System interface module *
|
||||
* For "C" version of CP/M-68K *
|
||||
* *
|
||||
* Copyright (c) 1982 Digital Research, Inc. *
|
||||
* *
|
||||
* Version 0.2 -- September 22, 1982 *
|
||||
* *
|
||||
*****************************************************************
|
||||
|
||||
* Declare Public Routines
|
||||
|
||||
.globl _bios1 * 6 BIOS entry points from BDOS
|
||||
.globl _bios2
|
||||
.globl _bios3
|
||||
.globl _bios4
|
||||
.globl _bios5
|
||||
.globl _bios6
|
||||
.globl _traphnd * trap #2 handler
|
||||
.globl _swap * byte swapper
|
||||
.globl _udiv * unsigned divide routine
|
||||
|
||||
* Declare external routines
|
||||
.globl __bdos * BDOS entry point in bdosmain
|
||||
|
||||
* The following external references were put in just to make sure that all
|
||||
* the BDOS modules were referenced, so we could put them in a library
|
||||
.globl _constat * references conbdos.o
|
||||
.globl _dirscan * references dskutil.o
|
||||
.globl _create * references fileio.o
|
||||
.globl _bdosrw * references bdosrw.o
|
||||
|
||||
biosf = 50
|
||||
setsupf = 62
|
||||
|
||||
_traphnd:
|
||||
*
|
||||
* first save the registers and
|
||||
* check for functions handled by assembly language routines
|
||||
*
|
||||
cmpi #setsupf,d0
|
||||
beq setsup
|
||||
movem.l d1-d7/a0-a6,-(sp)
|
||||
cmpi #biosf,d0
|
||||
beq bioscall
|
||||
*
|
||||
* function number is passed in D0
|
||||
* byte and word pararmeters are passed in D1.W
|
||||
* address parameters are passed in D1.L
|
||||
*
|
||||
move.l d1,-(a7)
|
||||
move.w d1,-(a7)
|
||||
move.w d0,-(a7)
|
||||
jsr __bdos * call BDOS
|
||||
*
|
||||
* now restore the regs
|
||||
*
|
||||
ext.l d0
|
||||
addq #8,sp * fix up the stack
|
||||
bdone:
|
||||
movem.l (sp)+,a0-a6/d1-d7
|
||||
rte * return from trap call
|
||||
|
||||
*
|
||||
* direct BIOS call function
|
||||
*
|
||||
bioscall:
|
||||
move.l d1,a0 * get address of CPB
|
||||
move.w (a0)+,d0
|
||||
movem.l (a0)+,d1-d2
|
||||
trap #3
|
||||
bra bdone
|
||||
|
||||
*
|
||||
* Set supervisor mode procedure
|
||||
*
|
||||
setsup:
|
||||
ori #$2000,(sp) * turn on supervisor bit in SR
|
||||
rte
|
||||
|
||||
*
|
||||
* BIOS Interface Routines
|
||||
*
|
||||
*
|
||||
* Note - there are 6 BIOS entry points from the BDOS, labelled BIOS1 -
|
||||
* BIOS6, depending on the parameters passed.
|
||||
|
||||
_bios5:
|
||||
* For BIOS functions sectran and set exception vector
|
||||
* Has function number and 2 parameters, a word followed by a long word
|
||||
move.l 8(sp),d2 * get 2nd parameter (long word)
|
||||
bra _bios2 * join common routine
|
||||
|
||||
_bios4:
|
||||
* For BIOS function seldsk
|
||||
* Has function number followed by 2 word parameters
|
||||
move.w 8(sp),d2 * get 2nd parameter (word)
|
||||
bra _bios2 * join common routine
|
||||
|
||||
_bios3:
|
||||
* For BIOS function set dma
|
||||
* Has function number followed by 1 long parameter
|
||||
move.l 6(sp),d1 * get long word parameter
|
||||
bra _bios1 * join common routine
|
||||
|
||||
_bios2:
|
||||
* For all BIOS functions with a word parameter
|
||||
* Word parameter follows function number
|
||||
move.w 6(sp),d1 * get 1st parameter (word)
|
||||
|
||||
_bios6:
|
||||
_bios1:
|
||||
* For all BIOS functions that have no parameter other than function number
|
||||
move.w 4(sp),d0 * get function number
|
||||
movem.l d3-d7/a3-a6,-(sp)
|
||||
* * save C register variables
|
||||
trap #3 * do BIOS call
|
||||
* * returns value in d0
|
||||
movem.l (sp)+,d3-d7/a3-a6
|
||||
rts
|
||||
|
||||
*
|
||||
* Utility Subroutines
|
||||
*
|
||||
|
||||
_swap:
|
||||
* Swap bytes of a word, return swapped value in d0
|
||||
move.b 5(sp),d0
|
||||
lsl #8,d0
|
||||
move.b 4(sp),d0
|
||||
rts
|
||||
|
||||
_udiv:
|
||||
* Unsigned divide routine
|
||||
* returns unsigned quotient in D0.W
|
||||
|
||||
* UWORD udiv( divisor, dividend, remp )
|
||||
*
|
||||
* REG LONG divisor;
|
||||
* UWORD dividend;
|
||||
* UWORD *remp /* pointer to remainder (returned) */
|
||||
|
||||
move.l 4(sp), d0 * get dividend
|
||||
divu 8(sp), d0 * do the divide
|
||||
movea.l 10(sp),a0
|
||||
swap d0
|
||||
move.w d0, (a0) * store remainder
|
||||
clr.w d0
|
||||
swap d0 * word quotient in d0
|
||||
rts
|
||||
|
||||
.end
|
||||
@@ -0,0 +1,68 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* C P / M C H E A D E R F I L E
|
||||
* -----------------------------------
|
||||
* Copyright 1982 by Digital Research Inc. All rights reserved.
|
||||
*
|
||||
* This is an include file for assisting the user to write portable
|
||||
* programs for C.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define ALCYON 1 /* using Alcyon compiler */
|
||||
/*
|
||||
* Standard type definitions
|
||||
*/
|
||||
/***************************/
|
||||
#define BYTE char /* Signed byte */
|
||||
#define BOOLEAN char /* 2 valued (true/false) */
|
||||
#define WORD short /* Signed word (16 bits) */
|
||||
#define UWORD unsigned int /* unsigned word */
|
||||
#define LONG long /* signed long (32 bits) */
|
||||
#define ULONG unsigned long /* Unsigned long */
|
||||
#define REG register /* register variable */
|
||||
#define LOCAL auto /* Local var on 68000 */
|
||||
#define EXTERN extern /* External variable */
|
||||
#define MLOCAL static /* Local to module */
|
||||
#define GLOBAL /**/ /* Global variable */
|
||||
#define VOID /**/ /* Void function return */
|
||||
/***************************/
|
||||
#ifdef ALCYON
|
||||
#define UBYTE char
|
||||
#define UBWORD(a) ((UWORD)a & 0xff)
|
||||
/* Unsigned byte to word cast */
|
||||
#else
|
||||
#define UBYTE unsigned char /* Unsigned byte */
|
||||
#define UBWORD(a) (UWORD)a
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Miscellaneous Definitions: */
|
||||
/****************************************************************************/
|
||||
#define FAILURE (-1) /* Function failure return val */
|
||||
#define SUCCESS (0) /* Function success return val */
|
||||
#define YES 1 /* "TRUE" */
|
||||
#define NO 0 /* "FALSE" */
|
||||
#define FOREVER for(;;) /* Infinite loop declaration */
|
||||
#define NULL (BYTE *)0 /* Null pointer value */
|
||||
#define EOF (-1) /* EOF Value */
|
||||
#define TRUE (1) /* Function TRUE value */
|
||||
#define FALSE (0) /* Function FALSE value */
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* M A C R O S */
|
||||
/* ----------- */
|
||||
/* */
|
||||
/* Define some stuff as macros .... */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#define abs(x) ((x) < 0 ? -(x) : (x)) /* Absolute value function */
|
||||
|
||||
#define max(x,y) (((x) > (y)) ? (x) : (y)) /* Max function */
|
||||
#define min(x,y) (((x) < (y)) ? (x) : (y)) /* Min function */
|
||||
|
||||
/*************************** end of stdio.h *********************************/
|
||||
@@ -0,0 +1,70 @@
|
||||
1File: BDOSINC.H Page 1
|
||||
1 /*****************************************************************************
|
||||
2 *
|
||||
3 * C P / M C H E A D E R F I L E
|
||||
4 * -----------------------------------
|
||||
5 * Copyright 1982 by Digital Research Inc. All rights reserved.
|
||||
6 *
|
||||
7 * This is an include file for assisting the user to write portable
|
||||
8 * programs for C.
|
||||
9 *
|
||||
10 *****************************************************************************/
|
||||
11 #define ALCYON 1 /* using Alcyon compiler */
|
||||
12 /*
|
||||
13 * Standard type definitions
|
||||
14 */
|
||||
15 /***************************/
|
||||
16 #define BYTE char /* Signed byte */
|
||||
17 #define BOOLEAN char /* 2 valued (true/false) */
|
||||
18 #define WORD short /* Signed word (16 bits) */
|
||||
19 #define UWORD unsigned int /* unsigned word */
|
||||
20 #define LONG long /* signed long (32 bits) */
|
||||
21 #define ULONG unsigned long /* Unsigned long */
|
||||
22 #define REG register /* register variable */
|
||||
23 #define LOCAL auto /* Local var on 68000 */
|
||||
24 #define EXTERN extern /* External variable */
|
||||
25 #define MLOCAL static /* Local to module */
|
||||
26 #define GLOBAL /**/ /* Global variable */
|
||||
27 #define VOID /**/ /* Void function return */
|
||||
28 /***************************/
|
||||
29 #ifdef ALCYON
|
||||
30 #define UBYTE char
|
||||
31 #define UBWORD(a) ((UWORD)a & 0xff)
|
||||
32 /* Unsigned byte to word cast */
|
||||
33 #else
|
||||
34 #define UBYTE unsigned char /* Unsigned byte */
|
||||
35 #define UBWORD(a) (UWORD)a
|
||||
36 #endif
|
||||
37
|
||||
38
|
||||
39
|
||||
40 /****************************************************************************/
|
||||
41 /* Miscellaneous Definitions: */
|
||||
42 /****************************************************************************/
|
||||
43 #define FAILURE (-1) /* Function failure return val */
|
||||
44 #define SUCCESS (0) /* Function success return val */
|
||||
45 #define YES 1 /* "TRUE" */
|
||||
46 #define NO 0 /* "FALSE" */
|
||||
47 #define FOREVER for(;;) /* Infinite loop declaration */
|
||||
48 #define NULL (BYTE *)0 /* Null pointer value */
|
||||
49 #define EOF (-1) /* EOF Value */
|
||||
50 #define TRUE (1) /* Function TRUE value */
|
||||
51 #define FALSE (0) /* Function FALSE value */
|
||||
52
|
||||
53
|
||||
54 /****************************************************************************/
|
||||
55 /* */
|
||||
56 /* M A C R O S */
|
||||
57 /* ----------- */
|
||||
58 /* */
|
||||
59 /* Define some stuff as macros .... */
|
||||
1File: BDOSINC.H Page 2
|
||||
60 /* */
|
||||
61 /****************************************************************************/
|
||||
62
|
||||
63 #define abs(x) ((x) < 0 ? -(x) : (x)) /* Absolute value function */
|
||||
64
|
||||
65 #define max(x,y) (((x) > (y)) ? (x) : (y)) /* Max function */
|
||||
66 #define min(x,y) (((x) < (y)) ? (x) : (y)) /* Min function */
|
||||
67
|
||||
68 /*************************** end of stdio.h *********************************/
|
||||
304
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosmain.c
Normal file
304
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosmain.c
Normal file
@@ -0,0 +1,304 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-68K BDOS Main Routine *
|
||||
* *
|
||||
* This is the main routine for the BDOS for CP/M-68K *
|
||||
* It has one entry point, _bdos, which is called from *
|
||||
* the assembly language trap handler found in bdosif.s. *
|
||||
* The parameters are a function number (integer) and an *
|
||||
* information parameter (which is passed from bdosif as *
|
||||
* both an integer and a pointer).
|
||||
* The BDOS can potentially return a pointer, long word, *
|
||||
* or word *
|
||||
* *
|
||||
* Configured for Alcyon C on the VAX *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "bdosinc.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "biosdef.h" /* Declarations of BIOS functions */
|
||||
|
||||
/* Declare EXTERN functions */
|
||||
|
||||
EXTERN warmboot(); /* Warm Boot function */
|
||||
EXTERN BOOLEAN constat(); /* Console status */
|
||||
EXTERN UBYTE conin(); /* Console Input function */
|
||||
EXTERN tabout(); /* Console output with tab expansion */
|
||||
EXTERN UBYTE rawconio(); /* Raw console I/O */
|
||||
EXTERN prt_line(); /* Print line until delimiter */
|
||||
EXTERN readline(); /* Buffered console read */
|
||||
EXTERN seldsk(); /* Select disk */
|
||||
EXTERN BOOLEAN openfile(); /* Open File */
|
||||
EXTERN UWORD close_fi(); /* Close File */
|
||||
EXTERN UWORD search(); /* Search first and next fcns */
|
||||
EXTERN UWORD dirscan(); /* General directory scanning routine */
|
||||
EXTERN UWORD bdosrw(); /* Sequential and Random disk read/write */
|
||||
EXTERN BOOLEAN create(); /* Create file */
|
||||
EXTERN BOOLEAN delete(); /* Delete file */
|
||||
EXTERN BOOLEAN rename(); /* Rename file */
|
||||
EXTERN BOOLEAN set_attr(); /* Set file attributes */
|
||||
EXTERN getsize(); /* Get File Size */
|
||||
EXTERN setran(); /* Set Random Record */
|
||||
EXTERN free_sp(); /* Get Disk Free Space */
|
||||
EXTERN UWORD flushit(); /* Flush Buffers */
|
||||
EXTERN UWORD pgmld(); /* Program Load */
|
||||
EXTERN UWORD setexc(); /* Set Exception Vector */
|
||||
EXTERN set_tpa(); /* Get/Set TPA Limits */
|
||||
EXTERN move(); /* general purpose byte mover */
|
||||
|
||||
|
||||
/* Declare "true" global variables; i.e., those which will pertain to the
|
||||
entire file system and thus will remain global even when this becomes
|
||||
a multi-tasking file system */
|
||||
|
||||
GLOBAL UWORD log_dsk; /* 16-bit vector of logged in drives */
|
||||
GLOBAL UWORD ro_dsk; /* 16-bit vector of read-only drives */
|
||||
GLOBAL UWORD crit_dsk; /* 16-bit vector of drives in "critical"
|
||||
state. Used to control dir checksums */
|
||||
GLOBAL BYTE *tpa_lp; /* TPA lower boundary (permanent) */
|
||||
GLOBAL BYTE *tpa_lt; /* TPA lower boundary (temporary) */
|
||||
GLOBAL BYTE *tpa_hp; /* TPA upper boundary (permanent) */
|
||||
GLOBAL BYTE *tpa_ht; /* TPA upper boundary (temporary) */
|
||||
|
||||
|
||||
/* Declare the "state variables". These are globals for the single-thread
|
||||
version of the file system, but are put in a structure so they can be
|
||||
based, with a pointer coming from the calling process */
|
||||
|
||||
GLOBAL struct stvars gbls;
|
||||
|
||||
struct tempstr
|
||||
{
|
||||
UBYTE tempdisk;
|
||||
BOOLEAN reselect;
|
||||
struct fcb *fptr;
|
||||
};
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* _bdos MAIN ROUTINE *
|
||||
* *
|
||||
* Called with _bdos(func, info, infop) *
|
||||
* *
|
||||
* Where: *
|
||||
* func is the BDOS function number (d0.w) *
|
||||
* info is the word parameter (d1.w) *
|
||||
* infop is the pointer parameter (d1.l) *
|
||||
* note that info is the word form of infop*
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
|
||||
UWORD _bdos(func,info,infop)
|
||||
REG WORD func; /* BDOS function number */
|
||||
REG UWORD info; /* d1.w word parameter */
|
||||
REG UBYTE *infop; /* d1.l pointer parameter */
|
||||
{
|
||||
REG UWORD rtnval;
|
||||
LOCAL struct tempstr temp;
|
||||
BSETUP
|
||||
|
||||
temp.reselect = FALSE;
|
||||
temp.fptr = infop;
|
||||
rtnval = 0;
|
||||
|
||||
switch (func) /* switch on function number */
|
||||
{
|
||||
case 0: warmboot(0); /* warm boot function */
|
||||
/* break; */
|
||||
|
||||
case 1: return((UWORD)conin()); /* console input function */
|
||||
/* break; */
|
||||
|
||||
case 2: tabout((UBYTE)info); /* console output with */
|
||||
break; /* tab expansion */
|
||||
|
||||
case 3: return((UWORD)brdr()); /* get reader from bios */
|
||||
/* break; */
|
||||
|
||||
case 4: bpun((UBYTE)info); /* punch output to bios */
|
||||
break;
|
||||
|
||||
case 5: blstout((UBYTE)info); /* list output from bios */
|
||||
break;
|
||||
|
||||
case 6: return((UWORD)rawconio(info)); /* raw console I/O */
|
||||
/* break; */
|
||||
|
||||
case 7: return(bgetiob()); /* get i/o byte */
|
||||
/* break; */
|
||||
|
||||
case 8: bsetiob(info); /* set i/o byte function */
|
||||
break;
|
||||
|
||||
case 9: prt_line(infop); /* print line function */
|
||||
break;
|
||||
|
||||
case 10: readline(infop); /* read buffered con input */
|
||||
break;
|
||||
|
||||
case 11: return((UWORD)constat()); /* console status */
|
||||
/* break; */
|
||||
|
||||
case 12: return(VERSION); /* return version number */
|
||||
/* break; */
|
||||
|
||||
case 13: log_dsk = 0; /* reset disk system */
|
||||
ro_dsk = 0;
|
||||
crit_dsk= 0;
|
||||
GBL.curdsk = 0xff;
|
||||
GBL.dfltdsk = 0;
|
||||
break;
|
||||
|
||||
case 14: seldsk((UBYTE)info); /* select disk */
|
||||
GBL.dfltdsk = (UBYTE)info;
|
||||
break;
|
||||
|
||||
case 15: tmp_sel(&temp); /* open file */
|
||||
infop->extent = 0;
|
||||
infop->s2 = 0;
|
||||
rtnval = dirscan(openfile, infop, 0);
|
||||
break;
|
||||
|
||||
case 16: tmp_sel(&temp); /* close file */
|
||||
rtnval = close_fi(infop);
|
||||
break;
|
||||
|
||||
case 17: GBL.srchp = infop; /* search first */
|
||||
rtnval = search(infop, 0, &temp);
|
||||
break;
|
||||
|
||||
case 18: infop = GBL.srchp; /* search next */
|
||||
temp.fptr = infop;
|
||||
rtnval = search(infop, 1, &temp);
|
||||
break;
|
||||
|
||||
case 19: tmp_sel(&temp); /* delete file */
|
||||
rtnval = dirscan(delete, infop, 2);
|
||||
break;
|
||||
|
||||
case 20: tmp_sel(&temp); /* read sequential */
|
||||
rtnval = bdosrw(infop, TRUE, 0);
|
||||
break;
|
||||
|
||||
case 21: tmp_sel(&temp); /* write sequential */
|
||||
rtnval = bdosrw(infop, FALSE, 0);
|
||||
break;
|
||||
|
||||
case 22: tmp_sel(&temp); /* create file */
|
||||
infop->extent = 0;
|
||||
infop->s1 = 0;
|
||||
infop->s2 = 0;
|
||||
infop->rcdcnt = 0;
|
||||
/* Zero extent, S1, S2, rcrdcnt. create zeros rest */
|
||||
rtnval = dirscan(create, infop, 8);
|
||||
break;
|
||||
|
||||
case 23: tmp_sel(&temp); /* rename file */
|
||||
rtnval = dirscan(rename, infop, 2);
|
||||
break;
|
||||
|
||||
case 24: return(log_dsk); /* return login vector */
|
||||
/* break; */
|
||||
|
||||
case 25: return(UBWORD(GBL.dfltdsk)); /* return current disk */
|
||||
/* break; */
|
||||
|
||||
case 26: GBL.dmaadr = infop; /* set dma address */
|
||||
break;
|
||||
|
||||
/* No function 27 -- Get Allocation Vector */
|
||||
|
||||
case 28: ro_dsk |= 1<<GBL.dfltdsk; /* set disk read-only */
|
||||
break;
|
||||
|
||||
case 29: return(ro_dsk); /* get read-only vector */
|
||||
/* break; */
|
||||
|
||||
case 30: tmp_sel(&temp); /* set file attributes */
|
||||
rtnval = dirscan(set_attr, infop, 2);
|
||||
break;
|
||||
|
||||
case 31: if (GBL.curdsk != GBL.dfltdsk) seldsk(GBL.dfltdsk);
|
||||
move( (GBL.parmp), infop, sizeof *(GBL.parmp) );
|
||||
break; /* return disk parameters */
|
||||
|
||||
case 32: if ( (info & 0xff) <= 15 ) /* get/set user number */
|
||||
GBL.user = (UBYTE)info;
|
||||
return(UBWORD(GBL.user));
|
||||
/* break; */
|
||||
|
||||
case 33: tmp_sel(&temp); /* random read */
|
||||
rtnval = bdosrw(infop, TRUE, 1);
|
||||
break;
|
||||
|
||||
case 34: tmp_sel(&temp); /* random write */
|
||||
rtnval = bdosrw(infop, FALSE, 1);
|
||||
break;
|
||||
|
||||
case 35: tmp_sel(&temp); /* get file size */
|
||||
getsize(infop);
|
||||
break;
|
||||
|
||||
case 36: tmp_sel(&temp); /* set random record */
|
||||
setran(infop);
|
||||
break;
|
||||
|
||||
case 37: info = ~info; /* reset drive */
|
||||
log_dsk &= info;
|
||||
ro_dsk &= info;
|
||||
crit_dsk &= info;
|
||||
break;
|
||||
|
||||
case 40: tmp_sel(&temp); /* write random with 0 fill */
|
||||
rtnval = bdosrw(infop, FALSE, 2);
|
||||
break;
|
||||
|
||||
case 46: free_sp(info); /* get disk free space */
|
||||
break;
|
||||
|
||||
case 47: GBL.chainp = GBL.dmaadr; /* chain to program */
|
||||
warmboot(0); /* terminate calling program */
|
||||
/* break; */
|
||||
|
||||
case 48: return( flushit() ); /* flush buffers */
|
||||
/* break; */
|
||||
|
||||
case 59: return(pgmld(infop,GBL.dmaadr)); /* program load */
|
||||
/* break; */
|
||||
|
||||
case 61: return(setexc(infop)); /* set exception vector */
|
||||
/* break; */
|
||||
|
||||
case 63: set_tpa(infop); /* get/set TPA limits */
|
||||
break;
|
||||
|
||||
default: return(-1); /* bad function number */
|
||||
/* break; */
|
||||
|
||||
}; /* end of switch statement */
|
||||
if (temp.reselect) infop->drvcode = temp.tempdisk;
|
||||
/* if reselected disk, restore it now */
|
||||
|
||||
return(rtnval); /* return the BDOS return value */
|
||||
} /* end _bdos */
|
||||
|
||||
|
||||
tmp_sel(temptr) /* temporarily select disk pointed to by fcb */
|
||||
REG struct tempstr *temptr;
|
||||
{
|
||||
REG struct fcb *fcbp;
|
||||
REG UBYTE tmp_dsk;
|
||||
BSETUP
|
||||
|
||||
fcbp = temptr->fptr; /* get local copy of fcb pointer */
|
||||
tmp_dsk = (temptr->tempdisk = fcbp->drvcode);
|
||||
seldsk( tmp_dsk ? tmp_dsk - 1 : GBL.dfltdsk );
|
||||
|
||||
fcbp->drvcode = GBL.user;
|
||||
temptr->reselect = TRUE;
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
1File: BDOSMAIN.C Page 1
|
||||
1
|
||||
2 /****************************************************************
|
||||
3 * *
|
||||
4 * CP/M-68K BDOS Main Routine *
|
||||
5 * *
|
||||
6 * This is the main routine for the BDOS for CP/M-68K *
|
||||
7 * It has one entry point, _bdos, which is called from *
|
||||
8 * the assembly language trap handler found in bdosif.s. *
|
||||
9 * The parameters are a function number (integer) and an *
|
||||
10 * information parameter (which is passed from bdosif as *
|
||||
11 * both an integer and a pointer).
|
||||
12 * The BDOS can potentially return a pointer, long word, *
|
||||
13 * or word *
|
||||
14 * *
|
||||
15 * Configured for Alcyon C on the VAX *
|
||||
16 * *
|
||||
17 ****************************************************************/
|
||||
18
|
||||
19 #include "bdosinc.h" /* Standard I/O declarations */
|
||||
20
|
||||
21 #include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
22
|
||||
23 #include "biosdef.h" /* Declarations of BIOS functions */
|
||||
24
|
||||
25 /* Declare EXTERN functions */
|
||||
26
|
||||
27 EXTERN warmboot(); /* Warm Boot function */
|
||||
28 EXTERN BOOLEAN constat(); /* Console status */
|
||||
29 EXTERN UBYTE conin(); /* Console Input function */
|
||||
30 EXTERN tabout(); /* Console output with tab expansion */
|
||||
31 EXTERN UBYTE rawconio(); /* Raw console I/O */
|
||||
32 EXTERN prt_line(); /* Print line until delimiter */
|
||||
33 EXTERN readline(); /* Buffered console read */
|
||||
34 EXTERN seldsk(); /* Select disk */
|
||||
35 EXTERN BOOLEAN openfile(); /* Open File */
|
||||
36 EXTERN UWORD close_fi(); /* Close File */
|
||||
37 EXTERN UWORD search(); /* Search first and next fcns */
|
||||
38 EXTERN UWORD dirscan(); /* General directory scanning routine */
|
||||
39 EXTERN UWORD bdosrw(); /* Sequential and Random disk read/write */
|
||||
40 EXTERN BOOLEAN create(); /* Create file */
|
||||
41 EXTERN BOOLEAN delete(); /* Delete file */
|
||||
42 EXTERN BOOLEAN rename(); /* Rename file */
|
||||
43 EXTERN BOOLEAN set_attr(); /* Set file attributes */
|
||||
44 EXTERN getsize(); /* Get File Size */
|
||||
45 EXTERN setran(); /* Set Random Record */
|
||||
46 EXTERN free_sp(); /* Get Disk Free Space */
|
||||
47 EXTERN UWORD flushit(); /* Flush Buffers */
|
||||
48 EXTERN UWORD pgmld(); /* Program Load */
|
||||
49 EXTERN UWORD setexc(); /* Set Exception Vector */
|
||||
50 EXTERN set_tpa(); /* Get/Set TPA Limits */
|
||||
51 EXTERN move(); /* general purpose byte mover */
|
||||
52
|
||||
53
|
||||
54 /* Declare "true" global variables; i.e., those which will pertain to the
|
||||
55 entire file system and thus will remain global even when this becomes
|
||||
56 a multi-tasking file system */
|
||||
57
|
||||
58 GLOBAL UWORD log_dsk; /* 16-bit vector of logged in drives */
|
||||
59 GLOBAL UWORD ro_dsk; /* 16-bit vector of read-only drives */
|
||||
1File: BDOSMAIN.C Page 2
|
||||
60 GLOBAL UWORD crit_dsk; /* 16-bit vector of drives in "critical"
|
||||
61 state. Used to control dir checksums */
|
||||
62 GLOBAL BYTE *tpa_lp; /* TPA lower boundary (permanent) */
|
||||
63 GLOBAL BYTE *tpa_lt; /* TPA lower boundary (temporary) */
|
||||
64 GLOBAL BYTE *tpa_hp; /* TPA upper boundary (permanent) */
|
||||
65 GLOBAL BYTE *tpa_ht; /* TPA upper boundary (temporary) */
|
||||
66
|
||||
67
|
||||
68 /* Declare the "state variables". These are globals for the single-thread
|
||||
69 version of the file system, but are put in a structure so they can be
|
||||
70 based, with a pointer coming from the calling process */
|
||||
71
|
||||
72 GLOBAL struct stvars gbls;
|
||||
73
|
||||
74 struct tempstr
|
||||
75 {
|
||||
76 UBYTE tempdisk;
|
||||
77 BOOLEAN reselect;
|
||||
78 struct fcb *fptr;
|
||||
79 };
|
||||
80
|
||||
81 /****************************************************************
|
||||
82 * *
|
||||
83 * _bdos MAIN ROUTINE *
|
||||
84 * *
|
||||
85 * Called with _bdos(func, info, infop) *
|
||||
86 * *
|
||||
87 * Where: *
|
||||
88 * func is the BDOS function number (d0.w) *
|
||||
89 * info is the word parameter (d1.w) *
|
||||
90 * infop is the pointer parameter (d1.l) *
|
||||
91 * note that info is the word form of infop*
|
||||
92 * *
|
||||
93 ****************************************************************/
|
||||
94
|
||||
95
|
||||
96 UWORD _bdos(func,info,infop)
|
||||
97 REG WORD func; /* BDOS function number */
|
||||
98 REG UWORD info; /* d1.w word parameter */
|
||||
99 REG UBYTE *infop; /* d1.l pointer parameter */
|
||||
100 {
|
||||
101 REG UWORD rtnval;
|
||||
102 LOCAL struct tempstr temp;
|
||||
103 BSETUP
|
||||
104
|
||||
105 temp.reselect = FALSE;
|
||||
106 temp.fptr = infop;
|
||||
107 rtnval = 0;
|
||||
108
|
||||
109 switch (func) /* switch on function number */
|
||||
110 {
|
||||
111 case 0: warmboot(0); /* warm boot function */
|
||||
112 /* break; */
|
||||
113
|
||||
114 case 1: return((UWORD)conin()); /* console input function */
|
||||
115 /* break; */
|
||||
116
|
||||
117 case 2: tabout((UBYTE)info); /* console output with */
|
||||
118 break; /* tab expansion */
|
||||
1File: BDOSMAIN.C Page 3
|
||||
119
|
||||
120 case 3: return((UWORD)brdr()); /* get reader from bios */
|
||||
121 /* break; */
|
||||
122
|
||||
123 case 4: bpun((UBYTE)info); /* punch output to bios */
|
||||
124 break;
|
||||
125
|
||||
126 case 5: blstout((UBYTE)info); /* list output from bios */
|
||||
127 break;
|
||||
128
|
||||
129 case 6: return((UWORD)rawconio(info)); /* raw console I/O */
|
||||
130 /* break; */
|
||||
131
|
||||
132 case 7: return(bgetiob()); /* get i/o byte */
|
||||
133 /* break; */
|
||||
134
|
||||
135 case 8: bsetiob(info); /* set i/o byte function */
|
||||
136 break;
|
||||
137
|
||||
138 case 9: prt_line(infop); /* print line function */
|
||||
139 break;
|
||||
140
|
||||
141 case 10: readline(infop); /* read buffered con input */
|
||||
142 break;
|
||||
143
|
||||
144 case 11: return((UWORD)constat()); /* console status */
|
||||
145 /* break; */
|
||||
146
|
||||
147 case 12: return(VERSION); /* return version number */
|
||||
148 /* break; */
|
||||
149
|
||||
150 case 13: log_dsk = 0; /* reset disk system */
|
||||
151 ro_dsk = 0;
|
||||
152 crit_dsk= 0;
|
||||
153 GBL.curdsk = 0xff;
|
||||
154 GBL.dfltdsk = 0;
|
||||
155 break;
|
||||
156
|
||||
157 case 14: seldsk((UBYTE)info); /* select disk */
|
||||
158 GBL.dfltdsk = (UBYTE)info;
|
||||
159 break;
|
||||
160
|
||||
161 case 15: tmp_sel(&temp); /* open file */
|
||||
162 infop->extent = 0;
|
||||
163 infop->s2 = 0;
|
||||
164 rtnval = dirscan(openfile, infop, 0);
|
||||
165 break;
|
||||
166
|
||||
167 case 16: tmp_sel(&temp); /* close file */
|
||||
168 rtnval = close_fi(infop);
|
||||
169 break;
|
||||
170
|
||||
171 case 17: GBL.srchp = infop; /* search first */
|
||||
172 rtnval = search(infop, 0, &temp);
|
||||
173 break;
|
||||
174
|
||||
175 case 18: infop = GBL.srchp; /* search next */
|
||||
176 temp.fptr = infop;
|
||||
177 rtnval = search(infop, 1, &temp);
|
||||
1File: BDOSMAIN.C Page 4
|
||||
178 break;
|
||||
179
|
||||
180 case 19: tmp_sel(&temp); /* delete file */
|
||||
181 rtnval = dirscan(delete, infop, 2);
|
||||
182 break;
|
||||
183
|
||||
184 case 20: tmp_sel(&temp); /* read sequential */
|
||||
185 rtnval = bdosrw(infop, TRUE, 0);
|
||||
186 break;
|
||||
187
|
||||
188 case 21: tmp_sel(&temp); /* write sequential */
|
||||
189 rtnval = bdosrw(infop, FALSE, 0);
|
||||
190 break;
|
||||
191
|
||||
192 case 22: tmp_sel(&temp); /* create file */
|
||||
193 infop->extent = 0;
|
||||
194 infop->s1 = 0;
|
||||
195 infop->s2 = 0;
|
||||
196 infop->rcdcnt = 0;
|
||||
197 /* Zero extent, S1, S2, rcrdcnt. create zeros rest */
|
||||
198 rtnval = dirscan(create, infop, 8);
|
||||
199 break;
|
||||
200
|
||||
201 case 23: tmp_sel(&temp); /* rename file */
|
||||
202 rtnval = dirscan(rename, infop, 2);
|
||||
203 break;
|
||||
204
|
||||
205 case 24: return(log_dsk); /* return login vector */
|
||||
206 /* break; */
|
||||
207
|
||||
208 case 25: return(UBWORD(GBL.dfltdsk)); /* return current disk */
|
||||
209 /* break; */
|
||||
210
|
||||
211 case 26: GBL.dmaadr = infop; /* set dma address */
|
||||
212 break;
|
||||
213
|
||||
214 /* No function 27 -- Get Allocation Vector */
|
||||
215
|
||||
216 case 28: ro_dsk |= 1<<GBL.dfltdsk; /* set disk read-only */
|
||||
217 break;
|
||||
218
|
||||
219 case 29: return(ro_dsk); /* get read-only vector */
|
||||
220 /* break; */
|
||||
221
|
||||
222 case 30: tmp_sel(&temp); /* set file attributes */
|
||||
223 rtnval = dirscan(set_attr, infop, 2);
|
||||
224 break;
|
||||
225
|
||||
226 case 31: if (GBL.curdsk != GBL.dfltdsk) seldsk(GBL.dfltdsk);
|
||||
227 move( (GBL.parmp), infop, sizeof *(GBL.parmp) );
|
||||
228 break; /* return disk parameters */
|
||||
229
|
||||
230 case 32: if ( (info & 0xff) <= 15 ) /* get/set user number */
|
||||
231 GBL.user = (UBYTE)info;
|
||||
232 return(UBWORD(GBL.user));
|
||||
233 /* break; */
|
||||
234
|
||||
235 case 33: tmp_sel(&temp); /* random read */
|
||||
236 rtnval = bdosrw(infop, TRUE, 1);
|
||||
1File: BDOSMAIN.C Page 5
|
||||
237 break;
|
||||
238
|
||||
239 case 34: tmp_sel(&temp); /* random write */
|
||||
240 rtnval = bdosrw(infop, FALSE, 1);
|
||||
241 break;
|
||||
242
|
||||
243 case 35: tmp_sel(&temp); /* get file size */
|
||||
244 getsize(infop);
|
||||
245 break;
|
||||
246
|
||||
247 case 36: tmp_sel(&temp); /* set random record */
|
||||
248 setran(infop);
|
||||
249 break;
|
||||
250
|
||||
251 case 37: info = ~info; /* reset drive */
|
||||
252 log_dsk &= info;
|
||||
253 ro_dsk &= info;
|
||||
254 crit_dsk &= info;
|
||||
255 break;
|
||||
256
|
||||
257 case 40: tmp_sel(&temp); /* write random with 0 fill */
|
||||
258 rtnval = bdosrw(infop, FALSE, 2);
|
||||
259 break;
|
||||
260
|
||||
261 case 46: free_sp(info); /* get disk free space */
|
||||
262 break;
|
||||
263
|
||||
264 case 47: GBL.chainp = GBL.dmaadr; /* chain to program */
|
||||
265 warmboot(0); /* terminate calling program */
|
||||
266 /* break; */
|
||||
267
|
||||
268 case 48: return( flushit() ); /* flush buffers */
|
||||
269 /* break; */
|
||||
270
|
||||
271 case 59: return(pgmld(infop,GBL.dmaadr)); /* program load */
|
||||
272 /* break; */
|
||||
273
|
||||
274 case 61: return(setexc(infop)); /* set exception vector */
|
||||
275 /* break; */
|
||||
276
|
||||
277 case 63: set_tpa(infop); /* get/set TPA limits */
|
||||
278 break;
|
||||
279
|
||||
280 default: return(-1); /* bad function number */
|
||||
281 /* break; */
|
||||
282
|
||||
283 }; /* end of switch statement */
|
||||
284 if (temp.reselect) infop->drvcode = temp.tempdisk;
|
||||
285 /* if reselected disk, restore it now */
|
||||
286
|
||||
287 return(rtnval); /* return the BDOS return value */
|
||||
288 } /* end _bdos */
|
||||
289
|
||||
290
|
||||
291 tmp_sel(temptr) /* temporarily select disk pointed to by fcb */
|
||||
292 REG struct tempstr *temptr;
|
||||
293 {
|
||||
294 REG struct fcb *fcbp;
|
||||
295 REG UBYTE tmp_dsk;
|
||||
1File: BDOSMAIN.C Page 6
|
||||
296 BSETUP
|
||||
297
|
||||
298 fcbp = temptr->fptr; /* get local copy of fcb pointer */
|
||||
299 tmp_dsk = (temptr->tempdisk = fcbp->drvcode);
|
||||
300 seldsk( tmp_dsk ? tmp_dsk - 1 : GBL.dfltdsk );
|
||||
301
|
||||
302 fcbp->drvcode = GBL.user;
|
||||
303 temptr->reselect = TRUE;
|
||||
304 }
|
||||
308
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosmisc.c
Normal file
308
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosmisc.c
Normal file
@@ -0,0 +1,308 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-68K BDOS Miscellaneous Module *
|
||||
* *
|
||||
* This module contains miscellaneous loose ends for *
|
||||
* CP/M-68K. Included are: *
|
||||
* *
|
||||
* bdosinit() - BDOS initialization routine *
|
||||
* called from CCP for system init *
|
||||
* warmboot() - BDOS warm boot exit routine *
|
||||
* error() - BDOS error printing routine *
|
||||
* ro_err() - BDOS read-only file error routine *
|
||||
* setexc() - BDOS set exception vector *
|
||||
* set_tpa() - BDOS get/set TPA limits *
|
||||
* serial # and copyright notice, machine readable *
|
||||
* *
|
||||
* *
|
||||
* Configured for Alcyon C on the VAX *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "bdosinc.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "biosdef.h" /* BIOS definitions, needed for bios wboot */
|
||||
|
||||
|
||||
/* serial # and copyright notice */
|
||||
|
||||
char *copyrt="CP/M-68K(tm), Version 1.1, Copyright (c) 1983, Digital Research";
|
||||
char *serial="XXXX-0000-654321";
|
||||
|
||||
|
||||
|
||||
/* Declare external functions */
|
||||
EXTERN conout(); /* Console Output function */
|
||||
EXTERN UBYTE conin(); /* Console Input function */
|
||||
EXTERN prt_line(); /* Print String function */
|
||||
EXTERN UWORD _bdos(); /* BDOS main routine */
|
||||
EXTERN UBYTE *traphndl(); /* assembly language trap handler */
|
||||
EXTERN initexc(); /* init the exception handler in */
|
||||
/* exceptn.s */
|
||||
EXTERN UWORD dirscan(); /* Directory scanning routine */
|
||||
EXTERN BOOLEAN set_attr(); /* Set File attributes function */
|
||||
EXTERN UWORD dir_rd(); /* Read directory sector routine */
|
||||
|
||||
/* Declare external variables */
|
||||
EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
EXTERN UWORD crit_dsk; /* vector of critical disks */
|
||||
EXTERN BYTE *tpa_lt; /* TPA lower limit (temporary) */
|
||||
EXTERN BYTE *tpa_lp; /* TPA lower limit (permanent) */
|
||||
EXTERN BYTE *tpa_ht; /* TPA upper limit (temporary) */
|
||||
EXTERN BYTE *tpa_hp; /* TPA upper limit (permanent) */
|
||||
EXTERN BOOLEAN submit; /* external variables from CCP */
|
||||
EXTERN BOOLEAN morecmds;
|
||||
|
||||
|
||||
#define trap2v 34 /* trap 2 vector number */
|
||||
#define ctrlc 3 /* control-c */
|
||||
|
||||
|
||||
/********************************
|
||||
* bdos initialization routine *
|
||||
********************************/
|
||||
|
||||
bdosinit()
|
||||
/* Initialize the File System */
|
||||
{
|
||||
REG struct
|
||||
{
|
||||
WORD nmbr;
|
||||
BYTE *low;
|
||||
LONG length;
|
||||
} *segp;
|
||||
BSETUP
|
||||
|
||||
bsetvec(trap2v, &traphndl); /* set up trap vector */
|
||||
GBL.kbchar = 0; /* initialize the "global" variables */
|
||||
GBL.insptr = GBL.remptr = &(GBL.t_buff[0]);
|
||||
GBL.delim = '$';
|
||||
GBL.lstecho = FALSE;
|
||||
GBL.echodel = TRUE;
|
||||
GBL.chainp = NULL;
|
||||
_bdos(13); /* reset disk system function */
|
||||
segp = bgetseg(); /* get pointer to memory segment table */
|
||||
tpa_lt = tpa_lp = segp->low;
|
||||
tpa_ht = tpa_hp = tpa_lp + segp->length;
|
||||
initexc( &(GBL.excvec[0]) );
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* warmboot entry point *
|
||||
************************/
|
||||
|
||||
warmboot(parm)
|
||||
/* Warm Boot the system */
|
||||
WORD parm; /* 1 to reset submit flag */
|
||||
{
|
||||
BSETUP
|
||||
|
||||
log_dsk &= ~ro_dsk; /* log off any disk marked read-only */
|
||||
/* note that this code is specifically for a single-
|
||||
thread system. It won't work in a multi-task sys */
|
||||
ro_dsk = 0;
|
||||
crit_dsk = 0;
|
||||
if (parm)
|
||||
submit = morecmds = FALSE;
|
||||
GBL.curdsk = 0xff; /* set current disk to "unknown" */
|
||||
tpa_lt = tpa_lp;
|
||||
tpa_ht = tpa_hp;
|
||||
initexc( &(GBL.excvec[0]) );
|
||||
bwboot();
|
||||
}
|
||||
|
||||
|
||||
/*************************/
|
||||
/* disk error handlers */
|
||||
/*************************/
|
||||
|
||||
prt_err(p)
|
||||
/* print the error message */
|
||||
|
||||
BYTE *p;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
prt_line(p);
|
||||
prt_line(" error on drive $");
|
||||
conout(GBL.curdsk + 'A');
|
||||
}
|
||||
|
||||
|
||||
abrt_err(p)
|
||||
/* print the error message and always abort */
|
||||
|
||||
BYTE *p;
|
||||
{
|
||||
prt_err(p);
|
||||
warmboot(1);
|
||||
}
|
||||
|
||||
|
||||
ext_err(cont,p)
|
||||
/* print the error message, and allow for retry, abort, or ignore */
|
||||
|
||||
REG BOOLEAN cont; /* Boolean for whether continuing is allowed */
|
||||
BYTE *p; /* pointer to error message */
|
||||
{
|
||||
REG UBYTE ch;
|
||||
|
||||
prt_err(p);
|
||||
do
|
||||
{
|
||||
prt_line("\n\rDo you want to: Abort (A), Retry (R)$");
|
||||
if (cont) prt_line(", or Continue with bad data (C)$");
|
||||
prt_line("? $");
|
||||
ch = conin() & 0x5f;
|
||||
prt_line("\r\n$");
|
||||
|
||||
switch ( ch )
|
||||
{
|
||||
case ctrlc: warmboot(1);
|
||||
case 'A': warmboot(1);
|
||||
case 'C': if (cont) return(1);
|
||||
break;
|
||||
case 'R': return(0);
|
||||
}
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
|
||||
/********************************/
|
||||
/* Read-only File Error Routine */
|
||||
/********************************/
|
||||
|
||||
ro_err(fcbp,dirindx)
|
||||
/* File R/O error */
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
WORD dirindx;
|
||||
{
|
||||
REG BYTE *p;
|
||||
REG UWORD i;
|
||||
REG UBYTE ch;
|
||||
|
||||
p = (BYTE *)fcbp;
|
||||
prt_line("CP/M Disk file error: $");
|
||||
i = 8;
|
||||
do conout(*++p & 0x7f); while (--i);
|
||||
conout('.');
|
||||
i = 3;
|
||||
do conout(*++p & 0x7f); while (--i);
|
||||
prt_line(" is read-only.$");
|
||||
do
|
||||
{
|
||||
prt_line("\r\nDo you want to: Change it to read/write (C), or Abort (A)? $");
|
||||
ch = conin() & 0x5f;
|
||||
prt_line("\r\n$");
|
||||
|
||||
switch ( ch )
|
||||
{
|
||||
case ctrlc: warmboot(1);
|
||||
case 'A': warmboot(1);
|
||||
case 'C': fcbp->ftype[robit] &= 0x7f;
|
||||
dirscan(set_attr, fcbp, 2);
|
||||
return(dir_rd(dirindx >> 2));
|
||||
} /* Reset the directory buffer !!!! */
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* error entry point *
|
||||
************************/
|
||||
|
||||
error(errnum)
|
||||
/* Print error message, do appropriate response */
|
||||
|
||||
UWORD errnum; /* error number */
|
||||
{
|
||||
BSETUP
|
||||
|
||||
prt_line("\r\nCP/M Disk $");
|
||||
switch (errnum)
|
||||
{
|
||||
case 0: return( ext_err(TRUE,"read$") );
|
||||
/* break; */
|
||||
|
||||
case 1: return( ext_err(TRUE,"write$") );
|
||||
/* break; */
|
||||
|
||||
case 2: abrt_err("select$");
|
||||
/* break; */
|
||||
|
||||
case 3: return( ext_err(FALSE,"select$") );
|
||||
/* break; */
|
||||
|
||||
case 4: abrt_err("change$");
|
||||
/* break; */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
* set exception entry point *
|
||||
*****************************/
|
||||
|
||||
setexc(epbp)
|
||||
/* Set Exception Vector */
|
||||
REG struct
|
||||
{
|
||||
WORD vecnum;
|
||||
BYTE *newvec;
|
||||
BYTE *oldvec;
|
||||
} *epbp;
|
||||
|
||||
{
|
||||
REG WORD i;
|
||||
BSETUP
|
||||
|
||||
i = epbp->vecnum-2;
|
||||
if ( i==32 || i==33) return(-1);
|
||||
if ( (30 <= i) && (i <= 37) ) i -= 20;
|
||||
else if ( (i < 0) || (i > 9) ) return(255);
|
||||
epbp->oldvec = GBL.excvec[i];
|
||||
GBL.excvec[i] = epbp->newvec;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
* get/set TPA entry point *
|
||||
*****************************/
|
||||
|
||||
set_tpa(p)
|
||||
/* Get/Set TPA Limits */
|
||||
REG struct
|
||||
{
|
||||
UWORD parms;
|
||||
BYTE *low;
|
||||
BYTE *high;
|
||||
} *p;
|
||||
|
||||
#define set 1
|
||||
#define sticky 2
|
||||
|
||||
{
|
||||
if (p->parms & set)
|
||||
{
|
||||
tpa_lt = p->low;
|
||||
tpa_ht = p->high;
|
||||
if (p->parms & sticky)
|
||||
{
|
||||
tpa_lp = tpa_lt;
|
||||
tpa_hp = tpa_ht;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->low = tpa_lt;
|
||||
p->high = tpa_ht;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
1File: BDOSMISC.C Page 1
|
||||
1
|
||||
2 /****************************************************************
|
||||
3 * *
|
||||
4 * CP/M-68K BDOS Miscellaneous Module *
|
||||
5 * *
|
||||
6 * This module contains miscellaneous loose ends for *
|
||||
7 * CP/M-68K. Included are: *
|
||||
8 * *
|
||||
9 * bdosinit() - BDOS initialization routine *
|
||||
10 * called from CCP for system init *
|
||||
11 * warmboot() - BDOS warm boot exit routine *
|
||||
12 * error() - BDOS error printing routine *
|
||||
13 * ro_err() - BDOS read-only file error routine *
|
||||
14 * setexc() - BDOS set exception vector *
|
||||
15 * set_tpa() - BDOS get/set TPA limits *
|
||||
16 * serial # and copyright notice, machine readable *
|
||||
17 * *
|
||||
18 * *
|
||||
19 * Configured for Alcyon C on the VAX *
|
||||
20 * *
|
||||
21 ****************************************************************/
|
||||
22
|
||||
23 #include "bdosinc.h" /* Standard I/O declarations */
|
||||
24
|
||||
25 #include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
26
|
||||
27 #include "biosdef.h" /* BIOS definitions, needed for bios wboot */
|
||||
28
|
||||
29
|
||||
30 /* serial # and copyright notice */
|
||||
31
|
||||
32 char *copyrt="CP/M-68K(tm), Version 1.1, Copyright (c) 1983, Digital Research";
|
||||
33 char *serial="XXXX-0000-654321";
|
||||
34
|
||||
35
|
||||
36
|
||||
37 /* Declare external functions */
|
||||
38 EXTERN conout(); /* Console Output function */
|
||||
39 EXTERN UBYTE conin(); /* Console Input function */
|
||||
40 EXTERN prt_line(); /* Print String function */
|
||||
41 EXTERN UWORD _bdos(); /* BDOS main routine */
|
||||
42 EXTERN UBYTE *traphndl(); /* assembly language trap handler */
|
||||
43 EXTERN initexc(); /* init the exception handler in */
|
||||
44 /* exceptn.s */
|
||||
45 EXTERN UWORD dirscan(); /* Directory scanning routine */
|
||||
46 EXTERN BOOLEAN set_attr(); /* Set File attributes function */
|
||||
47 EXTERN UWORD dir_rd(); /* Read directory sector routine */
|
||||
48
|
||||
49 /* Declare external variables */
|
||||
50 EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
51 EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
52 EXTERN UWORD crit_dsk; /* vector of critical disks */
|
||||
53 EXTERN BYTE *tpa_lt; /* TPA lower limit (temporary) */
|
||||
54 EXTERN BYTE *tpa_lp; /* TPA lower limit (permanent) */
|
||||
55 EXTERN BYTE *tpa_ht; /* TPA upper limit (temporary) */
|
||||
56 EXTERN BYTE *tpa_hp; /* TPA upper limit (permanent) */
|
||||
57 EXTERN BOOLEAN submit; /* external variables from CCP */
|
||||
58 EXTERN BOOLEAN morecmds;
|
||||
59
|
||||
1File: BDOSMISC.C Page 2
|
||||
60
|
||||
61 #define trap2v 34 /* trap 2 vector number */
|
||||
62 #define ctrlc 3 /* control-c */
|
||||
63
|
||||
64
|
||||
65 /********************************
|
||||
66 * bdos initialization routine *
|
||||
67 ********************************/
|
||||
68
|
||||
69 bdosinit()
|
||||
70 /* Initialize the File System */
|
||||
71 {
|
||||
72 REG struct
|
||||
73 {
|
||||
74 WORD nmbr;
|
||||
75 BYTE *low;
|
||||
76 LONG length;
|
||||
77 } *segp;
|
||||
78 BSETUP
|
||||
79
|
||||
80 bsetvec(trap2v, &traphndl); /* set up trap vector */
|
||||
81 GBL.kbchar = 0; /* initialize the "global" variables */
|
||||
82 GBL.insptr = GBL.remptr = &(GBL.t_buff[0]);
|
||||
83 GBL.delim = '$';
|
||||
84 GBL.lstecho = FALSE;
|
||||
85 GBL.echodel = TRUE;
|
||||
86 GBL.chainp = NULL;
|
||||
87 _bdos(13); /* reset disk system function */
|
||||
88 segp = bgetseg(); /* get pointer to memory segment table */
|
||||
89 tpa_lt = tpa_lp = segp->low;
|
||||
90 tpa_ht = tpa_hp = tpa_lp + segp->length;
|
||||
91 initexc( &(GBL.excvec[0]) );
|
||||
92 }
|
||||
93
|
||||
94
|
||||
95 /************************
|
||||
96 * warmboot entry point *
|
||||
97 ************************/
|
||||
98
|
||||
99 warmboot(parm)
|
||||
100 /* Warm Boot the system */
|
||||
101 WORD parm; /* 1 to reset submit flag */
|
||||
102 {
|
||||
103 BSETUP
|
||||
104
|
||||
105 log_dsk &= ~ro_dsk; /* log off any disk marked read-only */
|
||||
106 /* note that this code is specifically for a single-
|
||||
107 thread system. It won't work in a multi-task sys */
|
||||
108 ro_dsk = 0;
|
||||
109 crit_dsk = 0;
|
||||
110 if (parm)
|
||||
111 submit = morecmds = FALSE;
|
||||
112 GBL.curdsk = 0xff; /* set current disk to "unknown" */
|
||||
113 tpa_lt = tpa_lp;
|
||||
114 tpa_ht = tpa_hp;
|
||||
115 initexc( &(GBL.excvec[0]) );
|
||||
116 bwboot();
|
||||
117 }
|
||||
118
|
||||
1File: BDOSMISC.C Page 3
|
||||
119
|
||||
120 /*************************/
|
||||
121 /* disk error handlers */
|
||||
122 /*************************/
|
||||
123
|
||||
124 prt_err(p)
|
||||
125 /* print the error message */
|
||||
126
|
||||
127 BYTE *p;
|
||||
128 {
|
||||
129 BSETUP
|
||||
130
|
||||
131 prt_line(p);
|
||||
132 prt_line(" error on drive $");
|
||||
133 conout(GBL.curdsk + 'A');
|
||||
134 }
|
||||
135
|
||||
136
|
||||
137 abrt_err(p)
|
||||
138 /* print the error message and always abort */
|
||||
139
|
||||
140 BYTE *p;
|
||||
141 {
|
||||
142 prt_err(p);
|
||||
143 warmboot(1);
|
||||
144 }
|
||||
145
|
||||
146
|
||||
147 ext_err(cont,p)
|
||||
148 /* print the error message, and allow for retry, abort, or ignore */
|
||||
149
|
||||
150 REG BOOLEAN cont; /* Boolean for whether continuing is allowed */
|
||||
151 BYTE *p; /* pointer to error message */
|
||||
152 {
|
||||
153 REG UBYTE ch;
|
||||
154
|
||||
155 prt_err(p);
|
||||
156 do
|
||||
157 {
|
||||
158 prt_line("\n\rDo you want to: Abort (A), Retry (R)$");
|
||||
159 if (cont) prt_line(", or Continue with bad data (C)$");
|
||||
160 prt_line("? $");
|
||||
161 ch = conin() & 0x5f;
|
||||
162 prt_line("\r\n$");
|
||||
163
|
||||
164 switch ( ch )
|
||||
165 {
|
||||
166 case ctrlc: warmboot(1);
|
||||
167 case 'A': warmboot(1);
|
||||
168 case 'C': if (cont) return(1);
|
||||
169 break;
|
||||
170 case 'R': return(0);
|
||||
171 }
|
||||
172 } while (TRUE);
|
||||
173 }
|
||||
174
|
||||
175
|
||||
176 /********************************/
|
||||
177 /* Read-only File Error Routine */
|
||||
1File: BDOSMISC.C Page 4
|
||||
178 /********************************/
|
||||
179
|
||||
180 ro_err(fcbp,dirindx)
|
||||
181 /* File R/O error */
|
||||
182
|
||||
183 REG struct fcb *fcbp;
|
||||
184 WORD dirindx;
|
||||
185 {
|
||||
186 REG BYTE *p;
|
||||
187 REG UWORD i;
|
||||
188 REG UBYTE ch;
|
||||
189
|
||||
190 p = (BYTE *)fcbp;
|
||||
191 prt_line("CP/M Disk file error: $");
|
||||
192 i = 8;
|
||||
193 do conout(*++p & 0x7f); while (--i);
|
||||
194 conout('.');
|
||||
195 i = 3;
|
||||
196 do conout(*++p & 0x7f); while (--i);
|
||||
197 prt_line(" is read-only.$");
|
||||
198 do
|
||||
199 {
|
||||
200 prt_line("\r\nDo you want to: Change it to read/write (C), or Abort (A)? $");
|
||||
201 ch = conin() & 0x5f;
|
||||
202 prt_line("\r\n$");
|
||||
203
|
||||
204 switch ( ch )
|
||||
205 {
|
||||
206 case ctrlc: warmboot(1);
|
||||
207 case 'A': warmboot(1);
|
||||
208 case 'C': fcbp->ftype[robit] &= 0x7f;
|
||||
209 dirscan(set_attr, fcbp, 2);
|
||||
210 return(dir_rd(dirindx >> 2));
|
||||
211 } /* Reset the directory buffer !!!! */
|
||||
212 } while (TRUE);
|
||||
213 }
|
||||
214
|
||||
215
|
||||
216 /************************
|
||||
217 * error entry point *
|
||||
218 ************************/
|
||||
219
|
||||
220 error(errnum)
|
||||
221 /* Print error message, do appropriate response */
|
||||
222
|
||||
223 UWORD errnum; /* error number */
|
||||
224 {
|
||||
225 BSETUP
|
||||
226
|
||||
227 prt_line("\r\nCP/M Disk $");
|
||||
228 switch (errnum)
|
||||
229 {
|
||||
230 case 0: return( ext_err(TRUE,"read$") );
|
||||
231 /* break; */
|
||||
232
|
||||
233 case 1: return( ext_err(TRUE,"write$") );
|
||||
234 /* break; */
|
||||
235
|
||||
236 case 2: abrt_err("select$");
|
||||
1File: BDOSMISC.C Page 5
|
||||
237 /* break; */
|
||||
238
|
||||
239 case 3: return( ext_err(FALSE,"select$") );
|
||||
240 /* break; */
|
||||
241
|
||||
242 case 4: abrt_err("change$");
|
||||
243 /* break; */
|
||||
244
|
||||
245 }
|
||||
246 }
|
||||
247
|
||||
248
|
||||
249 /*****************************
|
||||
250 * set exception entry point *
|
||||
251 *****************************/
|
||||
252
|
||||
253 setexc(epbp)
|
||||
254 /* Set Exception Vector */
|
||||
255 REG struct
|
||||
256 {
|
||||
257 WORD vecnum;
|
||||
258 BYTE *newvec;
|
||||
259 BYTE *oldvec;
|
||||
260 } *epbp;
|
||||
261
|
||||
262 {
|
||||
263 REG WORD i;
|
||||
264 BSETUP
|
||||
265
|
||||
266 i = epbp->vecnum-2;
|
||||
267 if ( i==32 || i==33) return(-1);
|
||||
268 if ( (30 <= i) && (i <= 37) ) i -= 20;
|
||||
269 else if ( (i < 0) || (i > 9) ) return(255);
|
||||
270 epbp->oldvec = GBL.excvec[i];
|
||||
271 GBL.excvec[i] = epbp->newvec;
|
||||
272 return(0);
|
||||
273 }
|
||||
274
|
||||
275
|
||||
276 /*****************************
|
||||
277 * get/set TPA entry point *
|
||||
278 *****************************/
|
||||
279
|
||||
280 set_tpa(p)
|
||||
281 /* Get/Set TPA Limits */
|
||||
282 REG struct
|
||||
283 {
|
||||
284 UWORD parms;
|
||||
285 BYTE *low;
|
||||
286 BYTE *high;
|
||||
287 } *p;
|
||||
288
|
||||
289 #define set 1
|
||||
290 #define sticky 2
|
||||
291
|
||||
292 {
|
||||
293 if (p->parms & set)
|
||||
294 {
|
||||
295 tpa_lt = p->low;
|
||||
1File: BDOSMISC.C Page 6
|
||||
296 tpa_ht = p->high;
|
||||
297 if (p->parms & sticky)
|
||||
298 {
|
||||
299 tpa_lp = tpa_lt;
|
||||
300 tpa_hp = tpa_ht;
|
||||
301 }
|
||||
302 }
|
||||
303 else
|
||||
304 {
|
||||
305 p->low = tpa_lt;
|
||||
306 p->high = tpa_ht;
|
||||
307 }
|
||||
308 }
|
||||
314
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosrw.c
Normal file
314
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosrw.c
Normal file
@@ -0,0 +1,314 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-68K BDOS Disk Read/Write Module *
|
||||
* *
|
||||
* This module contains functions to perform sequential *
|
||||
* or random access read or write to the disk for CP/M-68K *
|
||||
* *
|
||||
* It includes the following external functions: *
|
||||
* *
|
||||
* bdosrw() - sequential and random disk I/O *
|
||||
* *
|
||||
* *
|
||||
* Compiled with Alcyon C on the VAX *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "bdosinc.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
|
||||
/* External function definitions */
|
||||
EXTERN UWORD rdwrt(); /* disk read/write routine */
|
||||
EXTERN WORD getaloc(); /* allocate a block of disk space */
|
||||
EXTERN WORD swap(); /* assembly language byte swapper */
|
||||
EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
EXTERN BOOLEAN openfile(); /* open file function passed to dirscan */
|
||||
EXTERN UWORD close_fi(); /* close file function */
|
||||
EXTERN BOOLEAN create(); /* create file function passed to dirscan */
|
||||
EXTERN UWORD ro_err(); /* read-only file error handler */
|
||||
|
||||
/* External variable definitions */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
/* First, some utility functions used by seqio and ranio */
|
||||
/**********************************************************/
|
||||
|
||||
/******************************
|
||||
* FCB block number routines *
|
||||
******************************/
|
||||
|
||||
WORD blkindx(fcbp)
|
||||
/* return index into fcb disk map */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
{
|
||||
REG struct dpb *dparmp; /* pointer to disk parameter block */
|
||||
REG WORD i;
|
||||
REG WORD blkshf;
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp;
|
||||
blkshf = dparmp->bsh;
|
||||
i = ((fcbp->extent) & dparmp->exm) << (7 - blkshf);
|
||||
return (i + (UBWORD(fcbp->cur_rec) >> blkshf) );
|
||||
}
|
||||
|
||||
|
||||
UWORD blknum(fcbp, index, wrdfcb)
|
||||
/* return block number in fcb indicated by index */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
WORD wrdfcb; /* boolean, fcb disk map of words */
|
||||
{
|
||||
if (wrdfcb)
|
||||
return( swap(fcbp->dskmap.big[index]) );
|
||||
else return( UBWORD(fcbp->dskmap.small[index]) );
|
||||
}
|
||||
|
||||
|
||||
setblk(fcbp, index, wrdfcb, block)
|
||||
/* put block number into fcb */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
WORD wrdfcb; /* boolean, fcb disk map of words */
|
||||
REG UWORD block; /* block number */
|
||||
{
|
||||
fcbp->s2 &= 0x7f; /* set file write flag */
|
||||
if (wrdfcb)
|
||||
fcbp->dskmap.big[index] = swap(block);
|
||||
else fcbp->dskmap.small[index] = (UBYTE)block;
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
* disk read/write routine *
|
||||
***************************/
|
||||
|
||||
UWORD do_io(block, rcrd, parm)
|
||||
|
||||
UWORD block; /* block number */
|
||||
UBYTE rcrd; /* record number */
|
||||
REG WORD parm; /* write parameter */
|
||||
{
|
||||
REG LONG lsec;
|
||||
REG struct dpb *dparmp;
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp; /* init dpb pointer */
|
||||
lsec = ((LONG)block << (dparmp->bsh)) +
|
||||
(LONG)(rcrd & (dparmp->blm));
|
||||
return( rdwrt(lsec, GBL.dmaadr, parm) );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************
|
||||
* routine for crossing extent boundaries *
|
||||
*******************************************/
|
||||
|
||||
WORD new_ext(fcbp, reading, ran)
|
||||
/* If sequential I/O, open the next extent */
|
||||
/* If random I/O, compute new extent from random record field */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
BOOLEAN reading; /* read/write flag */
|
||||
WORD ran; /* random I/O flag */
|
||||
{
|
||||
REG UBYTE mod; /* module number */
|
||||
REG UBYTE ext; /* extent number */
|
||||
REG UBYTE t_mod; /* temp mod number */
|
||||
REG UBYTE t_ext; /* temp extent */
|
||||
BSETUP
|
||||
|
||||
if (ran)
|
||||
{
|
||||
mod = ( (fcbp->ran0) << 4) | ( (fcbp->ran1) >> 4);
|
||||
ext = ( ((fcbp->ran1) & 0x0f) << 1);
|
||||
if ((fcbp->ran2) & 0x80) ext |= 1;
|
||||
/* the calculation of ext was coded this way because of a */
|
||||
/* compiler bug from Alcyon */
|
||||
}
|
||||
else
|
||||
{
|
||||
mod = (fcbp->s2) & 0x3f;
|
||||
ext = (fcbp->extent) + 1; /* for sequential, incr extent */
|
||||
}
|
||||
if (ext >= 32)
|
||||
{
|
||||
ext = 0;
|
||||
mod += 1;
|
||||
}
|
||||
if (mod >= 64) return(6); /* past maximum file size */
|
||||
if ( mod == ((fcbp->s2) & 0x3f) )
|
||||
if ( ! ((ext ^ (fcbp->extent)) & ~((GBL.parmp)->exm) & 0x1f) )
|
||||
{ /* we're in same logical extent */
|
||||
fcbp->extent = ext;
|
||||
return(0);
|
||||
}
|
||||
/* Extent or Module numbers don't match */
|
||||
/* Close the old extent and open a one */
|
||||
if ( close_fi(fcbp) >= 255 ) return(3);
|
||||
/* can't close old extent */
|
||||
t_mod = fcbp->s2;
|
||||
t_ext = fcbp->extent;
|
||||
fcbp->s2 = mod;
|
||||
fcbp->extent = ext;
|
||||
if ( dirscan(openfile, fcbp, 0) >= 255 ) /* open extent */
|
||||
{
|
||||
if (reading)
|
||||
{ /* reading unwritten extent */
|
||||
fcbp->s2 = t_mod;
|
||||
fcbp->extent = t_ext;
|
||||
return(4);
|
||||
}
|
||||
if ( dirscan(create, fcbp, 8) >= 255 )
|
||||
return(5); /* can't create new extent */
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/************************************
|
||||
* Routine to calculate the maximum *
|
||||
* extent number of an FCB in a *
|
||||
* extent-folded environment *
|
||||
************************************/
|
||||
|
||||
UWORD calcext(fcbp)
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
REG UWORD i;
|
||||
REG BYTE *p;
|
||||
BSETUP
|
||||
|
||||
i = 15;
|
||||
p = &(fcbp->dskmap.small[16]);
|
||||
do
|
||||
{
|
||||
if (*--p) break;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
/* Now i contains the index of the last non-zero block in the FCB */
|
||||
if ((GBL.parmp)->dsm > 255) i >>= 1;
|
||||
i >>= 7 - ((GBL.parmp)->bsh);
|
||||
return ( (fcbp->extent) & ~((GBL.parmp)->exm) & 0x1f | i );
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
* Routine to get the actual *
|
||||
* record count of the currently *
|
||||
* active logical extent of a FCB *
|
||||
*********************************/
|
||||
|
||||
UWORD get_rc(fcbp)
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
REG UWORD ext;
|
||||
|
||||
ext = calcext(fcbp); /* find last active extent in fcb */
|
||||
if (ext == fcbp->extent) return(UBWORD(fcbp->rcdcnt));
|
||||
/* if this is the last active fcb, return fcb's rc */
|
||||
else if (ext > fcbp->extent) return(128);
|
||||
/* if the fcb has more extents past this one, then */
|
||||
/* the current one is logically full */
|
||||
else return (0);
|
||||
/* if we seeked past the last active extent, rc = 0 */
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* bdosrw entry point *
|
||||
************************/
|
||||
|
||||
UWORD bdosrw(fcbp, reading, random)
|
||||
|
||||
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
|
||||
REG BOOLEAN reading; /* boolean to tell whether to read or write */
|
||||
WORD random; /* 0 = sequential, 1 = random (normal), */
|
||||
/* 2 = random with zero fill */
|
||||
{
|
||||
REG UWORD block; /* block number from fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
REG BYTE *old_dma; /* temp holding spot for dmaadr */
|
||||
REG WORD parm; /* parameter to do-io */
|
||||
REG WORD bigfile; /* file system is in word mode */
|
||||
REG UWORD rtn; /* return parameter */
|
||||
REG UBYTE rc; /* temp storage for rcdcnt */
|
||||
BSETUP
|
||||
|
||||
bigfile = ((GBL.parmp)->dsm) & ~0xff;
|
||||
if ( ( ! reading) && (fcbp->ftype[robit] & 0x80) )
|
||||
ro_err(fcbp,((GBL.dpbp)->dpbp)->drm);
|
||||
/* check for read-only file */
|
||||
if (random)
|
||||
{
|
||||
if ( rtn = new_ext(fcbp, reading, TRUE) ) return(rtn);
|
||||
/* open new extent if necessary, return if error */
|
||||
fcbp->cur_rec = (fcbp->ran2) & 0x7f;
|
||||
}
|
||||
else /* sequential */
|
||||
if (fcbp->cur_rec == 128)
|
||||
{ /* time to try next extent */
|
||||
if ( new_ext(fcbp, reading, FALSE) )
|
||||
return(1); /* if can't open new extent, error */
|
||||
fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */
|
||||
}
|
||||
|
||||
/* record is now in active fcb */
|
||||
rc = fcbp->rcdcnt;
|
||||
if ( UBWORD(fcbp->cur_rec) >= get_rc(fcbp) )
|
||||
{
|
||||
if (reading) return(1); /* reading unwritten data */
|
||||
fcbp->s2 &= 0x7f; /* set file write flag */
|
||||
rc = fcbp->cur_rec + 1;
|
||||
}
|
||||
index = blkindx(fcbp); /* get index into fcb disk map */
|
||||
block = blknum(fcbp, index, bigfile);
|
||||
if (block) parm = (reading ? 0 : 1);
|
||||
else /* if allocated block, parm is just read or write */
|
||||
{ /* unallocated block */
|
||||
if (reading) return(1); /* reading unwritten data */
|
||||
|
||||
/* Writing to new block */
|
||||
/* The parm passed to getaloc is the previously allocated block */
|
||||
/* or 0, if the previous block is not allocated */
|
||||
|
||||
block = getaloc(blknum(fcbp, (index ? (index - 1) : 0), bigfile));
|
||||
if (block == ~0) return(2); /* out of space */
|
||||
setblk(fcbp, index, bigfile, block);
|
||||
parm = 3;
|
||||
if (random == 2)
|
||||
{ /* Write random with zero fill */
|
||||
old_dma = GBL.dmaadr;
|
||||
GBL.dmaadr = GBL.dirbufp; /* Do DMA from dir_buf */
|
||||
index = SECLEN;
|
||||
do GBL.dmaadr[--index] = 0;
|
||||
while (index); /* zero the dma buffer */
|
||||
for (index = 0; index <= ((GBL.parmp)->blm); index++)
|
||||
{
|
||||
do_io(block, (UBYTE)index, parm);
|
||||
/* write zeros to the block */
|
||||
parm = 1; /* next write is not to new block */
|
||||
}
|
||||
GBL.dmaadr = old_dma; /* restore dma address */
|
||||
}
|
||||
}
|
||||
rtn = do_io(block, fcbp->cur_rec, parm);
|
||||
if ( rtn == 0 )
|
||||
{
|
||||
fcbp->rcdcnt = rc;
|
||||
if ( ! random ) fcbp->cur_rec += 1;
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
320
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosrw.lis
Normal file
320
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/bdosrw.lis
Normal file
@@ -0,0 +1,320 @@
|
||||
1File: BDOSRW.C Page 1
|
||||
1
|
||||
2 /****************************************************************
|
||||
3 * *
|
||||
4 * CP/M-68K BDOS Disk Read/Write Module *
|
||||
5 * *
|
||||
6 * This module contains functions to perform sequential *
|
||||
7 * or random access read or write to the disk for CP/M-68K *
|
||||
8 * *
|
||||
9 * It includes the following external functions: *
|
||||
10 * *
|
||||
11 * bdosrw() - sequential and random disk I/O *
|
||||
12 * *
|
||||
13 * *
|
||||
14 * Compiled with Alcyon C on the VAX *
|
||||
15 * *
|
||||
16 ****************************************************************/
|
||||
17
|
||||
18 #include "bdosinc.h" /* Standard I/O declarations */
|
||||
19
|
||||
20 #include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
21
|
||||
22
|
||||
23 /* External function definitions */
|
||||
24 EXTERN UWORD rdwrt(); /* disk read/write routine */
|
||||
25 EXTERN WORD getaloc(); /* allocate a block of disk space */
|
||||
26 EXTERN WORD swap(); /* assembly language byte swapper */
|
||||
27 EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
28 EXTERN BOOLEAN openfile(); /* open file function passed to dirscan */
|
||||
29 EXTERN UWORD close_fi(); /* close file function */
|
||||
30 EXTERN BOOLEAN create(); /* create file function passed to dirscan */
|
||||
31 EXTERN UWORD ro_err(); /* read-only file error handler */
|
||||
32
|
||||
33 /* External variable definitions */
|
||||
34 EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
35
|
||||
36
|
||||
37 /**********************************************************/
|
||||
38 /* First, some utility functions used by seqio and ranio */
|
||||
39 /**********************************************************/
|
||||
40
|
||||
41 /******************************
|
||||
42 * FCB block number routines *
|
||||
43 ******************************/
|
||||
44
|
||||
45 WORD blkindx(fcbp)
|
||||
46 /* return index into fcb disk map */
|
||||
47
|
||||
48 REG struct fcb *fcbp; /* pointer to fcb */
|
||||
49 {
|
||||
50 REG struct dpb *dparmp; /* pointer to disk parameter block */
|
||||
51 REG WORD i;
|
||||
52 REG WORD blkshf;
|
||||
53 BSETUP
|
||||
54
|
||||
55 dparmp = GBL.parmp;
|
||||
56 blkshf = dparmp->bsh;
|
||||
57 i = ((fcbp->extent) & dparmp->exm) << (7 - blkshf);
|
||||
58 return (i + (UBWORD(fcbp->cur_rec) >> blkshf) );
|
||||
59 }
|
||||
1File: BDOSRW.C Page 2
|
||||
60
|
||||
61
|
||||
62 UWORD blknum(fcbp, index, wrdfcb)
|
||||
63 /* return block number in fcb indicated by index */
|
||||
64
|
||||
65 REG struct fcb *fcbp; /* pointer to fcb */
|
||||
66 REG WORD index; /* index into disk map of fcb */
|
||||
67 WORD wrdfcb; /* boolean, fcb disk map of words */
|
||||
68 {
|
||||
69 if (wrdfcb)
|
||||
70 return( swap(fcbp->dskmap.big[index]) );
|
||||
71 else return( UBWORD(fcbp->dskmap.small[index]) );
|
||||
72 }
|
||||
73
|
||||
74
|
||||
75 setblk(fcbp, index, wrdfcb, block)
|
||||
76 /* put block number into fcb */
|
||||
77
|
||||
78 REG struct fcb *fcbp; /* pointer to fcb */
|
||||
79 REG WORD index; /* index into disk map of fcb */
|
||||
80 WORD wrdfcb; /* boolean, fcb disk map of words */
|
||||
81 REG UWORD block; /* block number */
|
||||
82 {
|
||||
83 fcbp->s2 &= 0x7f; /* set file write flag */
|
||||
84 if (wrdfcb)
|
||||
85 fcbp->dskmap.big[index] = swap(block);
|
||||
86 else fcbp->dskmap.small[index] = (UBYTE)block;
|
||||
87 }
|
||||
88
|
||||
89
|
||||
90 /***************************
|
||||
91 * disk read/write routine *
|
||||
92 ***************************/
|
||||
93
|
||||
94 UWORD do_io(block, rcrd, parm)
|
||||
95
|
||||
96 UWORD block; /* block number */
|
||||
97 UBYTE rcrd; /* record number */
|
||||
98 REG WORD parm; /* write parameter */
|
||||
99 {
|
||||
100 REG LONG lsec;
|
||||
101 REG struct dpb *dparmp;
|
||||
102 BSETUP
|
||||
103
|
||||
104 dparmp = GBL.parmp; /* init dpb pointer */
|
||||
105 lsec = ((LONG)block << (dparmp->bsh)) +
|
||||
106 (LONG)(rcrd & (dparmp->blm));
|
||||
107 return( rdwrt(lsec, GBL.dmaadr, parm) );
|
||||
108 }
|
||||
109
|
||||
110
|
||||
111 /*******************************************
|
||||
112 * routine for crossing extent boundaries *
|
||||
113 *******************************************/
|
||||
114
|
||||
115 WORD new_ext(fcbp, reading, ran)
|
||||
116 /* If sequential I/O, open the next extent */
|
||||
117 /* If random I/O, compute new extent from random record field */
|
||||
118
|
||||
1File: BDOSRW.C Page 3
|
||||
119 REG struct fcb *fcbp; /* pointer to fcb */
|
||||
120 BOOLEAN reading; /* read/write flag */
|
||||
121 WORD ran; /* random I/O flag */
|
||||
122 {
|
||||
123 REG UBYTE mod; /* module number */
|
||||
124 REG UBYTE ext; /* extent number */
|
||||
125 REG UBYTE t_mod; /* temp mod number */
|
||||
126 REG UBYTE t_ext; /* temp extent */
|
||||
127 BSETUP
|
||||
128
|
||||
129 if (ran)
|
||||
130 {
|
||||
131 mod = ( (fcbp->ran0) << 4) | ( (fcbp->ran1) >> 4);
|
||||
132 ext = ( ((fcbp->ran1) & 0x0f) << 1);
|
||||
133 if ((fcbp->ran2) & 0x80) ext |= 1;
|
||||
134 /* the calculation of ext was coded this way because of a */
|
||||
135 /* compiler bug from Alcyon */
|
||||
136 }
|
||||
137 else
|
||||
138 {
|
||||
139 mod = (fcbp->s2) & 0x3f;
|
||||
140 ext = (fcbp->extent) + 1; /* for sequential, incr extent */
|
||||
141 }
|
||||
142 if (ext >= 32)
|
||||
143 {
|
||||
144 ext = 0;
|
||||
145 mod += 1;
|
||||
146 }
|
||||
147 if (mod >= 64) return(6); /* past maximum file size */
|
||||
148 if ( mod == ((fcbp->s2) & 0x3f) )
|
||||
149 if ( ! ((ext ^ (fcbp->extent)) & ~((GBL.parmp)->exm) & 0x1f) )
|
||||
150 { /* we're in same logical extent */
|
||||
151 fcbp->extent = ext;
|
||||
152 return(0);
|
||||
153 }
|
||||
154 /* Extent or Module numbers don't match */
|
||||
155 /* Close the old extent and open a one */
|
||||
156 if ( close_fi(fcbp) >= 255 ) return(3);
|
||||
157 /* can't close old extent */
|
||||
158 t_mod = fcbp->s2;
|
||||
159 t_ext = fcbp->extent;
|
||||
160 fcbp->s2 = mod;
|
||||
161 fcbp->extent = ext;
|
||||
162 if ( dirscan(openfile, fcbp, 0) >= 255 ) /* open extent */
|
||||
163 {
|
||||
164 if (reading)
|
||||
165 { /* reading unwritten extent */
|
||||
166 fcbp->s2 = t_mod;
|
||||
167 fcbp->extent = t_ext;
|
||||
168 return(4);
|
||||
169 }
|
||||
170 if ( dirscan(create, fcbp, 8) >= 255 )
|
||||
171 return(5); /* can't create new extent */
|
||||
172 }
|
||||
173 return(0);
|
||||
174 }
|
||||
175
|
||||
176
|
||||
177 /************************************
|
||||
1File: BDOSRW.C Page 4
|
||||
178 * Routine to calculate the maximum *
|
||||
179 * extent number of an FCB in a *
|
||||
180 * extent-folded environment *
|
||||
181 ************************************/
|
||||
182
|
||||
183 UWORD calcext(fcbp)
|
||||
184
|
||||
185 REG struct fcb *fcbp;
|
||||
186
|
||||
187 {
|
||||
188 REG UWORD i;
|
||||
189 REG BYTE *p;
|
||||
190 BSETUP
|
||||
191
|
||||
192 i = 15;
|
||||
193 p = &(fcbp->dskmap.small[16]);
|
||||
194 do
|
||||
195 {
|
||||
196 if (*--p) break;
|
||||
197 i -= 1;
|
||||
198 } while (i);
|
||||
199 /* Now i contains the index of the last non-zero block in the FCB */
|
||||
200 if ((GBL.parmp)->dsm > 255) i >>= 1;
|
||||
201 i >>= 7 - ((GBL.parmp)->bsh);
|
||||
202 return ( (fcbp->extent) & ~((GBL.parmp)->exm) & 0x1f | i );
|
||||
203 }
|
||||
204
|
||||
205
|
||||
206 /*********************************
|
||||
207 * Routine to get the actual *
|
||||
208 * record count of the currently *
|
||||
209 * active logical extent of a FCB *
|
||||
210 *********************************/
|
||||
211
|
||||
212 UWORD get_rc(fcbp)
|
||||
213
|
||||
214 REG struct fcb *fcbp;
|
||||
215
|
||||
216 {
|
||||
217 REG UWORD ext;
|
||||
218
|
||||
219 ext = calcext(fcbp); /* find last active extent in fcb */
|
||||
220 if (ext == fcbp->extent) return(UBWORD(fcbp->rcdcnt));
|
||||
221 /* if this is the last active fcb, return fcb's rc */
|
||||
222 else if (ext > fcbp->extent) return(128);
|
||||
223 /* if the fcb has more extents past this one, then */
|
||||
224 /* the current one is logically full */
|
||||
225 else return (0);
|
||||
226 /* if we seeked past the last active extent, rc = 0 */
|
||||
227 }
|
||||
228
|
||||
229
|
||||
230 /************************
|
||||
231 * bdosrw entry point *
|
||||
232 ************************/
|
||||
233
|
||||
234 UWORD bdosrw(fcbp, reading, random)
|
||||
235
|
||||
236 REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
|
||||
1File: BDOSRW.C Page 5
|
||||
237 REG BOOLEAN reading; /* boolean to tell whether to read or write */
|
||||
238 WORD random; /* 0 = sequential, 1 = random (normal), */
|
||||
239 /* 2 = random with zero fill */
|
||||
240 {
|
||||
241 REG UWORD block; /* block number from fcb */
|
||||
242 REG WORD index; /* index into disk map of fcb */
|
||||
243 REG BYTE *old_dma; /* temp holding spot for dmaadr */
|
||||
244 REG WORD parm; /* parameter to do-io */
|
||||
245 REG WORD bigfile; /* file system is in word mode */
|
||||
246 REG UWORD rtn; /* return parameter */
|
||||
247 REG UBYTE rc; /* temp storage for rcdcnt */
|
||||
248 BSETUP
|
||||
249
|
||||
250 bigfile = ((GBL.parmp)->dsm) & ~0xff;
|
||||
251 if ( ( ! reading) && (fcbp->ftype[robit] & 0x80) )
|
||||
252 ro_err(fcbp,((GBL.dpbp)->dpbp)->drm);
|
||||
253 /* check for read-only file */
|
||||
254 if (random)
|
||||
255 {
|
||||
256 if ( rtn = new_ext(fcbp, reading, TRUE) ) return(rtn);
|
||||
257 /* open new extent if necessary, return if error */
|
||||
258 fcbp->cur_rec = (fcbp->ran2) & 0x7f;
|
||||
259 }
|
||||
260 else /* sequential */
|
||||
261 if (fcbp->cur_rec == 128)
|
||||
262 { /* time to try next extent */
|
||||
263 if ( new_ext(fcbp, reading, FALSE) )
|
||||
264 return(1); /* if can't open new extent, error */
|
||||
265 fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */
|
||||
266 }
|
||||
267
|
||||
268 /* record is now in active fcb */
|
||||
269 rc = fcbp->rcdcnt;
|
||||
270 if ( UBWORD(fcbp->cur_rec) >= get_rc(fcbp) )
|
||||
271 {
|
||||
272 if (reading) return(1); /* reading unwritten data */
|
||||
273 fcbp->s2 &= 0x7f; /* set file write flag */
|
||||
274 rc = fcbp->cur_rec + 1;
|
||||
275 }
|
||||
276 index = blkindx(fcbp); /* get index into fcb disk map */
|
||||
277 block = blknum(fcbp, index, bigfile);
|
||||
278 if (block) parm = (reading ? 0 : 1);
|
||||
279 else /* if allocated block, parm is just read or write */
|
||||
280 { /* unallocated block */
|
||||
281 if (reading) return(1); /* reading unwritten data */
|
||||
282
|
||||
283 /* Writing to new block */
|
||||
284 /* The parm passed to getaloc is the previously allocated block */
|
||||
285 /* or 0, if the previous block is not allocated */
|
||||
286
|
||||
287 block = getaloc(blknum(fcbp, (index ? (index - 1) : 0), bigfile));
|
||||
288 if (block == ~0) return(2); /* out of space */
|
||||
289 setblk(fcbp, index, bigfile, block);
|
||||
290 parm = 3;
|
||||
291 if (random == 2)
|
||||
292 { /* Write random with zero fill */
|
||||
293 old_dma = GBL.dmaadr;
|
||||
294 GBL.dmaadr = GBL.dirbufp; /* Do DMA from dir_buf */
|
||||
295 index = SECLEN;
|
||||
1File: BDOSRW.C Page 6
|
||||
296 do GBL.dmaadr[--index] = 0;
|
||||
297 while (index); /* zero the dma buffer */
|
||||
298 for (index = 0; index <= ((GBL.parmp)->blm); index++)
|
||||
299 {
|
||||
300 do_io(block, (UBYTE)index, parm);
|
||||
301 /* write zeros to the block */
|
||||
302 parm = 1; /* next write is not to new block */
|
||||
303 }
|
||||
304 GBL.dmaadr = old_dma; /* restore dma address */
|
||||
305 }
|
||||
306 }
|
||||
307 rtn = do_io(block, fcbp->cur_rec, parm);
|
||||
308 if ( rtn == 0 )
|
||||
309 {
|
||||
310 fcbp->rcdcnt = rc;
|
||||
311 if ( ! random ) fcbp->cur_rec += 1;
|
||||
312 }
|
||||
313 return(rtn);
|
||||
314 }
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
/********************************************************
|
||||
* *
|
||||
* BIOS definitions for CP/M-68K *
|
||||
* *
|
||||
* Copyright (c) 1982 Digital Research, Inc. *
|
||||
* *
|
||||
* This include file simply defines the BIOS calls *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
EXTERN UBYTE bios1(); /* used for character I/O functions */
|
||||
EXTERN bios2(); /* parm1 is word, no return value */
|
||||
EXTERN bios3(); /* used for set dma only */
|
||||
/* parm1 is a pointer, no return */
|
||||
EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */
|
||||
/* words, returns a pointer to dph */
|
||||
EXTERN UWORD bios5(); /* for sectran and set exception */
|
||||
EXTERN BYTE *bios6(); /* for get memory segment table */
|
||||
|
||||
|
||||
#define bwboot() bios1(1) /* warm boot */
|
||||
#define bconstat() bios1(2) /* console status */
|
||||
#define bconin() bios1(3) /* console input */
|
||||
#define bconout(parm) bios2(4,parm) /* console output parm */
|
||||
#define blstout(parm) bios2(5,parm) /* list device output */
|
||||
#define bpun(parm) bios2(6,parm) /* punch char output */
|
||||
#define brdr() bios1(7) /* reader input */
|
||||
#define bhome() bios1(8) /* recalibrate drive */
|
||||
#define bseldsk(parm1,parm2) bios4(9,parm1,parm2)
|
||||
/* select disk and return info */
|
||||
#define bsettrk(parm) bios2(10,parm) /* set track on disk */
|
||||
#define bsetsec(parm) bios2(11,parm) /* set sector for disk */
|
||||
#define bsetdma(parm) bios3(12,parm) /* set dma address */
|
||||
#define bread() bios1(13) /* read sector from disk */
|
||||
#define bwrite(parm) bios2(14,parm) /* write sector to disk */
|
||||
#define blistst() bios1(15) /* list device status */
|
||||
#define bsectrn(parm1,parm2) bios5(16,parm1,parm2)
|
||||
/* sector translate */
|
||||
#define bgetseg() bios6(18) /* get memory segment tbl */
|
||||
#define bgetiob() bios1(19) /* get I/O byte */
|
||||
#define bsetiob(parm) bios2(20,parm) /* set I/O byte */
|
||||
#define bflush() bios1(21) /* flush buffers */
|
||||
#define bsetvec(parm1,parm2) bios5(22,parm1,parm2)
|
||||
/* set exception vector */
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
1File: BIOSDEF.H Page 1
|
||||
1
|
||||
2 /********************************************************
|
||||
3 * *
|
||||
4 * BIOS definitions for CP/M-68K *
|
||||
5 * *
|
||||
6 * Copyright (c) 1982 Digital Research, Inc. *
|
||||
7 * *
|
||||
8 * This include file simply defines the BIOS calls *
|
||||
9 * *
|
||||
10 ********************************************************/
|
||||
11
|
||||
12 EXTERN UBYTE bios1(); /* used for character I/O functions */
|
||||
13 EXTERN bios2(); /* parm1 is word, no return value */
|
||||
14 EXTERN bios3(); /* used for set dma only */
|
||||
15 /* parm1 is a pointer, no return */
|
||||
16 EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */
|
||||
17 /* words, returns a pointer to dph */
|
||||
18 EXTERN UWORD bios5(); /* for sectran and set exception */
|
||||
19 EXTERN BYTE *bios6(); /* for get memory segment table */
|
||||
20
|
||||
21
|
||||
22 #define bwboot() bios1(1) /* warm boot */
|
||||
23 #define bconstat() bios1(2) /* console status */
|
||||
24 #define bconin() bios1(3) /* console input */
|
||||
25 #define bconout(parm) bios2(4,parm) /* console output parm */
|
||||
26 #define blstout(parm) bios2(5,parm) /* list device output */
|
||||
27 #define bpun(parm) bios2(6,parm) /* punch char output */
|
||||
28 #define brdr() bios1(7) /* reader input */
|
||||
29 #define bhome() bios1(8) /* recalibrate drive */
|
||||
30 #define bseldsk(parm1,parm2) bios4(9,parm1,parm2)
|
||||
31 /* select disk and return info */
|
||||
32 #define bsettrk(parm) bios2(10,parm) /* set track on disk */
|
||||
33 #define bsetsec(parm) bios2(11,parm) /* set sector for disk */
|
||||
34 #define bsetdma(parm) bios3(12,parm) /* set dma address */
|
||||
35 #define bread() bios1(13) /* read sector from disk */
|
||||
36 #define bwrite(parm) bios2(14,parm) /* write sector to disk */
|
||||
37 #define blistst() bios1(15) /* list device status */
|
||||
38 #define bsectrn(parm1,parm2) bios5(16,parm1,parm2)
|
||||
39 /* sector translate */
|
||||
40 #define bgetseg() bios6(18) /* get memory segment tbl */
|
||||
41 #define bgetiob() bios1(19) /* get I/O byte */
|
||||
42 #define bsetiob(parm) bios2(20,parm) /* set I/O byte */
|
||||
43 #define bflush() bios1(21) /* flush buffers */
|
||||
44 #define bsetvec(parm1,parm2) bios5(22,parm1,parm2)
|
||||
45 /* set exception vector */
|
||||
46
|
||||
1476
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccp.c
Normal file
1476
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccp.c
Normal file
File diff suppressed because it is too large
Load Diff
1508
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccp.lis
Normal file
1508
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccp.lis
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 1
|
||||
Source File: ccpbdos.s
|
||||
|
||||
1 *************************************************************************
|
||||
2 * *
|
||||
3 * INTERFACE MODULE BETWEEN *
|
||||
4 * CCP and THE BDOS *
|
||||
5 * *
|
||||
6 * *
|
||||
7 * THIS IS THE DUAL PROCESSOR,ROMABLE CP/M-68K SYSTEM *
|
||||
8 * ================================================== *
|
||||
9 * *
|
||||
10 * (C) Copyright Digital Research 1983 all rights reserved *
|
||||
11 * *
|
||||
12 *************************************************************************
|
||||
13
|
||||
14 .globl _bdos
|
||||
15 00000000 302F0004 _bdos: move.w 4(sp),d0
|
||||
16 00000004 222F0006 move.l 6(sp),d1
|
||||
17 00000008 4E42 trap #2
|
||||
18 0000000A 4E75 rts
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 2
|
||||
Source File: ccpbdos.s
|
||||
|
||||
S y m b o l T a b l e
|
||||
|
||||
_bdos 00000000 TEXT
|
||||
@@ -0,0 +1,18 @@
|
||||
*************************************************************************
|
||||
* *
|
||||
* INTERFACE MODULE BETWEEN *
|
||||
* CCP and THE BDOS *
|
||||
* *
|
||||
* *
|
||||
* THIS IS THE DUAL PROCESSOR,ROMABLE CP/M-68K SYSTEM *
|
||||
* ================================================== *
|
||||
* *
|
||||
* (C) Copyright Digital Research 1983 all rights reserved *
|
||||
* *
|
||||
*************************************************************************
|
||||
|
||||
.globl _bdos
|
||||
_bdos: move.w 4(sp),d0
|
||||
move.l 6(sp),d1
|
||||
trap #2
|
||||
rts
|
||||
158
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccpdef.h
Normal file
158
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccpdef.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/*--------------------------------------------------------------*\
|
||||
| ccp_def.c DEFINES v1.0 |
|
||||
| ======= |
|
||||
| |
|
||||
| CP/M 68k: A CP/M derived operating system |
|
||||
| |
|
||||
| File contents: |
|
||||
| ------------- |
|
||||
| This file contains all of the #defines |
|
||||
| used by the console command processor. |
|
||||
| |
|
||||
| created by : Tom Saulpaugh Date: 7/13/82 |
|
||||
| ---------- |
|
||||
| last modified: 10/29/82 |
|
||||
| ------------- |
|
||||
| |
|
||||
| (c) COPYRIGHT Digital Research 1982 |
|
||||
| all rights reserved |
|
||||
| |
|
||||
\*--------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| CP/M Transient Commands |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define DIRCMD 0
|
||||
#define TYPECMD 1
|
||||
#define RENCMD 2
|
||||
#define ERACMD 3
|
||||
#define UCMD 4
|
||||
#define CH_DISK 5
|
||||
#define SUBCMD 6
|
||||
#define SUB_FILE 7
|
||||
#define FILE 8
|
||||
#define DIRSCMD 9
|
||||
#define SEARCH 10
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| Modes and Flags |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define ON 1
|
||||
#define OFF 0
|
||||
#define MATCH 0
|
||||
#define GOOD 1
|
||||
#define BAD 0
|
||||
#define FILL 1
|
||||
#define NOFILL 0
|
||||
#define VOID /*no return value*/
|
||||
#define NO_FILE 98
|
||||
#define STOP 99
|
||||
#define USER_ZERO 0
|
||||
#define DISK_A 1
|
||||
#define SOURCEDRIVE 88
|
||||
#define DESTDRIVE 99
|
||||
#define BYTE char
|
||||
#define REG register
|
||||
#define WORD signed short
|
||||
#define UWORD unsigned int
|
||||
#define LONG signed long
|
||||
#define ULONG unsigned long
|
||||
#define GET_MEM_REG 18
|
||||
#define ZERO 0
|
||||
#define NULL '\0'
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NO_READ 255
|
||||
#define BLANK ' '
|
||||
#define BACKSLH '\\'
|
||||
#define EXLIMPT '!'
|
||||
#define CMASK 0177
|
||||
#define ONE (long)49
|
||||
#define TAB 9
|
||||
#define Cr 13
|
||||
#define Lf 10
|
||||
#define CR (long)13
|
||||
#define LF (long)10
|
||||
#define EOF 26
|
||||
#define BLANKS (long)32
|
||||
#define PERIOD (long)46
|
||||
#define COLON (long)58
|
||||
#define ARROW (long)62
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| Data Structure Size Constants |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define CMD_LEN 128
|
||||
#define BIG_CMD_LEN 255
|
||||
#define MAX_ARGS 4
|
||||
#define ARG_LEN 26
|
||||
#define NO_OF_DRIVES 16
|
||||
#define NUMDELS 16
|
||||
#define FCB_LEN 36
|
||||
#define DMA_LEN 128
|
||||
#define FILES_PER_LINE 5
|
||||
#define SCR_HEIGHT 23
|
||||
#define BIG_WIDTH 80
|
||||
#define SMALL_WIDTH 40
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| BDOS Function Calls |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define WARMBOOT 0
|
||||
#define CONIN 1
|
||||
#define CONSOLE_OUTPUT 2
|
||||
#define READER_INPUT 3
|
||||
#define PUNCH_OUTPUT 4
|
||||
#define LIST_OUTPUT 5
|
||||
#define DIR_CONS_I/O 6
|
||||
#define GET_I/O_BYTE 7
|
||||
#define SET_I/O_BYTE 8
|
||||
#define PRINT_STRING 9
|
||||
#define READ_CONS_BUF 10
|
||||
#define GET_CONS_STAT 11
|
||||
#define RET_VERSION_NO 12
|
||||
#define RESET_DISK_SYS 13
|
||||
#define SELECT_DISK 14
|
||||
#define OPEN_FILE 15
|
||||
#define CLOSE_FILE 16
|
||||
#define SEARCH_FIRST 17
|
||||
#define SEARCH_NEXT 18
|
||||
#define DELETE_FILE 19
|
||||
#define READ_SEQ 20
|
||||
#define WRITE_SEQ 21
|
||||
#define MAKE_FILE 22
|
||||
#define RENAME_FILE 23
|
||||
#define RET_LOGIN_VEC 24
|
||||
#define RET_CUR_DISK 25
|
||||
#define SET_DMA_ADDR 26
|
||||
#define GET_ADDR(ALLOC) 27
|
||||
#define WRITE_PROT_DISK 28
|
||||
#define GET_READ/O_VEC 29
|
||||
#define SET_FILE_ATTRIB 30
|
||||
#define GET_ADDR_D_PARM 31
|
||||
#define GET_USER_NO 32
|
||||
#define READ_RANDOM 33
|
||||
#define WRITE_RANDOM 34
|
||||
#define COMP_FILE-SIZE 35
|
||||
#define SET_RANDOM_REC 36
|
||||
#define RESET_DRIVE 37
|
||||
#define WRITE_RAN_ZERO 40
|
||||
#define BIOS_CALL 50
|
||||
#define LOAD_PROGRAM 59
|
||||
|
||||
/*----------------------------------------------*\
|
||||
| MACROS |
|
||||
\*----------------------------------------------*/
|
||||
|
||||
#define isalpha(c) (islower(c) || isupper(c))
|
||||
#define islower(c) ('a' <= (c) && (c) <= 'z')
|
||||
#define isupper(c) ('A' <= (c) && (c) <= 'Z')
|
||||
#define tolower(c) (isupper(c) ? ((c)+040):(c))
|
||||
#define toupper(c) (islower(c) ? ((c)-040):(c))
|
||||
#define isdigit(c) ('0' <= (c) && (c) <= '9')
|
||||
|
||||
161
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccpdef.lst
Normal file
161
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccpdef.lst
Normal file
@@ -0,0 +1,161 @@
|
||||
1File: CCPDEF.H Page 1
|
||||
1 /*--------------------------------------------------------------*\
|
||||
2 | ccp_def.c DEFINES v1.0 |
|
||||
3 | ======= |
|
||||
4 | |
|
||||
5 | CP/M 68k: A CP/M derived operating system |
|
||||
6 | |
|
||||
7 | File contents: |
|
||||
8 | ------------- |
|
||||
9 | This file contains all of the #defines |
|
||||
10 | used by the console command processor. |
|
||||
11 | |
|
||||
12 | created by : Tom Saulpaugh Date: 7/13/82 |
|
||||
13 | ---------- |
|
||||
14 | last modified: 10/29/82 |
|
||||
15 | ------------- |
|
||||
16 | |
|
||||
17 | (c) COPYRIGHT Digital Research 1982 |
|
||||
18 | all rights reserved |
|
||||
19 | |
|
||||
20 \*--------------------------------------------------------------*/
|
||||
21
|
||||
22
|
||||
23 /*-------------------------------------------*\
|
||||
24 | CP/M Transient Commands |
|
||||
25 \*-------------------------------------------*/
|
||||
26
|
||||
27 #define DIRCMD 0
|
||||
28 #define TYPECMD 1
|
||||
29 #define RENCMD 2
|
||||
30 #define ERACMD 3
|
||||
31 #define UCMD 4
|
||||
32 #define CH_DISK 5
|
||||
33 #define SUBCMD 6
|
||||
34 #define SUB_FILE 7
|
||||
35 #define FILE 8
|
||||
36 #define DIRSCMD 9
|
||||
37 #define SEARCH 10
|
||||
38
|
||||
39 /*-------------------------------------------*\
|
||||
40 | Modes and Flags |
|
||||
41 \*-------------------------------------------*/
|
||||
42
|
||||
43 #define ON 1
|
||||
44 #define OFF 0
|
||||
45 #define MATCH 0
|
||||
46 #define GOOD 1
|
||||
47 #define BAD 0
|
||||
48 #define FILL 1
|
||||
49 #define NOFILL 0
|
||||
50 #define VOID /*no return value*/
|
||||
51 #define NO_FILE 98
|
||||
52 #define STOP 99
|
||||
53 #define USER_ZERO 0
|
||||
54 #define DISK_A 1
|
||||
55 #define SOURCEDRIVE 88
|
||||
56 #define DESTDRIVE 99
|
||||
57 #define BYTE char
|
||||
58 #define REG register
|
||||
59 #define WORD signed short
|
||||
1File: CCPDEF.H Page 2
|
||||
60 #define UWORD unsigned int
|
||||
61 #define LONG signed long
|
||||
62 #define ULONG unsigned long
|
||||
63 #define GET_MEM_REG 18
|
||||
64 #define ZERO 0
|
||||
65 #define NULL '\0'
|
||||
66 #define TRUE 1
|
||||
67 #define FALSE 0
|
||||
68 #define NO_READ 255
|
||||
69 #define BLANK ' '
|
||||
70 #define BACKSLH '\\'
|
||||
71 #define EXLIMPT '!'
|
||||
72 #define CMASK 0177
|
||||
73 #define ONE (long)49
|
||||
74 #define TAB 9
|
||||
75 #define Cr 13
|
||||
76 #define Lf 10
|
||||
77 #define CR (long)13
|
||||
78 #define LF (long)10
|
||||
79 #define EOF 26
|
||||
80 #define BLANKS (long)32
|
||||
81 #define PERIOD (long)46
|
||||
82 #define COLON (long)58
|
||||
83 #define ARROW (long)62
|
||||
84
|
||||
85 /*-------------------------------------------*\
|
||||
86 | Data Structure Size Constants |
|
||||
87 \*-------------------------------------------*/
|
||||
88
|
||||
89 #define CMD_LEN 128
|
||||
90 #define BIG_CMD_LEN 255
|
||||
91 #define MAX_ARGS 4
|
||||
92 #define ARG_LEN 26
|
||||
93 #define NO_OF_DRIVES 16
|
||||
94 #define NUMDELS 16
|
||||
95 #define FCB_LEN 36
|
||||
96 #define DMA_LEN 128
|
||||
97 #define FILES_PER_LINE 5
|
||||
98 #define SCR_HEIGHT 23
|
||||
99 #define BIG_WIDTH 80
|
||||
100 #define SMALL_WIDTH 40
|
||||
101
|
||||
102 /*-------------------------------------------*\
|
||||
103 | BDOS Function Calls |
|
||||
104 \*-------------------------------------------*/
|
||||
105
|
||||
106 #define WARMBOOT 0
|
||||
107 #define CONIN 1
|
||||
108 #define CONSOLE_OUTPUT 2
|
||||
109 #define READER_INPUT 3
|
||||
110 #define PUNCH_OUTPUT 4
|
||||
111 #define LIST_OUTPUT 5
|
||||
112 #define DIR_CONS_I/O 6
|
||||
113 #define GET_I/O_BYTE 7
|
||||
114 #define SET_I/O_BYTE 8
|
||||
115 #define PRINT_STRING 9
|
||||
116 #define READ_CONS_BUF 10
|
||||
117 #define GET_CONS_STAT 11
|
||||
118 #define RET_VERSION_NO 12
|
||||
1File: CCPDEF.H Page 3
|
||||
119 #define RESET_DISK_SYS 13
|
||||
120 #define SELECT_DISK 14
|
||||
121 #define OPEN_FILE 15
|
||||
122 #define CLOSE_FILE 16
|
||||
123 #define SEARCH_FIRST 17
|
||||
124 #define SEARCH_NEXT 18
|
||||
125 #define DELETE_FILE 19
|
||||
126 #define READ_SEQ 20
|
||||
127 #define WRITE_SEQ 21
|
||||
128 #define MAKE_FILE 22
|
||||
129 #define RENAME_FILE 23
|
||||
130 #define RET_LOGIN_VEC 24
|
||||
131 #define RET_CUR_DISK 25
|
||||
132 #define SET_DMA_ADDR 26
|
||||
133 #define GET_ADDR(ALLOC) 27
|
||||
134 #define WRITE_PROT_DISK 28
|
||||
135 #define GET_READ/O_VEC 29
|
||||
136 #define SET_FILE_ATTRIB 30
|
||||
137 #define GET_ADDR_D_PARM 31
|
||||
138 #define GET_USER_NO 32
|
||||
139 #define READ_RANDOM 33
|
||||
140 #define WRITE_RANDOM 34
|
||||
141 #define COMP_FILE-SIZE 35
|
||||
142 #define SET_RANDOM_REC 36
|
||||
143 #define RESET_DRIVE 37
|
||||
144 #define WRITE_RAN_ZERO 40
|
||||
145 #define BIOS_CALL 50
|
||||
146 #define LOAD_PROGRAM 59
|
||||
147
|
||||
148 /*----------------------------------------------*\
|
||||
149 | MACROS |
|
||||
150 \*----------------------------------------------*/
|
||||
151
|
||||
152 #define isalpha(c) (islower(c) || isupper(c))
|
||||
153 #define islower(c) ('a' <= (c) && (c) <= 'z')
|
||||
154 #define isupper(c) ('A' <= (c) && (c) <= 'Z')
|
||||
155 #define tolower(c) (isupper(c) ? ((c)+040):(c))
|
||||
156 #define toupper(c) (islower(c) ? ((c)-040):(c))
|
||||
157 #define isdigit(c) ('0' <= (c) && (c) <= '9')
|
||||
158
|
||||
131
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccpif.lis
Normal file
131
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccpif.lis
Normal file
@@ -0,0 +1,131 @@
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 1
|
||||
Source File: ccpif.s
|
||||
|
||||
1 *************************************************************************
|
||||
2 * *
|
||||
3 * CPM68K INTERFACE MODULE FOR *
|
||||
4 * THE CONSOLE COMMAND PROCESSOR *
|
||||
5 * *
|
||||
6 * THIS IS THE DUAL-PROCESSOR,ROMABLE CP/M-68K SYSTEM *
|
||||
7 * ================================================== *
|
||||
8 * *
|
||||
9 * (C) Copyright Digital Research 1983 all rights reserved *
|
||||
10 * *
|
||||
11 *************************************************************************
|
||||
12
|
||||
13
|
||||
14 .globl _bios1
|
||||
15 .globl _bdos
|
||||
16 .globl _load68k
|
||||
17 .globl _load_tbl
|
||||
18 .globl init_tbl
|
||||
19 .globl _load_try
|
||||
20 .globl _autorom
|
||||
21 .globl flags
|
||||
22 .globl TPAB
|
||||
23 .globl stack
|
||||
24 .globl _bdosini
|
||||
25 .globl _main
|
||||
26 .globl _submit
|
||||
27 .globl _morecmds
|
||||
28 .globl _autost
|
||||
29 .globl _usercmd
|
||||
30 .globl _init
|
||||
31 .globl _ccp
|
||||
32 .globl _patch
|
||||
33 .globl cpm
|
||||
34
|
||||
35 00000000 .text
|
||||
36 cpm:
|
||||
37 00000000 4EF900000038 jmp.l ccpstart * start ccp with possible initial command
|
||||
38 00000006 4EF900000032 jmp.l ccpclear * clear auto start flag
|
||||
39
|
||||
40
|
||||
41
|
||||
42 00000000 .bss
|
||||
43 00000000 _autost: .ds.b 1 * autostart command flag
|
||||
44 00000001 _usercmd: .ds.b 130 * user command buffer
|
||||
45
|
||||
46 00000084 .text
|
||||
46 0000000C
|
||||
47 0000000C 434F505952494748 copy: .dc.b 'COPYRIGHT (C) 1982, Digital Research '
|
||||
47 00000014 5420284329203139
|
||||
47 0000001C 38322C2044696769
|
||||
47 00000024 74616C2052657365
|
||||
47 0000002C 6172636820
|
||||
48
|
||||
49
|
||||
50 00000032 .text
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 2
|
||||
Source File: ccpif.s
|
||||
|
||||
50 00000032
|
||||
51 ccpclear:
|
||||
52 00000032 423900000000 clr.b _autost * clear the autostart flag
|
||||
53
|
||||
54 ccpstart:
|
||||
55 00000038 4FF900000000 lea stack,sp * set up the stack pointer
|
||||
56 0000003E 423900000000 clr.b _autost * clear the auto start flag
|
||||
57 00000044 4EB900000000 jsr _init * call bios init
|
||||
58 0000004A 33C000000084 move.w d0,dskuser * save user # & disk
|
||||
59 *
|
||||
60 *
|
||||
61 * ROM SYSTEM INITIALIZATION
|
||||
62 * OF BSS VARIABLES
|
||||
63 *
|
||||
64 *
|
||||
65
|
||||
66 00000050 423900000000 clr.b _load_try
|
||||
67 00000056 423900000086 clr.b _submit
|
||||
68 0000005C 423900000088 clr.b _morecmds
|
||||
69 00000062 13FC000100000000 move.b #$1,_autorom
|
||||
70 0000006A 427900000000 clr.w flags
|
||||
71 00000070 427900000000 clr.w TPAB
|
||||
72 00000076 4EB900000000 jsr init_tbl
|
||||
73
|
||||
74
|
||||
75
|
||||
76 0000007C 4EB900000000 jsr _bdosini * do bdos init
|
||||
77 00000082 303C0020 move.w #32,d0 * get user bdos func #
|
||||
78 00000086 4281 clr.l d1 * clear out d1
|
||||
79 00000088 123900000084 move.b dskuser,d1 * get the user #
|
||||
80 0000008E 4E42 trap #2 * set the user number
|
||||
81 00000090 4280 clr.l d0 * clear d0
|
||||
82 00000092 303C000E move.w #14,d0 * select function
|
||||
83 00000096 4281 clr.l d1 * clear d1
|
||||
84 00000098 323900000084 move.w dskuser,d1 * get disk to be selected
|
||||
85 0000009E 024100FF andi #$0ff,d1 * mask off the user #
|
||||
86 000000A2 4E42 trap #2 * select the disk
|
||||
87
|
||||
88 _ccp:
|
||||
89 000000A4 4FF900000000 lea stack,sp * set up the stack pointer
|
||||
90 000000AA 4EB900000000 jsr _main * call the CCP
|
||||
91 000000B0 60F2 bra _ccp
|
||||
92
|
||||
93 00000084 .bss
|
||||
94 .even
|
||||
95
|
||||
96 00000084 dskuser: .ds.w 1
|
||||
97 .even
|
||||
98 00000086 _submit: .ds.b 1
|
||||
99 00000088 .even
|
||||
99 00000088
|
||||
100 00000088 _morecmds: .ds.b 1
|
||||
101 0000008A .even
|
||||
101 0000008A
|
||||
102 0000008A _patch .ds.l 25
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 3
|
||||
Source File: ccpif.s
|
||||
|
||||
103 000000EE .end
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 4
|
||||
Source File: ccpif.s
|
||||
|
||||
S y m b o l T a b l e
|
||||
|
||||
TPAB ******** EXT _autorom ******** EXT _autost 00000000 BSS _bdos ******** EXT
|
||||
_bdosini ******** EXT _bios1 ******** EXT _ccp 000000A4 TEXT _init ******** EXT
|
||||
_load68k ******** EXT _load_tb ******** EXT _load_tr ******** EXT _main ******** EXT
|
||||
_morecmd 00000088 BSS _patch 0000008A BSS _submit 00000086 BSS _usercmd 00000001 BSS
|
||||
ccpclear 00000032 TEXT ccpstart 00000038 TEXT copy 0000000C TEXT cpm 00000000 TEXT
|
||||
dskuser 00000084 BSS flags ******** EXT init_tbl ******** EXT stack ******** EXT
|
||||
113
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccpif.s
Normal file
113
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccpif.s
Normal file
@@ -0,0 +1,113 @@
|
||||
*************************************************************************
|
||||
* *
|
||||
* CPM68K INTERFACE MODULE FOR *
|
||||
* THE CONSOLE COMMAND PROCESSOR *
|
||||
* *
|
||||
* THIS IS THE DUAL-PROCESSOR,ROMABLE CP/M-68K SYSTEM *
|
||||
* ================================================== *
|
||||
* *
|
||||
* (C) Copyright Digital Research 1983 all rights reserved *
|
||||
* *
|
||||
*************************************************************************
|
||||
|
||||
|
||||
.globl _bios1
|
||||
.globl _bdos
|
||||
.globl _load68k
|
||||
.globl _load_tbl
|
||||
.globl init_tbl
|
||||
.globl _load_try
|
||||
.globl _autorom
|
||||
.globl flags
|
||||
.globl TPAB
|
||||
.globl stack
|
||||
.globl _bdosini
|
||||
.globl _main
|
||||
.globl _submit
|
||||
.globl _morecmds
|
||||
.globl _autost
|
||||
.globl _usercmd
|
||||
.globl _init
|
||||
.globl _ccp
|
||||
.globl _patch
|
||||
.globl cpm
|
||||
|
||||
.text
|
||||
cpm:
|
||||
jmp.l ccpstart * start ccp with possible initial command
|
||||
jmp.l ccpclear * clear auto start flag
|
||||
|
||||
|
||||
|
||||
.bss
|
||||
_autost: .ds.b 1 * autostart command flag
|
||||
_usercmd: .ds.b 130 * user command buffer
|
||||
|
||||
.text
|
||||
copy: .dc.b 'COPYRIGHT (C) 1982, Digital Research '
|
||||
|
||||
|
||||
.text
|
||||
ccpclear:
|
||||
clr.b _autost * clear the autostart flag
|
||||
|
||||
ccpstart:
|
||||
lea stack,sp * set up the stack pointer
|
||||
clr.b _autost * clear the auto start flag
|
||||
jsr _init * call bios init
|
||||
move.w d0,dskuser * save user # & disk
|
||||
*
|
||||
*
|
||||
* ROM SYSTEM INITIALIZATION
|
||||
* OF BSS VARIABLES
|
||||
*
|
||||
*
|
||||
|
||||
clr.b _load_try
|
||||
clr.b _submit
|
||||
clr.b _morecmds
|
||||
move.b #$1,_autorom
|
||||
clr.w flags
|
||||
clr.w TPAB
|
||||
jsr init_tbl
|
||||
|
||||
|
||||
|
||||
jsr _bdosini * do bdos init
|
||||
move.w #32,d0 * get user bdos func #
|
||||
clr.l d1 * clear out d1
|
||||
move.b dskuser,d1 * get the user #
|
||||
trap #2 * set the user number
|
||||
clr.l d0 * clear d0
|
||||
move.w #14,d0 * select function
|
||||
clr.l d1 * clear d1
|
||||
move.w dskuser,d1 * get disk to be selected
|
||||
andi #$0ff,d1 * mask off the user #
|
||||
trap #2 * select the disk
|
||||
|
||||
_ccp:
|
||||
lea stack,sp * set up the stack pointer
|
||||
jsr _main * call the CCP
|
||||
bra _ccp
|
||||
|
||||
.bss
|
||||
.even
|
||||
|
||||
dskuser: .ds.w 1
|
||||
.even
|
||||
_submit: .ds.b 1
|
||||
.even
|
||||
_morecmds: .ds.b 1
|
||||
.even
|
||||
_patch .ds.l 25
|
||||
.end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 1
|
||||
Source File: ccpload.s
|
||||
|
||||
1 *****************************************************************
|
||||
2 * *
|
||||
3 * COMMAND FILE LOADER FOR CPM68K *
|
||||
4 * ============================== *
|
||||
5 * *
|
||||
6 * (c) COPYRIGHT Digital Research 1983 *
|
||||
7 * all rights reserved *
|
||||
8 * *
|
||||
9 * THIS IS THE DUAL PROCESSOR,ROMABLE CP/M-68K SYSTEM *
|
||||
10 * ================================================== *
|
||||
11 * *
|
||||
12 * Description: *
|
||||
13 * ----------- The command file loader is envoked by *
|
||||
14 * the CCP after the CCP has successfully *
|
||||
15 * opened that file. The loader must *
|
||||
16 * call the BDOS to obtain the boundries *
|
||||
17 * of the TPA. The load parameter block *
|
||||
18 * defined in this loader holds all the *
|
||||
19 * memory size and location details. *
|
||||
20 * Next the loader returns the system to *
|
||||
21 * its original user #. The CCP might *
|
||||
22 * have switched to user zero during its *
|
||||
23 * search for the file. Next the default *
|
||||
24 * dma address is set for the loaded *
|
||||
25 * program. Next the command tail is *
|
||||
26 * placed,along with the first two parsed *
|
||||
27 * fcb's,into the user basepage. *
|
||||
28 * Lastly the user stack pointer is set up *
|
||||
29 * and the return address is put on the *
|
||||
30 * user stack. An RTE transferes control. *
|
||||
31 * If a load was not successfull, the *
|
||||
32 * appropriate error message is printed. *
|
||||
33 * *
|
||||
34 * Created by: Tom Saulpaugh *
|
||||
35 * *
|
||||
36 * Last Modified: 3/02/83 *
|
||||
37 * *
|
||||
38 *****************************************************************
|
||||
39
|
||||
40
|
||||
41
|
||||
42 .globl _load68k * make this procedure public
|
||||
43 .globl _user * global user # before load occured
|
||||
44 .globl _cmdfcb * parsed fcb
|
||||
45 .globl _tail * global pointer to command tail
|
||||
46 .globl _fill_fcb * procedure to fill fcb's
|
||||
47 .globl flags * ROM SYSTEM INITIALIZATION
|
||||
48 .globl TPAB * ROM SYSTEM INITIALIZATION
|
||||
49
|
||||
50
|
||||
51 reboot = 0
|
||||
52 printstr = 9
|
||||
53 setdma = 26
|
||||
54 chuser = 32
|
||||
55 pgmldf = 59
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 2
|
||||
Source File: ccpload.s
|
||||
|
||||
56 gettpa = 63
|
||||
57
|
||||
58 _load68k:
|
||||
59 *
|
||||
60 * Load the 68k file into the TPA
|
||||
61 * ------------------------------
|
||||
62 *
|
||||
63 00000000 .text
|
||||
64
|
||||
65 00000000 223C00000016 move.l #TPAB,d1 * move in address of tpa parameter block
|
||||
66 00000006 303C003F move.w #gettpa,d0 * get function number
|
||||
67 0000000A 4E42 trap #2 * get the tpa limits
|
||||
68 0000000C 23F90000001800000004 move.l low,lowadr * put it in the lpb
|
||||
69 00000016 23F90000001C00000008 move.l high,hiadr * put high tpa addr in lpb
|
||||
70 00000020 23FC0000000000000000 move.l #_cmdfcb,LPB * get address of opened fcb
|
||||
71 0000002A 703B move.l #pgmldf,d0 * move in bdos function no
|
||||
72 0000002C 223C00000000 move.l #LPB,d1 * d1 points to load block
|
||||
73 00000032 4E42 trap #2 * do the program load
|
||||
74 00000034 4A40 tst d0 * was the load successful?
|
||||
75 00000036 66000096 bne lderr * if not print error message and return
|
||||
76 *
|
||||
77 * return to original user #
|
||||
78 * -------------------------
|
||||
79 0000003A 323900000000 move.w _user,d1 * put user # to switch to in d1
|
||||
80 00000040 7020 move.l #chuser,d0 * put bdos func # in d0
|
||||
81 00000042 4E42 trap #2 * do the user # change
|
||||
82 *
|
||||
83 * set the default dma address
|
||||
84 * ---------------------------
|
||||
85 00000044 4281 clr.l d1 * clear d1 register
|
||||
86 00000046 22390000000C move.l baspag,d1 * d1 points to user base page
|
||||
87 0000004C D27C0080 add #$80,d1 * d1 points to default dma in base page
|
||||
88 00000050 2241 movea.l d1,a1 * save it for later use
|
||||
89 00000052 701A move #setdma,d0 * move in bdos function no
|
||||
90 00000054 4E42 trap #2 * set the default dma address
|
||||
91 *
|
||||
92 * move in the command tail
|
||||
93 * ------------------------
|
||||
94 00000056 2449 move.l a1,a2 * save a pointer to the count field
|
||||
95 00000058 5289 add.l #$01,a1 * point past count field
|
||||
96 0000005A 207900000000 move.l _tail,a0 * point to command tail
|
||||
97 00000060 4280 clr.l d0 * clear out d0
|
||||
98 00000062 0C100000 mvtail: cmpi.b #$00,(a0) * check for a NULL ending byte
|
||||
99 00000066 670C beq done * NULL byte terminates command
|
||||
100 00000068 0C100021 cmpi.b #$21,(a0) * check for an '!'
|
||||
101 0000006C 6706 beq done * '!' ends the command
|
||||
102 0000006E 12D8 move.b (a0)+,(a1)+ * move a byte of the command tail
|
||||
103 00000070 5240 addq #1,d0 * bump up the character count
|
||||
104 00000072 60EE bra mvtail * continue byte move
|
||||
105 00000074 1480 done: move.b d0,(a2) * put in the character count
|
||||
106 00000076 12BC0000 move.b #$00,(a1) * terminate cmd tail with a NULL byte
|
||||
107 *
|
||||
108 * fill fcb1 & fcb2
|
||||
109 * ----------------
|
||||
110 0000007A 2F3C00000000 move.l #_cmdfcb,-(sp) * put address of fcb buffer onto stack
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 3
|
||||
Source File: ccpload.s
|
||||
|
||||
111 00000080 3F3C0001 move.w #1,-(sp) * put 1 on stack(parm1)
|
||||
112 00000084 4EB900000000 jsr _fill_fcb * jump to 'C' code & fill cmdfcb with parm1
|
||||
113 0000008A 5C8F add.l #6,sp * clean off the stack
|
||||
114 0000008C 4280 clr.l d0 * clear register d0
|
||||
115 0000008E 705C moveq #$5c,d0 * put basepage address of fcb1 in d0
|
||||
116 00000090 6142 bsr movfcb * put fcb1 in the basepage
|
||||
117 00000092 2F3C00000000 move.l #_cmdfcb,-(sp) * put address of fcb buffer onto stack
|
||||
118 00000098 3F3C0002 move.w #2,-(sp) * put 2 on stack(parm2)
|
||||
119 0000009C 4EB900000000 jsr _fill_fcb * jump to 'C' code & fill cmdfcb with parm2
|
||||
120 000000A2 5C8F add.l #6,sp * clean off the stack
|
||||
121 000000A4 4280 clr.l d0 * clear register d0
|
||||
122 000000A6 7038 moveq #$38,d0 * put basepage address of fcb1 in d0
|
||||
123 000000A8 612A bsr movfcb * put fcb2 in the basepage
|
||||
124 *
|
||||
125 * now push rte stuff on stack
|
||||
126 * ---------------------------
|
||||
127 000000AA 207900000010 movea.l usrstk,a0 * get user stack pointer
|
||||
128 000000B0 22790000000C move.l baspag,a1 * get basepage address
|
||||
129 000000B6 2F290008 move.l 8(a1),-(sp) * push address we want to jump to
|
||||
130 000000BA 40C0 move sr,d0 * get the status register in d0
|
||||
131 000000BC 02405F00 andi #$5f00,d0 * mask trace,system bits,user flags
|
||||
132 000000C0 3F00 move.w d0,-(sp) * push it on stack
|
||||
133 000000C2 2109 move.l a1,-(a0) * push addr of basepage onto user stack
|
||||
134 000000C4 213C000000D0 move.l #cmdrtn,-(a0) * push return address onto user stack
|
||||
135 000000CA 4E60 move.l a0,usp * set up user stack pointer
|
||||
136 000000CC 4E73 rte
|
||||
137 *
|
||||
138 * load error
|
||||
139 * ----------
|
||||
140 lderr:
|
||||
141 000000CE 4E75 rts * return with error code in d0
|
||||
142 cmdrtn:
|
||||
143 000000D0 7000 move #reboot,d0 * reboot CPM
|
||||
144 000000D2 4E42 trap #2
|
||||
145 movfcb:
|
||||
146 000000D4 D0B90000000C add.l baspag,d0 * get offset into basepage
|
||||
147 000000DA 2040 move.l d0,a0 * move address into a0
|
||||
148 000000DC 227C00000000 move.l #_cmdfcb,a1 * a1 points to fcb to be moved
|
||||
149 000000E2 4280 clr.l d0 * clear register d0
|
||||
150 000000E4 7023 moveq #35,d0 * get length of fcb
|
||||
151 mov1:
|
||||
152 000000E6 10D9 move.b (a1)+,(a0)+ * move a byte into the basepage
|
||||
153 000000E8 51C8FFFC dbf d0,mov1 * if not done branch to mov1
|
||||
154 000000EC 4E75 rts
|
||||
155
|
||||
156
|
||||
157 00000000 .bss
|
||||
158
|
||||
159 .even
|
||||
160 *
|
||||
161 * LOAD PARAMETER BLOCK
|
||||
162 *
|
||||
163 00000000 LPB: .ds.l 1
|
||||
164 00000004 lowadr: .ds.l 1
|
||||
165 00000008 hiadr: .ds.l 1
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 4
|
||||
Source File: ccpload.s
|
||||
|
||||
166 0000000C baspag: .ds.l 1
|
||||
167 00000010 usrstk: .ds.l 1
|
||||
168 00000014 flags: .ds.w 1
|
||||
169
|
||||
170 *
|
||||
171 * TPA Parameter Block
|
||||
172 *
|
||||
173 .even
|
||||
174 00000016 TPAB: .ds.w 1
|
||||
175 00000018 low: .ds.l 1
|
||||
176 0000001C high: .ds.l 1
|
||||
177
|
||||
178
|
||||
179
|
||||
180
|
||||
181
|
||||
182
|
||||
183
|
||||
184
|
||||
185
|
||||
186
|
||||
187
|
||||
188 00000020 .end
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 5
|
||||
Source File: ccpload.s
|
||||
|
||||
S y m b o l T a b l e
|
||||
|
||||
LPB 00000000 BSS TPAB 00000016 BSS _cmdfcb ******** EXT _fill_fc ******** EXT
|
||||
_load68k 00000000 TEXT _tail ******** EXT _user ******** EXT baspag 0000000C BSS
|
||||
chuser 00000020 ABS cmdrtn 000000D0 TEXT done 00000074 TEXT flags 00000014 BSS
|
||||
gettpa 0000003F ABS hiadr 00000008 BSS high 0000001C BSS lderr 000000CE TEXT
|
||||
low 00000018 BSS lowadr 00000004 BSS mov1 000000E6 TEXT movfcb 000000D4 TEXT
|
||||
mvtail 00000062 TEXT pgmldf 0000003B ABS printstr 00000009 ABS reboot 00000000 ABS
|
||||
setdma 0000001A ABS usrstk 00000010 BSS
|
||||
188
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccpload.s
Normal file
188
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/ccpload.s
Normal file
@@ -0,0 +1,188 @@
|
||||
*****************************************************************
|
||||
* *
|
||||
* COMMAND FILE LOADER FOR CPM68K *
|
||||
* ============================== *
|
||||
* *
|
||||
* (c) COPYRIGHT Digital Research 1983 *
|
||||
* all rights reserved *
|
||||
* *
|
||||
* THIS IS THE DUAL PROCESSOR,ROMABLE CP/M-68K SYSTEM *
|
||||
* ================================================== *
|
||||
* *
|
||||
* Description: *
|
||||
* ----------- The command file loader is envoked by *
|
||||
* the CCP after the CCP has successfully *
|
||||
* opened that file. The loader must *
|
||||
* call the BDOS to obtain the boundries *
|
||||
* of the TPA. The load parameter block *
|
||||
* defined in this loader holds all the *
|
||||
* memory size and location details. *
|
||||
* Next the loader returns the system to *
|
||||
* its original user #. The CCP might *
|
||||
* have switched to user zero during its *
|
||||
* search for the file. Next the default *
|
||||
* dma address is set for the loaded *
|
||||
* program. Next the command tail is *
|
||||
* placed,along with the first two parsed *
|
||||
* fcb's,into the user basepage. *
|
||||
* Lastly the user stack pointer is set up *
|
||||
* and the return address is put on the *
|
||||
* user stack. An RTE transferes control. *
|
||||
* If a load was not successfull, the *
|
||||
* appropriate error message is printed. *
|
||||
* *
|
||||
* Created by: Tom Saulpaugh *
|
||||
* *
|
||||
* Last Modified: 3/02/83 *
|
||||
* *
|
||||
*****************************************************************
|
||||
|
||||
|
||||
|
||||
.globl _load68k * make this procedure public
|
||||
.globl _user * global user # before load occured
|
||||
.globl _cmdfcb * parsed fcb
|
||||
.globl _tail * global pointer to command tail
|
||||
.globl _fill_fcb * procedure to fill fcb's
|
||||
.globl flags * ROM SYSTEM INITIALIZATION
|
||||
.globl TPAB * ROM SYSTEM INITIALIZATION
|
||||
|
||||
|
||||
reboot = 0
|
||||
printstr = 9
|
||||
setdma = 26
|
||||
chuser = 32
|
||||
pgmldf = 59
|
||||
gettpa = 63
|
||||
|
||||
_load68k:
|
||||
*
|
||||
* Load the 68k file into the TPA
|
||||
* ------------------------------
|
||||
*
|
||||
.text
|
||||
|
||||
move.l #TPAB,d1 * move in address of tpa parameter block
|
||||
move.w #gettpa,d0 * get function number
|
||||
trap #2 * get the tpa limits
|
||||
move.l low,lowadr * put it in the lpb
|
||||
move.l high,hiadr * put high tpa addr in lpb
|
||||
move.l #_cmdfcb,LPB * get address of opened fcb
|
||||
move.l #pgmldf,d0 * move in bdos function no
|
||||
move.l #LPB,d1 * d1 points to load block
|
||||
trap #2 * do the program load
|
||||
tst d0 * was the load successful?
|
||||
bne lderr * if not print error message and return
|
||||
*
|
||||
* return to original user #
|
||||
* -------------------------
|
||||
move.w _user,d1 * put user # to switch to in d1
|
||||
move.l #chuser,d0 * put bdos func # in d0
|
||||
trap #2 * do the user # change
|
||||
*
|
||||
* set the default dma address
|
||||
* ---------------------------
|
||||
clr.l d1 * clear d1 register
|
||||
move.l baspag,d1 * d1 points to user base page
|
||||
add #$80,d1 * d1 points to default dma in base page
|
||||
movea.l d1,a1 * save it for later use
|
||||
move #setdma,d0 * move in bdos function no
|
||||
trap #2 * set the default dma address
|
||||
*
|
||||
* move in the command tail
|
||||
* ------------------------
|
||||
move.l a1,a2 * save a pointer to the count field
|
||||
add.l #$01,a1 * point past count field
|
||||
move.l _tail,a0 * point to command tail
|
||||
clr.l d0 * clear out d0
|
||||
mvtail: cmpi.b #$00,(a0) * check for a NULL ending byte
|
||||
beq done * NULL byte terminates command
|
||||
cmpi.b #$21,(a0) * check for an '!'
|
||||
beq done * '!' ends the command
|
||||
move.b (a0)+,(a1)+ * move a byte of the command tail
|
||||
addq #1,d0 * bump up the character count
|
||||
bra mvtail * continue byte move
|
||||
done: move.b d0,(a2) * put in the character count
|
||||
move.b #$00,(a1) * terminate cmd tail with a NULL byte
|
||||
*
|
||||
* fill fcb1 & fcb2
|
||||
* ----------------
|
||||
move.l #_cmdfcb,-(sp) * put address of fcb buffer onto stack
|
||||
move.w #1,-(sp) * put 1 on stack(parm1)
|
||||
jsr _fill_fcb * jump to 'C' code & fill cmdfcb with parm1
|
||||
add.l #6,sp * clean off the stack
|
||||
clr.l d0 * clear register d0
|
||||
moveq #$5c,d0 * put basepage address of fcb1 in d0
|
||||
bsr movfcb * put fcb1 in the basepage
|
||||
move.l #_cmdfcb,-(sp) * put address of fcb buffer onto stack
|
||||
move.w #2,-(sp) * put 2 on stack(parm2)
|
||||
jsr _fill_fcb * jump to 'C' code & fill cmdfcb with parm2
|
||||
add.l #6,sp * clean off the stack
|
||||
clr.l d0 * clear register d0
|
||||
moveq #$38,d0 * put basepage address of fcb1 in d0
|
||||
bsr movfcb * put fcb2 in the basepage
|
||||
*
|
||||
* now push rte stuff on stack
|
||||
* ---------------------------
|
||||
movea.l usrstk,a0 * get user stack pointer
|
||||
move.l baspag,a1 * get basepage address
|
||||
move.l 8(a1),-(sp) * push address we want to jump to
|
||||
move sr,d0 * get the status register in d0
|
||||
andi #$5f00,d0 * mask trace,system bits,user flags
|
||||
move.w d0,-(sp) * push it on stack
|
||||
move.l a1,-(a0) * push addr of basepage onto user stack
|
||||
move.l #cmdrtn,-(a0) * push return address onto user stack
|
||||
move.l a0,usp * set up user stack pointer
|
||||
rte
|
||||
*
|
||||
* load error
|
||||
* ----------
|
||||
lderr:
|
||||
rts * return with error code in d0
|
||||
cmdrtn:
|
||||
move #reboot,d0 * reboot CPM
|
||||
trap #2
|
||||
movfcb:
|
||||
add.l baspag,d0 * get offset into basepage
|
||||
move.l d0,a0 * move address into a0
|
||||
move.l #_cmdfcb,a1 * a1 points to fcb to be moved
|
||||
clr.l d0 * clear register d0
|
||||
moveq #35,d0 * get length of fcb
|
||||
mov1:
|
||||
move.b (a1)+,(a0)+ * move a byte into the basepage
|
||||
dbf d0,mov1 * if not done branch to mov1
|
||||
rts
|
||||
|
||||
|
||||
.bss
|
||||
|
||||
.even
|
||||
*
|
||||
* LOAD PARAMETER BLOCK
|
||||
*
|
||||
LPB: .ds.l 1
|
||||
lowadr: .ds.l 1
|
||||
hiadr: .ds.l 1
|
||||
baspag: .ds.l 1
|
||||
usrstk: .ds.l 1
|
||||
flags: .ds.w 1
|
||||
|
||||
*
|
||||
* TPA Parameter Block
|
||||
*
|
||||
.even
|
||||
TPAB: .ds.w 1
|
||||
low: .ds.l 1
|
||||
high: .ds.l 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.end
|
||||
346
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/conbdos.c
Normal file
346
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/conbdos.c
Normal file
@@ -0,0 +1,346 @@
|
||||
|
||||
/********************************************************
|
||||
* *
|
||||
* CP/M-68K BDOS Character I/O Routines *
|
||||
* *
|
||||
* This module does BDOS functions 1 thru 11 *
|
||||
* *
|
||||
* It contains the following functions which *
|
||||
* are called from the BDOS main routine: *
|
||||
* constat(); *
|
||||
* conin(); *
|
||||
* tabout(); *
|
||||
* rawconio(); *
|
||||
* prt_line(); *
|
||||
* readline(); *
|
||||
* *
|
||||
* Copyright (c) 1982 Digital Research, Inc. *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
#include "bdosinc.h"
|
||||
|
||||
#include "bdosdef.h"
|
||||
|
||||
#include "biosdef.h"
|
||||
|
||||
|
||||
#define ctrlc 0x03
|
||||
#define ctrle 0x05
|
||||
#define ctrlp 0x10
|
||||
#define ctrlq 0x11
|
||||
#define ctrlr 0x12
|
||||
#define ctrls 0x13
|
||||
#define ctrlu 0x15
|
||||
#define ctrlx 0x18
|
||||
|
||||
#define cr 0x0d
|
||||
#define lf 0x0a
|
||||
#define tab 0x09
|
||||
#define rub 0x7f
|
||||
#define bs 0x08
|
||||
#define space 0x20
|
||||
|
||||
|
||||
EXTERN warmboot(); /* External function definition */
|
||||
|
||||
|
||||
/******************/
|
||||
/* console status */
|
||||
/******************/
|
||||
|
||||
BOOLEAN constat()
|
||||
{
|
||||
BSETUP
|
||||
|
||||
return( GBL.kbchar ? TRUE : bconstat() );
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* check for ctrl/s */
|
||||
/* used internally */
|
||||
/********************/
|
||||
conbrk()
|
||||
{
|
||||
REG UBYTE ch;
|
||||
REG BOOLEAN stop;
|
||||
BSETUP
|
||||
|
||||
stop = FALSE;
|
||||
if ( bconstat() ) do
|
||||
{
|
||||
if ( (ch = bconin()) == ctrlc ) warmboot(1);
|
||||
if ( ch == ctrls ) stop = TRUE;
|
||||
else if (ch == ctrlq) stop = FALSE;
|
||||
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
else /* Insert character in ring buffer */
|
||||
{ /* */
|
||||
if(GBL.kbchar < TBUFSIZ) /* Room? */
|
||||
{ /************************************/
|
||||
*GBL.insptr++ = ch; /* Yes, insert the character in buff*/
|
||||
GBL.kbchar++; /* Up count */
|
||||
} /************************************/
|
||||
} /* Note if no room, character is */
|
||||
/* Ignomiously discarded (!) */
|
||||
/************************************/
|
||||
} while (stop);
|
||||
}
|
||||
|
||||
|
||||
/******************/
|
||||
/* console output */
|
||||
/* used internally*/
|
||||
/******************/
|
||||
|
||||
conout(ch)
|
||||
REG UBYTE ch;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
conbrk(); /* check for control-s break */
|
||||
bconout(ch); /* output character to console */
|
||||
if (GBL.lstecho) blstout(ch); /* if ctrl-p on, echo to list dev */
|
||||
if (ch >= ' ') GBL.column++; /* keep track of screen column */
|
||||
else if (ch == cr) GBL.column = 0;
|
||||
else if (ch == bs) GBL.column--;
|
||||
}
|
||||
|
||||
|
||||
/*************************************/
|
||||
/* console output with tab expansion */
|
||||
/*************************************/
|
||||
|
||||
tabout(ch)
|
||||
REG UBYTE ch; /* character to output to console */
|
||||
{
|
||||
BSETUP
|
||||
|
||||
if (ch == tab) do
|
||||
conout(' ');
|
||||
while (GBL.column & 7);
|
||||
else conout(ch);
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
/* console output with tab and */
|
||||
/* control character expansion */
|
||||
/*******************************/
|
||||
|
||||
cookdout(ch)
|
||||
REG UBYTE ch; /* character to output to console */
|
||||
{
|
||||
if (ch == tab) tabout(ch); /* if tab, expand it */
|
||||
else
|
||||
{
|
||||
if ( (UWORD)ch < (UWORD)' ' )
|
||||
{
|
||||
conout( '^' );
|
||||
ch |= 0x40;
|
||||
}
|
||||
conout(ch); /* output the character */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************/
|
||||
/* console input */
|
||||
/*****************/
|
||||
|
||||
UBYTE getch() /* Get char from buffer or bios */
|
||||
/* For internal use only */
|
||||
{
|
||||
REG UBYTE temp;
|
||||
BSETUP
|
||||
|
||||
if(GBL.kbchar)
|
||||
{
|
||||
temp = *GBL.remptr++; /* Fetch the character */
|
||||
GBL.kbchar--; /* Decrement the count */
|
||||
if(!GBL.kbchar) /* Gone to zero? */
|
||||
GBL.remptr = GBL.insptr = &(GBL.t_buff[0]);
|
||||
return(temp);
|
||||
}
|
||||
return( bconin() ); /* else get char from bios */
|
||||
}
|
||||
|
||||
UBYTE conin() /* BDOS console input function */
|
||||
{
|
||||
REG UBYTE ch;
|
||||
BSETUP
|
||||
|
||||
conout( ch = getch() );
|
||||
if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
return(ch);
|
||||
}
|
||||
|
||||
/******************
|
||||
* raw console i/o *
|
||||
******************/
|
||||
|
||||
UBYTE rawconio(parm) /* BDOS raw console I/O function */
|
||||
|
||||
REG UWORD parm;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
if (parm == 0xff) return(getch());
|
||||
else if (parm == 0xfe) return(constat());
|
||||
else bconout(parm & 0xff);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************/
|
||||
/* print line up to delimiter($) with tab expansion */
|
||||
/****************************************************/
|
||||
|
||||
prt_line(p)
|
||||
REG UBYTE *p;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
while( *p != GBL.delim ) tabout( *p++ );
|
||||
}
|
||||
|
||||
|
||||
/**********************************************/
|
||||
/* read line with editing and bounds checking */
|
||||
/**********************************************/
|
||||
|
||||
/* Two subroutines first */
|
||||
|
||||
newline(startcol)
|
||||
REG UWORD startcol;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
conout(cr); /* go to new line */
|
||||
conout(lf);
|
||||
while(startcol)
|
||||
{
|
||||
conout(' ');
|
||||
startcol -= 1; /* start output at starting column */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
backsp(bufp, col)
|
||||
/* backspace one character position */
|
||||
REG struct conbuf *bufp; /* pointer to console buffer */
|
||||
REG WORD col; /* starting console column */
|
||||
{
|
||||
REG UBYTE ch; /* current character */
|
||||
REG WORD i;
|
||||
REG UBYTE *p; /* character pointer */
|
||||
BSETUP
|
||||
|
||||
if (bufp->retlen) --(bufp->retlen);
|
||||
/* if buffer non-empty, decrease it by 1 */
|
||||
i = UBWORD(bufp->retlen); /* get new character count */
|
||||
p = &(bufp->cbuf[0]); /* point to character buffer */
|
||||
while (i--) /* calculate column position */
|
||||
{ /* across entire char buffer */
|
||||
ch = *p++; /* get next char */
|
||||
if ( ch == tab )
|
||||
{
|
||||
col += 8;
|
||||
col &= ~7; /* for tab, go to multiple of 8 */
|
||||
}
|
||||
else if ( (UWORD)ch < (UWORD)' ' ) col += 2;
|
||||
/* control chars put out 2 printable chars */
|
||||
else col += 1;
|
||||
}
|
||||
while (GBL.column > col)
|
||||
{
|
||||
conout(bs); /* backspace until we get to proper column */
|
||||
conout(' ');
|
||||
conout(bs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
readline(p) /* BDOS function 10 */
|
||||
REG struct conbuf *p;
|
||||
|
||||
{
|
||||
REG UBYTE ch;
|
||||
REG UWORD i;
|
||||
REG UWORD j;
|
||||
REG UBYTE *q;
|
||||
UWORD stcol;
|
||||
|
||||
BSETUP
|
||||
|
||||
stcol = GBL.column; /* set up starting column */
|
||||
if (GBL.chainp != NULL) /* chain to program code */
|
||||
{
|
||||
i = UBWORD(*(GBL.chainp++));
|
||||
j = UBWORD(p->maxlen);
|
||||
if (j < i) i = j; /* don't overflow console buffer! */
|
||||
p->retlen = (UBYTE)i;
|
||||
q = p->cbuf;
|
||||
while (i)
|
||||
{
|
||||
cookdout( *q++ = *(GBL.chainp++) );
|
||||
i -= 1;
|
||||
}
|
||||
GBL.chainp = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
p->retlen = 0; /* start out with empty buffer */
|
||||
while ( UBWORD(p->retlen) < UBWORD(p->maxlen) )
|
||||
{ /* main loop for read console buffer */
|
||||
|
||||
if ( ((ch=getch()) == ctrlc) && !(p->retlen) )
|
||||
{
|
||||
cookdout(ctrlc);
|
||||
warmboot(1);
|
||||
}
|
||||
|
||||
else if ( (ch == cr) || (ch == lf) )
|
||||
{ /* if cr or lf, exit */
|
||||
conout(cr);
|
||||
break;
|
||||
}
|
||||
|
||||
else if (ch == bs) backsp(p, stcol); /* backspace */
|
||||
|
||||
else if (ch == rub) /* delete character */
|
||||
{
|
||||
if (GBL.echodel)
|
||||
{
|
||||
if (p->retlen)
|
||||
{
|
||||
i = UBWORD(--(p->retlen));
|
||||
conout( p->cbuf[i] );
|
||||
}
|
||||
}
|
||||
else backsp(p, stcol);
|
||||
}
|
||||
|
||||
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
/* control-p */
|
||||
else if (ch == ctrlx) /* control-x */
|
||||
do backsp(p,stcol); while (p->retlen);
|
||||
|
||||
else if (ch == ctrle) newline(stcol); /* control-e */
|
||||
|
||||
else if (ch == ctrlu) /* control-u */
|
||||
{
|
||||
conout('#');
|
||||
newline(stcol);
|
||||
p->retlen = 0;
|
||||
}
|
||||
|
||||
else if (ch == ctrlr) /* control-r */
|
||||
{
|
||||
conout('#');
|
||||
newline(stcol);
|
||||
for (i=0; i < UBWORD(p->retlen); i++)
|
||||
cookdout( p->cbuf[i] );
|
||||
}
|
||||
|
||||
else /* normal character */
|
||||
cookdout( p->cbuf[UBWORD((p->retlen)++)] = ch );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
1File: CONBDOS.C Page 1
|
||||
1
|
||||
2 /********************************************************
|
||||
3 * *
|
||||
4 * CP/M-68K BDOS Character I/O Routines *
|
||||
5 * *
|
||||
6 * This module does BDOS functions 1 thru 11 *
|
||||
7 * *
|
||||
8 * It contains the following functions which *
|
||||
9 * are called from the BDOS main routine: *
|
||||
10 * constat(); *
|
||||
11 * conin(); *
|
||||
12 * tabout(); *
|
||||
13 * rawconio(); *
|
||||
14 * prt_line(); *
|
||||
15 * readline(); *
|
||||
16 * *
|
||||
17 * Copyright (c) 1982 Digital Research, Inc. *
|
||||
18 * *
|
||||
19 ********************************************************/
|
||||
20
|
||||
21 #include "bdosinc.h"
|
||||
22
|
||||
23 #include "bdosdef.h"
|
||||
24
|
||||
25 #include "biosdef.h"
|
||||
26
|
||||
27
|
||||
28 #define ctrlc 0x03
|
||||
29 #define ctrle 0x05
|
||||
30 #define ctrlp 0x10
|
||||
31 #define ctrlq 0x11
|
||||
32 #define ctrlr 0x12
|
||||
33 #define ctrls 0x13
|
||||
34 #define ctrlu 0x15
|
||||
35 #define ctrlx 0x18
|
||||
36
|
||||
37 #define cr 0x0d
|
||||
38 #define lf 0x0a
|
||||
39 #define tab 0x09
|
||||
40 #define rub 0x7f
|
||||
41 #define bs 0x08
|
||||
42 #define space 0x20
|
||||
43
|
||||
44
|
||||
45 EXTERN warmboot(); /* External function definition */
|
||||
46
|
||||
47
|
||||
48 /******************/
|
||||
49 /* console status */
|
||||
50 /******************/
|
||||
51
|
||||
52 BOOLEAN constat()
|
||||
53 {
|
||||
54 BSETUP
|
||||
55
|
||||
56 return( GBL.kbchar ? TRUE : bconstat() );
|
||||
57 }
|
||||
58
|
||||
59 /********************/
|
||||
1File: CONBDOS.C Page 2
|
||||
60 /* check for ctrl/s */
|
||||
61 /* used internally */
|
||||
62 /********************/
|
||||
63 conbrk()
|
||||
64 {
|
||||
65 REG UBYTE ch;
|
||||
66 REG BOOLEAN stop;
|
||||
67 BSETUP
|
||||
68
|
||||
69 stop = FALSE;
|
||||
70 if ( bconstat() ) do
|
||||
71 {
|
||||
72 if ( (ch = bconin()) == ctrlc ) warmboot(1);
|
||||
73 if ( ch == ctrls ) stop = TRUE;
|
||||
74 else if (ch == ctrlq) stop = FALSE;
|
||||
75 else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
76 else /* Insert character in ring buffer */
|
||||
77 { /* */
|
||||
78 if(GBL.kbchar < TBUFSIZ) /* Room? */
|
||||
79 { /************************************/
|
||||
80 *GBL.insptr++ = ch; /* Yes, insert the character in buff*/
|
||||
81 GBL.kbchar++; /* Up count */
|
||||
82 } /************************************/
|
||||
83 } /* Note if no room, character is */
|
||||
84 /* Ignomiously discarded (!) */
|
||||
85 /************************************/
|
||||
86 } while (stop);
|
||||
87 }
|
||||
88
|
||||
89
|
||||
90 /******************/
|
||||
91 /* console output */
|
||||
92 /* used internally*/
|
||||
93 /******************/
|
||||
94
|
||||
95 conout(ch)
|
||||
96 REG UBYTE ch;
|
||||
97 {
|
||||
98 BSETUP
|
||||
99
|
||||
100 conbrk(); /* check for control-s break */
|
||||
101 bconout(ch); /* output character to console */
|
||||
102 if (GBL.lstecho) blstout(ch); /* if ctrl-p on, echo to list dev */
|
||||
103 if (ch >= ' ') GBL.column++; /* keep track of screen column */
|
||||
104 else if (ch == cr) GBL.column = 0;
|
||||
105 else if (ch == bs) GBL.column--;
|
||||
106 }
|
||||
107
|
||||
108
|
||||
109 /*************************************/
|
||||
110 /* console output with tab expansion */
|
||||
111 /*************************************/
|
||||
112
|
||||
113 tabout(ch)
|
||||
114 REG UBYTE ch; /* character to output to console */
|
||||
115 {
|
||||
116 BSETUP
|
||||
117
|
||||
118 if (ch == tab) do
|
||||
1File: CONBDOS.C Page 3
|
||||
119 conout(' ');
|
||||
120 while (GBL.column & 7);
|
||||
121 else conout(ch);
|
||||
122 }
|
||||
123
|
||||
124 /*******************************/
|
||||
125 /* console output with tab and */
|
||||
126 /* control character expansion */
|
||||
127 /*******************************/
|
||||
128
|
||||
129 cookdout(ch)
|
||||
130 REG UBYTE ch; /* character to output to console */
|
||||
131 {
|
||||
132 if (ch == tab) tabout(ch); /* if tab, expand it */
|
||||
133 else
|
||||
134 {
|
||||
135 if ( (UWORD)ch < (UWORD)' ' )
|
||||
136 {
|
||||
137 conout( '^' );
|
||||
138 ch |= 0x40;
|
||||
139 }
|
||||
140 conout(ch); /* output the character */
|
||||
141 }
|
||||
142 }
|
||||
143
|
||||
144
|
||||
145 /*****************/
|
||||
146 /* console input */
|
||||
147 /*****************/
|
||||
148
|
||||
149 UBYTE getch() /* Get char from buffer or bios */
|
||||
150 /* For internal use only */
|
||||
151 {
|
||||
152 REG UBYTE temp;
|
||||
153 BSETUP
|
||||
154
|
||||
155 if(GBL.kbchar)
|
||||
156 {
|
||||
157 temp = *GBL.remptr++; /* Fetch the character */
|
||||
158 GBL.kbchar--; /* Decrement the count */
|
||||
159 if(!GBL.kbchar) /* Gone to zero? */
|
||||
160 GBL.remptr = GBL.insptr = &(GBL.t_buff[0]);
|
||||
161 return(temp);
|
||||
162 }
|
||||
163 return( bconin() ); /* else get char from bios */
|
||||
164 }
|
||||
165
|
||||
166 UBYTE conin() /* BDOS console input function */
|
||||
167 {
|
||||
168 REG UBYTE ch;
|
||||
169 BSETUP
|
||||
170
|
||||
171 conout( ch = getch() );
|
||||
172 if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
173 return(ch);
|
||||
174 }
|
||||
175
|
||||
176 /******************
|
||||
177 * raw console i/o *
|
||||
1File: CONBDOS.C Page 4
|
||||
178 ******************/
|
||||
179
|
||||
180 UBYTE rawconio(parm) /* BDOS raw console I/O function */
|
||||
181
|
||||
182 REG UWORD parm;
|
||||
183 {
|
||||
184 BSETUP
|
||||
185
|
||||
186 if (parm == 0xff) return(getch());
|
||||
187 else if (parm == 0xfe) return(constat());
|
||||
188 else bconout(parm & 0xff);
|
||||
189 }
|
||||
190
|
||||
191
|
||||
192 /****************************************************/
|
||||
193 /* print line up to delimiter($) with tab expansion */
|
||||
194 /****************************************************/
|
||||
195
|
||||
196 prt_line(p)
|
||||
197 REG UBYTE *p;
|
||||
198 {
|
||||
199 BSETUP
|
||||
200
|
||||
201 while( *p != GBL.delim ) tabout( *p++ );
|
||||
202 }
|
||||
203
|
||||
204
|
||||
205 /**********************************************/
|
||||
206 /* read line with editing and bounds checking */
|
||||
207 /**********************************************/
|
||||
208
|
||||
209 /* Two subroutines first */
|
||||
210
|
||||
211 newline(startcol)
|
||||
212 REG UWORD startcol;
|
||||
213 {
|
||||
214 BSETUP
|
||||
215
|
||||
216 conout(cr); /* go to new line */
|
||||
217 conout(lf);
|
||||
218 while(startcol)
|
||||
219 {
|
||||
220 conout(' ');
|
||||
221 startcol -= 1; /* start output at starting column */
|
||||
222 }
|
||||
223 }
|
||||
224
|
||||
225
|
||||
226 backsp(bufp, col)
|
||||
227 /* backspace one character position */
|
||||
228 REG struct conbuf *bufp; /* pointer to console buffer */
|
||||
229 REG WORD col; /* starting console column */
|
||||
230 {
|
||||
231 REG UBYTE ch; /* current character */
|
||||
232 REG WORD i;
|
||||
233 REG UBYTE *p; /* character pointer */
|
||||
234 BSETUP
|
||||
235
|
||||
236 if (bufp->retlen) --(bufp->retlen);
|
||||
1File: CONBDOS.C Page 5
|
||||
237 /* if buffer non-empty, decrease it by 1 */
|
||||
238 i = UBWORD(bufp->retlen); /* get new character count */
|
||||
239 p = &(bufp->cbuf[0]); /* point to character buffer */
|
||||
240 while (i--) /* calculate column position */
|
||||
241 { /* across entire char buffer */
|
||||
242 ch = *p++; /* get next char */
|
||||
243 if ( ch == tab )
|
||||
244 {
|
||||
245 col += 8;
|
||||
246 col &= ~7; /* for tab, go to multiple of 8 */
|
||||
247 }
|
||||
248 else if ( (UWORD)ch < (UWORD)' ' ) col += 2;
|
||||
249 /* control chars put out 2 printable chars */
|
||||
250 else col += 1;
|
||||
251 }
|
||||
252 while (GBL.column > col)
|
||||
253 {
|
||||
254 conout(bs); /* backspace until we get to proper column */
|
||||
255 conout(' ');
|
||||
256 conout(bs);
|
||||
257 }
|
||||
258 }
|
||||
259
|
||||
260
|
||||
261 readline(p) /* BDOS function 10 */
|
||||
262 REG struct conbuf *p;
|
||||
263
|
||||
264 {
|
||||
265 REG UBYTE ch;
|
||||
266 REG UWORD i;
|
||||
267 REG UWORD j;
|
||||
268 REG UBYTE *q;
|
||||
269 UWORD stcol;
|
||||
270
|
||||
271 BSETUP
|
||||
272
|
||||
273 stcol = GBL.column; /* set up starting column */
|
||||
274 if (GBL.chainp != NULL) /* chain to program code */
|
||||
275 {
|
||||
276 i = UBWORD(*(GBL.chainp++));
|
||||
277 j = UBWORD(p->maxlen);
|
||||
278 if (j < i) i = j; /* don't overflow console buffer! */
|
||||
279 p->retlen = (UBYTE)i;
|
||||
280 q = p->cbuf;
|
||||
281 while (i)
|
||||
282 {
|
||||
283 cookdout( *q++ = *(GBL.chainp++) );
|
||||
284 i -= 1;
|
||||
285 }
|
||||
286 GBL.chainp = NULL;
|
||||
287 return;
|
||||
288 }
|
||||
289
|
||||
290 p->retlen = 0; /* start out with empty buffer */
|
||||
291 while ( UBWORD(p->retlen) < UBWORD(p->maxlen) )
|
||||
292 { /* main loop for read console buffer */
|
||||
293
|
||||
294 if ( ((ch=getch()) == ctrlc) && !(p->retlen) )
|
||||
295 {
|
||||
1File: CONBDOS.C Page 6
|
||||
296 cookdout(ctrlc);
|
||||
297 warmboot(1);
|
||||
298 }
|
||||
299
|
||||
300 else if ( (ch == cr) || (ch == lf) )
|
||||
301 { /* if cr or lf, exit */
|
||||
302 conout(cr);
|
||||
303 break;
|
||||
304 }
|
||||
305
|
||||
306 else if (ch == bs) backsp(p, stcol); /* backspace */
|
||||
307
|
||||
308 else if (ch == rub) /* delete character */
|
||||
309 {
|
||||
310 if (GBL.echodel)
|
||||
311 {
|
||||
312 if (p->retlen)
|
||||
313 {
|
||||
314 i = UBWORD(--(p->retlen));
|
||||
315 conout( p->cbuf[i] );
|
||||
316 }
|
||||
317 }
|
||||
318 else backsp(p, stcol);
|
||||
319 }
|
||||
320
|
||||
321 else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
322 /* control-p */
|
||||
323 else if (ch == ctrlx) /* control-x */
|
||||
324 do backsp(p,stcol); while (p->retlen);
|
||||
325
|
||||
326 else if (ch == ctrle) newline(stcol); /* control-e */
|
||||
327
|
||||
328 else if (ch == ctrlu) /* control-u */
|
||||
329 {
|
||||
330 conout('#');
|
||||
331 newline(stcol);
|
||||
332 p->retlen = 0;
|
||||
333 }
|
||||
334
|
||||
335 else if (ch == ctrlr) /* control-r */
|
||||
336 {
|
||||
337 conout('#');
|
||||
338 newline(stcol);
|
||||
339 for (i=0; i < UBWORD(p->retlen); i++)
|
||||
340 cookdout( p->cbuf[i] );
|
||||
341 }
|
||||
342
|
||||
343 else /* normal character */
|
||||
344 cookdout( p->cbuf[UBWORD((p->retlen)++)] = ch );
|
||||
345 }
|
||||
346 }
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
The following is a list of the modules that form the BDOS for the
|
||||
C language version of CP/M-68K:
|
||||
|
||||
SOURCE FILES
|
||||
|
||||
bdosif.s - assembly language interface, trap handler,
|
||||
BIOS caller, function 62 (set supervisor)
|
||||
|
||||
conbdos.c - BDOS functions 1 thru 11 (console functions)
|
||||
|
||||
bdosmisc.c - BDOS initialization, warmboot, error handler, set exception,
|
||||
(used for miscellaneous BDOS routines)
|
||||
|
||||
dskutil.c - bit map handlers, directory read & write, dirscan
|
||||
(miscellaneous disk handling utilities)
|
||||
|
||||
fileio.c - all file handling calls except read & write
|
||||
includes open, close, delete, rename, etc.
|
||||
|
||||
bdosrw.c - sequential and random read & write
|
||||
|
||||
bdosmain.c - the BDOS case statement, global variable declarations
|
||||
|
||||
iosys.c - packet I/O to BIOS interface
|
||||
|
||||
pgmld.s - program load (function 59)
|
||||
|
||||
exceptn.s - exception handler
|
||||
|
||||
|
||||
INCLUDE FILES
|
||||
|
||||
bdosinc.h - standard i/o stuff, universal declarations
|
||||
|
||||
bdosdef.h - BDOS data structure declarations
|
||||
|
||||
biosdef.h - procedure declarations to interface to BIOS
|
||||
|
||||
pktio.h - definition of data structure for packet I/O
|
||||
|
||||
BIN
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/cpmlib
Normal file
BIN
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/cpmlib
Normal file
Binary file not shown.
@@ -0,0 +1,31 @@
|
||||
e:vax BDOSDEF.H r
|
||||
e:vax BDOSIF.S r
|
||||
e:vax BDOSINC.H r
|
||||
e:vax BDOSMAIN.C r
|
||||
e:vax BDOSMISC.C r
|
||||
e:vax BDOSRW.C r
|
||||
e:vax BIOSDEF.H r
|
||||
e:vax CCP.C r
|
||||
e:vax CCPBDOS.S r
|
||||
e:vax CCPDEF.H r
|
||||
e:vax CCPIF.S r
|
||||
e:vax CCPLOAD.S r
|
||||
e:vax CONBDOS.C r
|
||||
e:vax CPMC.DOC r
|
||||
e:vax CPMLIB. r
|
||||
e:vax DOWN.SUB r
|
||||
e:vax DOWN2.SUB r
|
||||
e:vax DSKUTIL.C r
|
||||
e:vax EXCEPTN.S r
|
||||
e:vax FILEIO.C r
|
||||
e:vax FILETYPS.S r
|
||||
e:vax IOSYS.C r
|
||||
e:vax MAKE.SUB r
|
||||
e:vax PGMLD.S r
|
||||
e:vax PKTIO.H r
|
||||
e:vax REAR.SUB r
|
||||
e:vax SEND2.SUB r
|
||||
e:vax STACK.S r
|
||||
e:vax UP2.SUB r
|
||||
e:vax VMAKE.COM r
|
||||
e:vax VSEND.COM r
|
||||
@@ -0,0 +1,26 @@
|
||||
vax REAR.SUB r
|
||||
vax MAKE.SUB r
|
||||
vax BDOSDEF.H r
|
||||
vax BDOSIF.S r
|
||||
vax BDOSINC.H r
|
||||
vax BDOSMAIN.C r
|
||||
vax BDOSMISC.C r
|
||||
vax BDOSRW.C r
|
||||
vax BIOSDEF.H r
|
||||
vax CONBDOS.C r
|
||||
vax CPMC.DOC r
|
||||
vax DSKUTIL.C r
|
||||
vax EXCEPTN.S r
|
||||
vax FILEIO.C r
|
||||
vax IOSYS.C r
|
||||
vax PGMLD.S r
|
||||
vax PKTIO.H r
|
||||
vax CCP.C r
|
||||
vax CCPBDOS.S r
|
||||
vax CCPDEF.H r
|
||||
vax CCPIF.S r
|
||||
vax CCPLOAD.S r
|
||||
vax FILETYPS.S r
|
||||
vax STACK.S r
|
||||
vax SEND2.SUB r
|
||||
vax up2.sub r
|
||||
297
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/dskutil.c
Normal file
297
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/dskutil.c
Normal file
@@ -0,0 +1,297 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-68K BDOS Disk Utilities Module *
|
||||
* *
|
||||
* This module contains the miscellaneous utilities *
|
||||
* for manipulating the disk in CP/M-68K. Included are: *
|
||||
* *
|
||||
* dirscan() - general purpose dir scanning *
|
||||
* setaloc() - set bit in allocation vector *
|
||||
* clraloc() - clear bit in allocation vector *
|
||||
* getaloc() - get free allocation block *
|
||||
* dchksum() - directory checksum calculator *
|
||||
* dir_rd() - read directory sector *
|
||||
* dir_wr() - write directory sector *
|
||||
* rdwrt() - read/write disk sector *
|
||||
* *
|
||||
* *
|
||||
* Configured for Alcyon C on the VAX *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "bdosinc.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "pktio.h" /* Packet I/O definitions */
|
||||
|
||||
|
||||
/* declare external functions and variables */
|
||||
EXTERN UWORD do_phio(); /* external physical disk I/O routine */
|
||||
EXTERN UWORD error(); /* external error routine */
|
||||
|
||||
EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
EXTERN UWORD crit_dsk; /* critical disk vector */
|
||||
|
||||
|
||||
/**********************
|
||||
* read/write routine *
|
||||
**********************/
|
||||
|
||||
UWORD rdwrt(secnum, dma, parm)
|
||||
/* General disk sector read/write routine */
|
||||
/* It simply sets up a I/O packet and sends it to do_phio */
|
||||
|
||||
LONG secnum; /* logical sector number to read/write */
|
||||
UBYTE *dma; /* dma address */
|
||||
REG WORD parm; /* 0 for read, write parm + 1 for write */
|
||||
|
||||
{
|
||||
struct iopb rwpkt;
|
||||
BSETUP
|
||||
|
||||
rwpkt.devnum = GBL.curdsk; /* disk to read/write */
|
||||
if (parm)
|
||||
{
|
||||
rwpkt.iofcn = (BYTE)write; /* if parm non-zero, we're doing a write */
|
||||
rwpkt.ioflags = (BYTE)(parm-1); /* pass write parm */
|
||||
if ( ro_dsk & (1 << (rwpkt.devnum)) ) error(4);
|
||||
/* don't write on read-only disk */
|
||||
}
|
||||
else
|
||||
{
|
||||
rwpkt.iofcn = (BYTE)read;
|
||||
rwpkt.ioflags = (BYTE)0;
|
||||
}
|
||||
rwpkt.devadr = secnum; /* sector number */
|
||||
rwpkt.xferadr = dma; /* dma address */
|
||||
|
||||
/* parameters that are currently not used by do_phio
|
||||
rwpkt.devtype = disk;
|
||||
rwpkt.xferlen = 1;
|
||||
*/
|
||||
rwpkt.infop = GBL.dphp; /* pass ptr to dph */
|
||||
while ( do_phio(&rwpkt) )
|
||||
if ( error( parm ? 1 : 0 ) ) break;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
* directory read routine *
|
||||
***************************/
|
||||
|
||||
UWORD dir_rd(secnum)
|
||||
|
||||
WORD secnum;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
return( rdwrt((LONG)secnum, GBL.dirbufp, 0) );
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* directory write routine *
|
||||
****************************/
|
||||
|
||||
UWORD dir_wr(secnum)
|
||||
|
||||
REG WORD secnum;
|
||||
{
|
||||
REG UWORD rtn;
|
||||
BSETUP
|
||||
|
||||
rtn = rdwrt( (LONG)secnum, GBL.dirbufp, 2);
|
||||
if ( secnum < (GBL.parmp)->cks )
|
||||
*((GBL.dphp)->csv + secnum) = dchksum();
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
* directory checksum routine *
|
||||
*******************************/
|
||||
|
||||
UBYTE dchksum()
|
||||
/* Compute checksum over one directory sector */
|
||||
/* Note that this implementation is dependant on the representation */
|
||||
/* of a LONG and is therefore not very portable. But it's fast */
|
||||
{
|
||||
REG LONG *p; /* local temp variables */
|
||||
REG LONG lsum;
|
||||
REG WORD i;
|
||||
|
||||
BSETUP
|
||||
|
||||
p = GBL.dirbufp; /* point to directory buffer */
|
||||
lsum = 0;
|
||||
i = SECLEN / (sizeof lsum);
|
||||
do
|
||||
{
|
||||
lsum += *p++; /* add next 4 bytes of directory */
|
||||
i -= 1;
|
||||
} while (i);
|
||||
lsum += (lsum >> 16);
|
||||
lsum += (lsum >> 8);
|
||||
return( (UBYTE)(lsum & 0xff) );
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* dirscan entry point *
|
||||
************************/
|
||||
|
||||
UWORD dirscan(funcp, fcbp, parms)
|
||||
|
||||
BOOLEAN (*funcp)(); /* funcp is a pointer to a Boolean function */
|
||||
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
|
||||
REG UWORD parms; /* parms is 16 bit set of bit parameters */
|
||||
|
||||
/* Parms & 1 = 0 to start at beginning of dir, 1 to continue from last */
|
||||
/* Parms & 2 = 0 to stop when *funcp is true, 1 to go until end */
|
||||
/* Parms & 4 = 0 to check the dir checksum, 1 to store new checksum */
|
||||
/* Parms & 8 = 0 to stop at hiwater, 1 to go until end of directory */
|
||||
|
||||
#define continue 1
|
||||
#define full 2
|
||||
#define initckv 4
|
||||
#define pasthw 8
|
||||
|
||||
{
|
||||
REG UWORD i; /* loop counter */
|
||||
REG struct dpb *dparmp; /* pointer to disk parm block */
|
||||
REG UWORD dirsec; /* sector number we're working on */
|
||||
REG UWORD rtn; /* return value */
|
||||
REG UBYTE *p; /* scratch pointer */
|
||||
REG UWORD bitvec; /* disk nmbr represented as a vector */
|
||||
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp; /* init ptr to dpb */
|
||||
rtn = 255; /* assume it doesn't work */
|
||||
|
||||
i = ( (parms & continue) ? GBL.srchpos + 1 : 0 );
|
||||
while ( (parms & pasthw) || (i <= ((GBL.dphp)->hiwater + 1)) )
|
||||
{ /* main directory scanning loop */
|
||||
if ( i > dparmp->drm ) break;
|
||||
if ( ! (i & 3) )
|
||||
{ /* inside loop happens when we need to
|
||||
read another directory sector */
|
||||
retry: dirsec = i >> 2;
|
||||
dir_rd(dirsec); /* read the directory sector */
|
||||
if ( dirsec < (dparmp->cks) ) /* checksumming on this sector? */
|
||||
{
|
||||
p = ((GBL.dphp)->csv) + dirsec;
|
||||
/* point to checksum vector byte */
|
||||
if (parms & initckv) *p = dchksum();
|
||||
else if (*p != dchksum())
|
||||
{ /* checksum error! */
|
||||
(GBL.dphp)->hiwater = dparmp->drm; /* reset hi water */
|
||||
bitvec = 1 << (GBL.curdsk);
|
||||
if (crit_dsk & bitvec) /* if disk in critical mode */
|
||||
ro_dsk |= bitvec; /* then set it to r/o */
|
||||
else
|
||||
{
|
||||
log_dsk &= ~bitvec; /* else log it off */
|
||||
seldsk(GBL.curdsk); /* and re-select it */
|
||||
goto retry; /* and re-do current op */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GBL.srchpos = i;
|
||||
if ( (*funcp)(fcbp, (GBL.dirbufp) + (i&3), i) )
|
||||
/* call function with parms of (1) fcb ptr,
|
||||
(2) pointer to directory entry, and
|
||||
(3) directory index */
|
||||
{
|
||||
if (parms & full) rtn = 0; /* found a match, but keep going */
|
||||
else return(i & 3); /* return directory code */
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/****************************************
|
||||
* Routines to manage allocation vector *
|
||||
* setaloc() *
|
||||
* clraloc() *
|
||||
* getaloc() *
|
||||
****************************************/
|
||||
|
||||
setaloc(bitnum)
|
||||
/* Set bit in allocation vector */
|
||||
REG UWORD bitnum;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
if (bitnum >= 0 && bitnum <= (GBL.parmp)->dsm)
|
||||
*((GBL.dphp)->alv + (bitnum>>3)) |= 0x80 >> (bitnum & 7);
|
||||
}
|
||||
|
||||
|
||||
clraloc(bitnum)
|
||||
/* Clear bit in allocation vector */
|
||||
REG UWORD bitnum;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
if (bitnum > 0 && bitnum <= (GBL.parmp)->dsm)
|
||||
*((GBL.dphp)->alv + (bitnum>>3)) &= ~(0x80 >> (bitnum & 7));
|
||||
}
|
||||
|
||||
|
||||
UWORD chkaloc(i)
|
||||
/* Check bit i in allocation vector */
|
||||
/* Return non-zero if block free, else return zero */
|
||||
REG UWORD i;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
return( ~(*( (GBL.dphp)->alv + (i >> 3) )) & (0x80 >> (i&7)) );
|
||||
}
|
||||
|
||||
|
||||
UWORD getaloc(leftblk)
|
||||
/* Get a free block in the file system and set the bit in allocation vector */
|
||||
/* It is passed the block number of the last block allocated to the file */
|
||||
/* It tries to allocate the block closest to the block that was passed */
|
||||
REG UWORD leftblk;
|
||||
{
|
||||
REG UWORD blk; /* block number to allocate */
|
||||
REG UWORD rtblk; /* high block number to try */
|
||||
REG UWORD diskmax; /* # bits in alv - 1 */
|
||||
|
||||
BSETUP
|
||||
LOCK /* need to lock the file system while messing
|
||||
with the allocation vector */
|
||||
|
||||
diskmax = (GBL.parmp)->dsm;
|
||||
/* get disk max field from dpb */
|
||||
rtblk = leftblk;
|
||||
blk = ~0; /* -1 returned if no free block found */
|
||||
while (leftblk || rtblk < diskmax)
|
||||
{
|
||||
if (leftblk)
|
||||
if (chkaloc(--leftblk))
|
||||
{
|
||||
blk = leftblk;
|
||||
break;
|
||||
}
|
||||
if (rtblk < diskmax)
|
||||
if (chkaloc(++rtblk))
|
||||
{
|
||||
blk = rtblk;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (blk != ~0) setaloc(blk);
|
||||
UNLOCK
|
||||
return(blk);
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
1File: DSKUTIL.C Page 1
|
||||
1
|
||||
2 /****************************************************************
|
||||
3 * *
|
||||
4 * CP/M-68K BDOS Disk Utilities Module *
|
||||
5 * *
|
||||
6 * This module contains the miscellaneous utilities *
|
||||
7 * for manipulating the disk in CP/M-68K. Included are: *
|
||||
8 * *
|
||||
9 * dirscan() - general purpose dir scanning *
|
||||
10 * setaloc() - set bit in allocation vector *
|
||||
11 * clraloc() - clear bit in allocation vector *
|
||||
12 * getaloc() - get free allocation block *
|
||||
13 * dchksum() - directory checksum calculator *
|
||||
14 * dir_rd() - read directory sector *
|
||||
15 * dir_wr() - write directory sector *
|
||||
16 * rdwrt() - read/write disk sector *
|
||||
17 * *
|
||||
18 * *
|
||||
19 * Configured for Alcyon C on the VAX *
|
||||
20 * *
|
||||
21 ****************************************************************/
|
||||
22
|
||||
23 #include "bdosinc.h" /* Standard I/O declarations */
|
||||
24
|
||||
25 #include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
26
|
||||
27 #include "pktio.h" /* Packet I/O definitions */
|
||||
28
|
||||
29
|
||||
30 /* declare external functions and variables */
|
||||
31 EXTERN UWORD do_phio(); /* external physical disk I/O routine */
|
||||
32 EXTERN UWORD error(); /* external error routine */
|
||||
33
|
||||
34 EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
35 EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
36 EXTERN UWORD crit_dsk; /* critical disk vector */
|
||||
37
|
||||
38
|
||||
39 /**********************
|
||||
40 * read/write routine *
|
||||
41 **********************/
|
||||
42
|
||||
43 UWORD rdwrt(secnum, dma, parm)
|
||||
44 /* General disk sector read/write routine */
|
||||
45 /* It simply sets up a I/O packet and sends it to do_phio */
|
||||
46
|
||||
47 LONG secnum; /* logical sector number to read/write */
|
||||
48 UBYTE *dma; /* dma address */
|
||||
49 REG WORD parm; /* 0 for read, write parm + 1 for write */
|
||||
50
|
||||
51 {
|
||||
52 struct iopb rwpkt;
|
||||
53 BSETUP
|
||||
54
|
||||
55 rwpkt.devnum = GBL.curdsk; /* disk to read/write */
|
||||
56 if (parm)
|
||||
57 {
|
||||
58 rwpkt.iofcn = (BYTE)write; /* if parm non-zero, we're doing a write */
|
||||
59 rwpkt.ioflags = (BYTE)(parm-1); /* pass write parm */
|
||||
1File: DSKUTIL.C Page 2
|
||||
60 if ( ro_dsk & (1 << (rwpkt.devnum)) ) error(4);
|
||||
61 /* don't write on read-only disk */
|
||||
62 }
|
||||
63 else
|
||||
64 {
|
||||
65 rwpkt.iofcn = (BYTE)read;
|
||||
66 rwpkt.ioflags = (BYTE)0;
|
||||
67 }
|
||||
68 rwpkt.devadr = secnum; /* sector number */
|
||||
69 rwpkt.xferadr = dma; /* dma address */
|
||||
70
|
||||
71 /* parameters that are currently not used by do_phio
|
||||
72 rwpkt.devtype = disk;
|
||||
73 rwpkt.xferlen = 1;
|
||||
74 */
|
||||
75 rwpkt.infop = GBL.dphp; /* pass ptr to dph */
|
||||
76 while ( do_phio(&rwpkt) )
|
||||
77 if ( error( parm ? 1 : 0 ) ) break;
|
||||
78 return(0);
|
||||
79 }
|
||||
80
|
||||
81
|
||||
82 /***************************
|
||||
83 * directory read routine *
|
||||
84 ***************************/
|
||||
85
|
||||
86 UWORD dir_rd(secnum)
|
||||
87
|
||||
88 WORD secnum;
|
||||
89 {
|
||||
90 BSETUP
|
||||
91
|
||||
92 return( rdwrt((LONG)secnum, GBL.dirbufp, 0) );
|
||||
93 }
|
||||
94
|
||||
95
|
||||
96 /****************************
|
||||
97 * directory write routine *
|
||||
98 ****************************/
|
||||
99
|
||||
100 UWORD dir_wr(secnum)
|
||||
101
|
||||
102 REG WORD secnum;
|
||||
103 {
|
||||
104 REG UWORD rtn;
|
||||
105 BSETUP
|
||||
106
|
||||
107 rtn = rdwrt( (LONG)secnum, GBL.dirbufp, 2);
|
||||
108 if ( secnum < (GBL.parmp)->cks )
|
||||
109 *((GBL.dphp)->csv + secnum) = dchksum();
|
||||
110 return(rtn);
|
||||
111 }
|
||||
112
|
||||
113
|
||||
114 /*******************************
|
||||
115 * directory checksum routine *
|
||||
116 *******************************/
|
||||
117
|
||||
118 UBYTE dchksum()
|
||||
1File: DSKUTIL.C Page 3
|
||||
119 /* Compute checksum over one directory sector */
|
||||
120 /* Note that this implementation is dependant on the representation */
|
||||
121 /* of a LONG and is therefore not very portable. But it's fast */
|
||||
122 {
|
||||
123 REG LONG *p; /* local temp variables */
|
||||
124 REG LONG lsum;
|
||||
125 REG WORD i;
|
||||
126
|
||||
127 BSETUP
|
||||
128
|
||||
129 p = GBL.dirbufp; /* point to directory buffer */
|
||||
130 lsum = 0;
|
||||
131 i = SECLEN / (sizeof lsum);
|
||||
132 do
|
||||
133 {
|
||||
134 lsum += *p++; /* add next 4 bytes of directory */
|
||||
135 i -= 1;
|
||||
136 } while (i);
|
||||
137 lsum += (lsum >> 16);
|
||||
138 lsum += (lsum >> 8);
|
||||
139 return( (UBYTE)(lsum & 0xff) );
|
||||
140 }
|
||||
141
|
||||
142
|
||||
143 /************************
|
||||
144 * dirscan entry point *
|
||||
145 ************************/
|
||||
146
|
||||
147 UWORD dirscan(funcp, fcbp, parms)
|
||||
148
|
||||
149 BOOLEAN (*funcp)(); /* funcp is a pointer to a Boolean function */
|
||||
150 REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
|
||||
151 REG UWORD parms; /* parms is 16 bit set of bit parameters */
|
||||
152
|
||||
153 /* Parms & 1 = 0 to start at beginning of dir, 1 to continue from last */
|
||||
154 /* Parms & 2 = 0 to stop when *funcp is true, 1 to go until end */
|
||||
155 /* Parms & 4 = 0 to check the dir checksum, 1 to store new checksum */
|
||||
156 /* Parms & 8 = 0 to stop at hiwater, 1 to go until end of directory */
|
||||
157
|
||||
158 #define continue 1
|
||||
159 #define full 2
|
||||
160 #define initckv 4
|
||||
161 #define pasthw 8
|
||||
162
|
||||
163 {
|
||||
164 REG UWORD i; /* loop counter */
|
||||
165 REG struct dpb *dparmp; /* pointer to disk parm block */
|
||||
166 REG UWORD dirsec; /* sector number we're working on */
|
||||
167 REG UWORD rtn; /* return value */
|
||||
168 REG UBYTE *p; /* scratch pointer */
|
||||
169 REG UWORD bitvec; /* disk nmbr represented as a vector */
|
||||
170
|
||||
171 BSETUP
|
||||
172
|
||||
173 dparmp = GBL.parmp; /* init ptr to dpb */
|
||||
174 rtn = 255; /* assume it doesn't work */
|
||||
175
|
||||
176 i = ( (parms & continue) ? GBL.srchpos + 1 : 0 );
|
||||
177 while ( (parms & pasthw) || (i <= ((GBL.dphp)->hiwater + 1)) )
|
||||
1File: DSKUTIL.C Page 4
|
||||
178 { /* main directory scanning loop */
|
||||
179 if ( i > dparmp->drm ) break;
|
||||
180 if ( ! (i & 3) )
|
||||
181 { /* inside loop happens when we need to
|
||||
182 read another directory sector */
|
||||
183 retry: dirsec = i >> 2;
|
||||
184 dir_rd(dirsec); /* read the directory sector */
|
||||
185 if ( dirsec < (dparmp->cks) ) /* checksumming on this sector? */
|
||||
186 {
|
||||
187 p = ((GBL.dphp)->csv) + dirsec;
|
||||
188 /* point to checksum vector byte */
|
||||
189 if (parms & initckv) *p = dchksum();
|
||||
190 else if (*p != dchksum())
|
||||
191 { /* checksum error! */
|
||||
192 (GBL.dphp)->hiwater = dparmp->drm; /* reset hi water */
|
||||
193 bitvec = 1 << (GBL.curdsk);
|
||||
194 if (crit_dsk & bitvec) /* if disk in critical mode */
|
||||
195 ro_dsk |= bitvec; /* then set it to r/o */
|
||||
196 else
|
||||
197 {
|
||||
198 log_dsk &= ~bitvec; /* else log it off */
|
||||
199 seldsk(GBL.curdsk); /* and re-select it */
|
||||
200 goto retry; /* and re-do current op */
|
||||
201 }
|
||||
202 }
|
||||
203 }
|
||||
204 }
|
||||
205
|
||||
206 GBL.srchpos = i;
|
||||
207 if ( (*funcp)(fcbp, (GBL.dirbufp) + (i&3), i) )
|
||||
208 /* call function with parms of (1) fcb ptr,
|
||||
209 (2) pointer to directory entry, and
|
||||
210 (3) directory index */
|
||||
211 {
|
||||
212 if (parms & full) rtn = 0; /* found a match, but keep going */
|
||||
213 else return(i & 3); /* return directory code */
|
||||
214 }
|
||||
215 i += 1;
|
||||
216 }
|
||||
217 return(rtn);
|
||||
218 }
|
||||
219
|
||||
220
|
||||
221 /****************************************
|
||||
222 * Routines to manage allocation vector *
|
||||
223 * setaloc() *
|
||||
224 * clraloc() *
|
||||
225 * getaloc() *
|
||||
226 ****************************************/
|
||||
227
|
||||
228 setaloc(bitnum)
|
||||
229 /* Set bit in allocation vector */
|
||||
230 REG UWORD bitnum;
|
||||
231 {
|
||||
232 BSETUP
|
||||
233
|
||||
234 if (bitnum >= 0 && bitnum <= (GBL.parmp)->dsm)
|
||||
235 *((GBL.dphp)->alv + (bitnum>>3)) |= 0x80 >> (bitnum & 7);
|
||||
236 }
|
||||
1File: DSKUTIL.C Page 5
|
||||
237
|
||||
238
|
||||
239 clraloc(bitnum)
|
||||
240 /* Clear bit in allocation vector */
|
||||
241 REG UWORD bitnum;
|
||||
242 {
|
||||
243 BSETUP
|
||||
244
|
||||
245 if (bitnum > 0 && bitnum <= (GBL.parmp)->dsm)
|
||||
246 *((GBL.dphp)->alv + (bitnum>>3)) &= ~(0x80 >> (bitnum & 7));
|
||||
247 }
|
||||
248
|
||||
249
|
||||
250 UWORD chkaloc(i)
|
||||
251 /* Check bit i in allocation vector */
|
||||
252 /* Return non-zero if block free, else return zero */
|
||||
253 REG UWORD i;
|
||||
254 {
|
||||
255 BSETUP
|
||||
256
|
||||
257 return( ~(*( (GBL.dphp)->alv + (i >> 3) )) & (0x80 >> (i&7)) );
|
||||
258 }
|
||||
259
|
||||
260
|
||||
261 UWORD getaloc(leftblk)
|
||||
262 /* Get a free block in the file system and set the bit in allocation vector */
|
||||
263 /* It is passed the block number of the last block allocated to the file */
|
||||
264 /* It tries to allocate the block closest to the block that was passed */
|
||||
265 REG UWORD leftblk;
|
||||
266 {
|
||||
267 REG UWORD blk; /* block number to allocate */
|
||||
268 REG UWORD rtblk; /* high block number to try */
|
||||
269 REG UWORD diskmax; /* # bits in alv - 1 */
|
||||
270
|
||||
271 BSETUP
|
||||
272 LOCK /* need to lock the file system while messing
|
||||
273 with the allocation vector */
|
||||
274
|
||||
275 diskmax = (GBL.parmp)->dsm;
|
||||
276 /* get disk max field from dpb */
|
||||
277 rtblk = leftblk;
|
||||
278 blk = ~0; /* -1 returned if no free block found */
|
||||
279 while (leftblk || rtblk < diskmax)
|
||||
280 {
|
||||
281 if (leftblk)
|
||||
282 if (chkaloc(--leftblk))
|
||||
283 {
|
||||
284 blk = leftblk;
|
||||
285 break;
|
||||
286 }
|
||||
287 if (rtblk < diskmax)
|
||||
288 if (chkaloc(++rtblk))
|
||||
289 {
|
||||
290 blk = rtblk;
|
||||
291 break;
|
||||
292 }
|
||||
293 }
|
||||
294 if (blk != ~0) setaloc(blk);
|
||||
295 UNLOCK
|
||||
1File: DSKUTIL.C Page 6
|
||||
296 return(blk);
|
||||
297 }
|
||||
@@ -0,0 +1,328 @@
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 1
|
||||
Source File: exceptn.s
|
||||
|
||||
1
|
||||
2 *************************************************
|
||||
3 * *
|
||||
4 * CP/M-68k Basic Disk Operating System *
|
||||
5 * Exception Handling Module *
|
||||
6 * *
|
||||
7 * Version 0.0 -- July 21, 1982 *
|
||||
8 * Version 0.1 -- July 25, 1982 *
|
||||
9 * Version 0.2 -- October 6, 1982 *
|
||||
10 * Version 0.3 -- December 21, 1982 *
|
||||
11 * *
|
||||
12 *************************************************
|
||||
13
|
||||
14
|
||||
15 .globl _initexc
|
||||
16 .globl _tpa_lp
|
||||
17 .globl _tpa_hp
|
||||
18
|
||||
19 bgetseg = 18
|
||||
20 bsetexc = 22
|
||||
21 buserr = 2
|
||||
22 spurious = 24
|
||||
23 trap0 = 32
|
||||
24 trap2 = 34
|
||||
25 trap3 = 35
|
||||
26 endvec = 48
|
||||
27
|
||||
28 _initexc:
|
||||
29 * Initialize Exception Vector Handlers
|
||||
30 * It has 1 passed parameter: the address of the exception vector array
|
||||
31 00000000 7016 move #bsetexc,d0
|
||||
32 00000002 7202 moveq #2,d1
|
||||
33 00000004 243C00000072 move.l #exchndl,d2
|
||||
34 init1:
|
||||
35 0000000A 48E7E000 movem.l d0-d2,-(sp)
|
||||
36 0000000E 4E43 trap #3 * BIOS call to set exception vector
|
||||
37 00000010 4CDF0007 movem.l (sp)+,d0-d2
|
||||
38 00000014 5241 init2: addq #1,d1
|
||||
39 00000016 5882 add.l #4,d2
|
||||
40 00000018 0C410018 cmpi #spurious,d1
|
||||
41 0000001C 6602 bne init3
|
||||
42 0000001E 7220 move #trap0,d1
|
||||
43 00000020 0C410022 init3: cmpi #trap2,d1
|
||||
44 00000024 67EE beq init2 * don't init trap 2 or trap 3
|
||||
45 00000026 0C410023 cmpi #trap3,d1
|
||||
46 0000002A 67E8 beq init2
|
||||
47 0000002C 0C410030 cmpi #endvec,d1
|
||||
48 00000030 6DD8 blt init1
|
||||
49 * initialize the exception vector array
|
||||
50
|
||||
51 00000032 7012 moveq #bgetseg,d0
|
||||
52 00000034 4E43 trap #3 * get the original TPA limits
|
||||
53 00000036 2040 movea.l d0,a0
|
||||
54 00000038 4A58 tst.w (a0)+
|
||||
55 0000003A 2218 move.l (a0)+,d1 * d1 = original low TPA limit
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 2
|
||||
Source File: exceptn.s
|
||||
|
||||
56 0000003C 2401 move.l d1,d2
|
||||
57 0000003E D490 add.l (a0),d2 * d2 = original high TPA limit
|
||||
58 00000040 263900000000 move.l _tpa_lp,d3 * d3 = new low TPA limit
|
||||
59 00000046 283900000000 move.l _tpa_hp,d4 * d4 = new high TPA limit
|
||||
60 0000004C 7011 move #17,d0
|
||||
61 0000004E 206F0004 movea.l 4(sp),a0
|
||||
62 00000052 23C800000000 move.l a0,evec_adr * save exception vector address
|
||||
63 init4:
|
||||
64 00000058 B290 cmp.l (a0),d1
|
||||
65 0000005A 620C bhi do_init * if old exception outside orig TPA, clear it
|
||||
66 0000005C B490 cmp.l (a0),d2
|
||||
67 0000005E 6308 bls do_init
|
||||
68 * current exception array entry is in original TPA
|
||||
69 00000060 B690 cmp.l (a0),d3
|
||||
70 00000062 6206 bhi dontinit * if old exception in old TPA but outside new
|
||||
71 00000064 B890 cmp.l (a0),d4 * TPA, don't clear it
|
||||
72 00000066 6302 bls dontinit
|
||||
73 do_init:
|
||||
74 00000068 4290 clr.l (a0)
|
||||
75 dontinit:
|
||||
76 0000006A 4A98 tst.l (a0)+
|
||||
77 0000006C 51C8FFEA dbf d0,init4
|
||||
78 00000070 4E75 rts
|
||||
79
|
||||
80 exchndl:
|
||||
81 00000072 61000056 bsr.w except
|
||||
82 excrtn0:
|
||||
83 00000076 61000052 bsr.w except
|
||||
84 0000007A 6100004E bsr.w except
|
||||
85 0000007E 6100004A bsr.w except
|
||||
86 00000082 61000046 bsr.w except
|
||||
87 00000086 61000042 bsr.w except
|
||||
88 0000008A 613E bsr.w except
|
||||
89 0000008C 613C bsr.w except
|
||||
90 0000008E 613A bsr.w except
|
||||
91 00000090 6138 bsr.w except
|
||||
92 00000092 6136 bsr.w except
|
||||
93 00000094 6134 bsr.w except
|
||||
94 00000096 6132 bsr.w except
|
||||
95 00000098 6130 bsr.w except
|
||||
96 0000009A 612E bsr.w except
|
||||
97 0000009C 612C bsr.w except
|
||||
98 0000009E 612A bsr.w except
|
||||
99 000000A0 6128 bsr.w except
|
||||
100 000000A2 6126 bsr.w except
|
||||
101 000000A4 6124 bsr.w except
|
||||
102 000000A6 6122 bsr.w except
|
||||
103 000000A8 6120 bsr.w except
|
||||
104 000000AA 611E bsr.w except
|
||||
105 000000AC 611C bsr.w except
|
||||
106 000000AE 611A bsr.w except
|
||||
107 000000B0 6118 bsr.w except
|
||||
108 000000B2 6116 bsr.w except
|
||||
109 000000B4 6114 bsr.w except
|
||||
110 000000B6 6112 bsr.w except
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 3
|
||||
Source File: exceptn.s
|
||||
|
||||
111 000000B8 6110 bsr.w except
|
||||
112 000000BA 610E bsr.w except
|
||||
113 000000BC 610C bsr.w except
|
||||
114 000000BE 610A bsr.w except
|
||||
115 000000C0 6108 bsr.w except
|
||||
116 000000C2 6106 bsr.w except
|
||||
117 000000C4 6104 bsr.w except
|
||||
118 000000C6 6102 bsr.w except
|
||||
119 000000C8 4E71 bsr.w except
|
||||
120
|
||||
121
|
||||
122 except:
|
||||
123 000000CA 4267 clr.w -(sp)
|
||||
124 000000CC 48E78080 movem.l a0/d0,-(sp) * 10 words now on stack in following order:
|
||||
125 * _______________________________
|
||||
126 * |____________D0.L_______________|
|
||||
127 * |____________A0.L_______________|
|
||||
128 * |____0000______|________________
|
||||
129 * |_______Handler Return__________|
|
||||
130 * If bus error, extra 2 longs are here
|
||||
131 * ______________
|
||||
132 * |__Status Reg__|________________
|
||||
133 * |_____Exception Return__________|
|
||||
134
|
||||
135 000000D0 202F000A move.l 10(sp),d0 * get return address from above array
|
||||
136 000000D4 90BC00000076 sub.l #excrtn0,d0 * d0 now has 4 * (encoded excptn nmbr), where
|
||||
137 * encoded excptn nmbr is in [0..21,22..37]
|
||||
138 * representing [2..23,32..47]
|
||||
139 000000DA 0C400024 cmpi #36,d0 * if d0/4 is in [0..9,22..29] then
|
||||
140 000000DE 6F10 ble chkredir * the exception may be redirected
|
||||
141 000000E0 0C400058 cmpi #88,d0
|
||||
142 000000E4 6D20 blt dfltexc
|
||||
143 000000E6 0C400074 cmpi #116,d0
|
||||
144 000000EA 6E1A bgt dfltexc
|
||||
145 * in range of redirected exceptions
|
||||
146 000000EC 04400030 subi #48,d0 * subtract 4*12 to normalize [0..9,22..29]
|
||||
147 * into [0..9,10..17]
|
||||
148 chkredir:
|
||||
149 000000F0 207900000000 movea.l evec_adr,a0
|
||||
150 000000F6 D0C0 adda d0,a0 * index into exception vector array
|
||||
151 000000F8 4A90 tst.l (a0) * if 00000000, then not redirected
|
||||
152 000000FA 6658 bne usrexc
|
||||
153 * not redirected, do default handler
|
||||
154 000000FC 0C400028 cmpi #40,d0
|
||||
155 00000100 6D04 blt dfltexc
|
||||
156 00000102 06400030 addi #48,d0 * add 4*12 that was sub'd above
|
||||
157 dfltexc:
|
||||
158 00000106 DEFC000E adda #14,sp * throw away 7 words that we added to stack
|
||||
159 0000010A E440 asr #2,d0 * divide d0 by 4
|
||||
160 * now d0 is in [0..21,22..37]
|
||||
161 * to represent [2..23,32..47]
|
||||
162 0000010C 0C400002 cmpi #2,d0 * bus or address error?
|
||||
163 00000110 6C04 bge nobusexc
|
||||
164 00000112 4CDF0300 movem.l (sp)+,a0-a1 * if yes, throw away 4 words from stack
|
||||
165 nobusexc:
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 4
|
||||
Source File: exceptn.s
|
||||
|
||||
166 00000116 4A5F tst.w (sp)+ * throw away stacked SR
|
||||
167 00000118 5440 addi #2,d0
|
||||
168 0000011A 0C400017 cmpi #23,d0 * get back real excptn nmbr in [2..23,32..47]
|
||||
169 0000011E 6F02 ble lowexc
|
||||
170 00000120 5040 addi #8,d0
|
||||
171 00000122 3F00 lowexc: move d0,-(sp) * save excptn nmbr
|
||||
172 00000124 41F900000000 lea excmsg1,a0
|
||||
173 0000012A 6100009A bsr print * print default exception message
|
||||
174 0000012E 301F move (sp)+,d0
|
||||
175 00000130 610000B2 bsr prtbyte
|
||||
176 00000134 41F90000000F lea excmsg2, a0
|
||||
177 0000013A 6100008A bsr print
|
||||
178 0000013E 201F move.l (sp)+,d0
|
||||
179 00000140 61000092 bsr prtlong
|
||||
180 00000144 41F900000022 lea excmsg3, a0
|
||||
181 0000014A 6100007A bsr print
|
||||
182 0000014E 4280 clr.l d0
|
||||
183 00000150 4E42 trap #2 * warm boot
|
||||
184 00000152 4E73 rte
|
||||
185
|
||||
186 usrexc:
|
||||
187 * Call user exception handler
|
||||
188 * make sure exception information is on his stack
|
||||
189 00000154 2F50000A move.l (a0),10(sp) * put user handler address on our stack
|
||||
190 00000158 4E68 move.l usp,a0 * user stack pointer to a0
|
||||
191 0000015A 0C400008 cmpi #8,d0 * address or bus error?
|
||||
192 0000015E 6D24 blt addrexc * if yes, skip
|
||||
193 00000160 082F000D000E btst #13,14(sp) * exception occured in user state?
|
||||
194 00000166 664A bne supstat1 * if no, go to supervisor handler
|
||||
195 00000168 212F0010 move.l 16(sp),-(a0) * put exception return on user stack
|
||||
196 0000016C 312F000E move.w 14(sp),-(a0) * put SR on user stack
|
||||
197 00000170 4E60 move.l a0,usp * update user stack pointer
|
||||
198 00000172 4CDF0101 movem.l (sp)+,a0/d0 * restore regs
|
||||
199 00000176 2F6F00020008 move.l 2(sp),8(sp) * move address of user handler to excptn rtn
|
||||
200 0000017C 5C4F addq #6,sp * clear junk from stack
|
||||
201 0000017E 02577FFF andi #$7fff,(sp) * clear trace bit
|
||||
202 00000182 4E73 rte * go to user handler
|
||||
203 addrexc:
|
||||
204 00000184 082F000D0016 btst #13,22(sp) * exception occured in user state?
|
||||
205 0000018A 662E bne supstat2 * if no, go to supervisor handler
|
||||
206 0000018C 212F0018 move.l 24(sp),-(a0) * put exception return on user stack
|
||||
207 00000190 312F0016 move.w 22(sp),-(a0) * put SR on user stack
|
||||
208 00000194 212F0012 move.l 18(sp),-(a0) * put extra 2 longs on user stack
|
||||
209 00000198 212F000E move.l 14(sp),-(a0)
|
||||
210 0000019C 4E60 move.l a0,usp * update user stack pointer
|
||||
211 0000019E 4CDF0101 movem.l (sp)+,a0/d0 * restore regs
|
||||
212 000001A2 2F6F00020010 move.l 2(sp),16(sp) * move address of user handler to excptn rtn
|
||||
213 000001A8 DEFC000E adda #14,sp * clear junk from stack
|
||||
214 000001AC 02577FFF andi #$7fff,(sp) * clear trace bit
|
||||
215 000001B0 4E73 rte * go to user handler
|
||||
216
|
||||
217 supstat1:
|
||||
218 000001B2 3F6F000E0008 move.w 14(sp),8(sp) * move SR to our exception return
|
||||
219 000001B8 6006 bra supstat3
|
||||
220 supstat2:
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 5
|
||||
Source File: exceptn.s
|
||||
|
||||
221 000001BA 3F6F00160008 move.w 22(sp),8(sp)
|
||||
222 supstat3:
|
||||
223 000001C0 4CDF0101 movem.l (sp)+,a0/d0
|
||||
224 000001C4 4E73 rte
|
||||
225
|
||||
226 *
|
||||
227 * Subroutines
|
||||
228 *
|
||||
229
|
||||
230 print:
|
||||
231 000001C6 4281 clr.l d1
|
||||
232 000001C8 1218 move.b (a0)+, d1
|
||||
233 000001CA 6706 beq prtdone
|
||||
234 000001CC 7002 move #2, d0
|
||||
235 000001CE 4E42 trap #2
|
||||
236 000001D0 60F4 bra print
|
||||
237 prtdone:
|
||||
238 000001D2 4E75 rts
|
||||
239
|
||||
240 prtlong:
|
||||
241 * Print d0.l in hex format
|
||||
242 000001D4 3F00 move d0,-(sp)
|
||||
243 000001D6 4840 swap d0
|
||||
244 000001D8 6102 bsr prtword
|
||||
245 000001DA 301F move (sp)+,d0
|
||||
246
|
||||
247 prtword:
|
||||
248 * Print d0.w in hex format
|
||||
249 000001DC 3F00 move d0,-(sp)
|
||||
250 000001DE E048 lsr #8,d0
|
||||
251 000001E0 6102 bsr prtbyte
|
||||
252 000001E2 301F move (sp)+,d0
|
||||
253
|
||||
254 prtbyte:
|
||||
255 * Print d0.b in hex format
|
||||
256 000001E4 3F00 move d0,-(sp)
|
||||
257 000001E6 E848 lsr #4,d0
|
||||
258 000001E8 6102 bsr prtnib
|
||||
259 000001EA 301F move (sp)+,d0
|
||||
260
|
||||
261 prtnib:
|
||||
262 000001EC 0240000F andi #$f,d0
|
||||
263 000001F0 0C40000A cmpi #10,d0
|
||||
264 000001F4 6D04 blt lt10
|
||||
265 000001F6 06000007 addi.b #'A'-'9'-1,d0
|
||||
266 lt10:
|
||||
267 000001FA 06000030 addi.b #'0',d0
|
||||
268 000001FE 3200 move d0,d1
|
||||
269 00000200 7002 move #2,d0
|
||||
270 00000202 4E42 trap #2
|
||||
271 00000204 4E75 rts
|
||||
272
|
||||
273
|
||||
274 00000000 .data
|
||||
275
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 6
|
||||
Source File: exceptn.s
|
||||
|
||||
276 excmsg1:
|
||||
277 00000000 0D0A0A4578636570 .dc.b 13,10,10,'Exception $',0
|
||||
277 00000008 74696F6E202400
|
||||
278
|
||||
279 excmsg2:
|
||||
280 0000000F 2061742075736572 .dc.b ' at user address $',0
|
||||
280 00000017 2061646472657373
|
||||
280 0000001F 202400
|
||||
281
|
||||
282 excmsg3:
|
||||
283 00000022 2E202041626F7274 .dc.b '. Aborted.',0
|
||||
283 0000002A 65642E00
|
||||
284
|
||||
285
|
||||
286 00000000 .bss
|
||||
287
|
||||
288 evec_adr:
|
||||
289 00000000 .ds.l 1
|
||||
290
|
||||
291 00000004 .end
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 7
|
||||
Source File: exceptn.s
|
||||
|
||||
S y m b o l T a b l e
|
||||
|
||||
_initexc 00000000 TEXT _tpa_hp ******** EXT _tpa_lp ******** EXT addrexc 00000184 TEXT
|
||||
bgetseg 00000012 ABS bsetexc 00000016 ABS buserr 00000002 ABS chkredir 000000F0 TEXT
|
||||
dfltexc 00000106 TEXT do_init 00000068 TEXT dontinit 0000006A TEXT endvec 00000030 ABS
|
||||
evec_adr 00000000 BSS except 000000CA TEXT exchndl 00000072 TEXT excmsg1 00000000 DATA
|
||||
excmsg2 0000000F DATA excmsg3 00000022 DATA excrtn0 00000076 TEXT init1 0000000A TEXT
|
||||
init2 00000014 TEXT init3 00000020 TEXT init4 00000058 TEXT lowexc 00000122 TEXT
|
||||
lt10 000001FA TEXT nobusexc 00000116 TEXT print 000001C6 TEXT prtbyte 000001E4 TEXT
|
||||
prtdone 000001D2 TEXT prtlong 000001D4 TEXT prtnib 000001EC TEXT prtword 000001DC TEXT
|
||||
spurious 00000018 ABS supstat1 000001B2 TEXT supstat2 000001BA TEXT supstat3 000001C0 TEXT
|
||||
trap0 00000020 ABS trap2 00000022 ABS trap3 00000023 ABS usrexc 00000154 TEXT
|
||||
291
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/exceptn.s
Normal file
291
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/exceptn.s
Normal file
@@ -0,0 +1,291 @@
|
||||
|
||||
*************************************************
|
||||
* *
|
||||
* CP/M-68k Basic Disk Operating System *
|
||||
* Exception Handling Module *
|
||||
* *
|
||||
* Version 0.0 -- July 21, 1982 *
|
||||
* Version 0.1 -- July 25, 1982 *
|
||||
* Version 0.2 -- October 6, 1982 *
|
||||
* Version 0.3 -- December 21, 1982 *
|
||||
* *
|
||||
*************************************************
|
||||
|
||||
|
||||
.globl _initexc
|
||||
.globl _tpa_lp
|
||||
.globl _tpa_hp
|
||||
|
||||
bgetseg = 18
|
||||
bsetexc = 22
|
||||
buserr = 2
|
||||
spurious = 24
|
||||
trap0 = 32
|
||||
trap2 = 34
|
||||
trap3 = 35
|
||||
endvec = 48
|
||||
|
||||
_initexc:
|
||||
* Initialize Exception Vector Handlers
|
||||
* It has 1 passed parameter: the address of the exception vector array
|
||||
move #bsetexc,d0
|
||||
moveq #2,d1
|
||||
move.l #exchndl,d2
|
||||
init1:
|
||||
movem.l d0-d2,-(sp)
|
||||
trap #3 * BIOS call to set exception vector
|
||||
movem.l (sp)+,d0-d2
|
||||
init2: addq #1,d1
|
||||
add.l #4,d2
|
||||
cmpi #spurious,d1
|
||||
bne init3
|
||||
move #trap0,d1
|
||||
init3: cmpi #trap2,d1
|
||||
beq init2 * don't init trap 2 or trap 3
|
||||
cmpi #trap3,d1
|
||||
beq init2
|
||||
cmpi #endvec,d1
|
||||
blt init1
|
||||
* initialize the exception vector array
|
||||
|
||||
moveq #bgetseg,d0
|
||||
trap #3 * get the original TPA limits
|
||||
movea.l d0,a0
|
||||
tst.w (a0)+
|
||||
move.l (a0)+,d1 * d1 = original low TPA limit
|
||||
move.l d1,d2
|
||||
add.l (a0),d2 * d2 = original high TPA limit
|
||||
move.l _tpa_lp,d3 * d3 = new low TPA limit
|
||||
move.l _tpa_hp,d4 * d4 = new high TPA limit
|
||||
move #17,d0
|
||||
movea.l 4(sp),a0
|
||||
move.l a0,evec_adr * save exception vector address
|
||||
init4:
|
||||
cmp.l (a0),d1
|
||||
bhi do_init * if old exception outside orig TPA, clear it
|
||||
cmp.l (a0),d2
|
||||
bls do_init
|
||||
* current exception array entry is in original TPA
|
||||
cmp.l (a0),d3
|
||||
bhi dontinit * if old exception in old TPA but outside new
|
||||
cmp.l (a0),d4 * TPA, don't clear it
|
||||
bls dontinit
|
||||
do_init:
|
||||
clr.l (a0)
|
||||
dontinit:
|
||||
tst.l (a0)+
|
||||
dbf d0,init4
|
||||
rts
|
||||
|
||||
exchndl:
|
||||
bsr.w except
|
||||
excrtn0:
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
bsr.w except
|
||||
|
||||
|
||||
except:
|
||||
clr.w -(sp)
|
||||
movem.l a0/d0,-(sp) * 10 words now on stack in following order:
|
||||
* _______________________________
|
||||
* |____________D0.L_______________|
|
||||
* |____________A0.L_______________|
|
||||
* |____0000______|________________
|
||||
* |_______Handler Return__________|
|
||||
* If bus error, extra 2 longs are here
|
||||
* ______________
|
||||
* |__Status Reg__|________________
|
||||
* |_____Exception Return__________|
|
||||
|
||||
move.l 10(sp),d0 * get return address from above array
|
||||
sub.l #excrtn0,d0 * d0 now has 4 * (encoded excptn nmbr), where
|
||||
* encoded excptn nmbr is in [0..21,22..37]
|
||||
* representing [2..23,32..47]
|
||||
cmpi #36,d0 * if d0/4 is in [0..9,22..29] then
|
||||
ble chkredir * the exception may be redirected
|
||||
cmpi #88,d0
|
||||
blt dfltexc
|
||||
cmpi #116,d0
|
||||
bgt dfltexc
|
||||
* in range of redirected exceptions
|
||||
subi #48,d0 * subtract 4*12 to normalize [0..9,22..29]
|
||||
* into [0..9,10..17]
|
||||
chkredir:
|
||||
movea.l evec_adr,a0
|
||||
adda d0,a0 * index into exception vector array
|
||||
tst.l (a0) * if 00000000, then not redirected
|
||||
bne usrexc
|
||||
* not redirected, do default handler
|
||||
cmpi #40,d0
|
||||
blt dfltexc
|
||||
addi #48,d0 * add 4*12 that was sub'd above
|
||||
dfltexc:
|
||||
adda #14,sp * throw away 7 words that we added to stack
|
||||
asr #2,d0 * divide d0 by 4
|
||||
* now d0 is in [0..21,22..37]
|
||||
* to represent [2..23,32..47]
|
||||
cmpi #2,d0 * bus or address error?
|
||||
bge nobusexc
|
||||
movem.l (sp)+,a0-a1 * if yes, throw away 4 words from stack
|
||||
nobusexc:
|
||||
tst.w (sp)+ * throw away stacked SR
|
||||
addi #2,d0
|
||||
cmpi #23,d0 * get back real excptn nmbr in [2..23,32..47]
|
||||
ble lowexc
|
||||
addi #8,d0
|
||||
lowexc: move d0,-(sp) * save excptn nmbr
|
||||
lea excmsg1,a0
|
||||
bsr print * print default exception message
|
||||
move (sp)+,d0
|
||||
bsr prtbyte
|
||||
lea excmsg2, a0
|
||||
bsr print
|
||||
move.l (sp)+,d0
|
||||
bsr prtlong
|
||||
lea excmsg3, a0
|
||||
bsr print
|
||||
clr.l d0
|
||||
trap #2 * warm boot
|
||||
rte
|
||||
|
||||
usrexc:
|
||||
* Call user exception handler
|
||||
* make sure exception information is on his stack
|
||||
move.l (a0),10(sp) * put user handler address on our stack
|
||||
move.l usp,a0 * user stack pointer to a0
|
||||
cmpi #8,d0 * address or bus error?
|
||||
blt addrexc * if yes, skip
|
||||
btst #13,14(sp) * exception occured in user state?
|
||||
bne supstat1 * if no, go to supervisor handler
|
||||
move.l 16(sp),-(a0) * put exception return on user stack
|
||||
move.w 14(sp),-(a0) * put SR on user stack
|
||||
move.l a0,usp * update user stack pointer
|
||||
movem.l (sp)+,a0/d0 * restore regs
|
||||
move.l 2(sp),8(sp) * move address of user handler to excptn rtn
|
||||
addq #6,sp * clear junk from stack
|
||||
andi #$7fff,(sp) * clear trace bit
|
||||
rte * go to user handler
|
||||
addrexc:
|
||||
btst #13,22(sp) * exception occured in user state?
|
||||
bne supstat2 * if no, go to supervisor handler
|
||||
move.l 24(sp),-(a0) * put exception return on user stack
|
||||
move.w 22(sp),-(a0) * put SR on user stack
|
||||
move.l 18(sp),-(a0) * put extra 2 longs on user stack
|
||||
move.l 14(sp),-(a0)
|
||||
move.l a0,usp * update user stack pointer
|
||||
movem.l (sp)+,a0/d0 * restore regs
|
||||
move.l 2(sp),16(sp) * move address of user handler to excptn rtn
|
||||
adda #14,sp * clear junk from stack
|
||||
andi #$7fff,(sp) * clear trace bit
|
||||
rte * go to user handler
|
||||
|
||||
supstat1:
|
||||
move.w 14(sp),8(sp) * move SR to our exception return
|
||||
bra supstat3
|
||||
supstat2:
|
||||
move.w 22(sp),8(sp)
|
||||
supstat3:
|
||||
movem.l (sp)+,a0/d0
|
||||
rte
|
||||
|
||||
*
|
||||
* Subroutines
|
||||
*
|
||||
|
||||
print:
|
||||
clr.l d1
|
||||
move.b (a0)+, d1
|
||||
beq prtdone
|
||||
move #2, d0
|
||||
trap #2
|
||||
bra print
|
||||
prtdone:
|
||||
rts
|
||||
|
||||
prtlong:
|
||||
* Print d0.l in hex format
|
||||
move d0,-(sp)
|
||||
swap d0
|
||||
bsr prtword
|
||||
move (sp)+,d0
|
||||
|
||||
prtword:
|
||||
* Print d0.w in hex format
|
||||
move d0,-(sp)
|
||||
lsr #8,d0
|
||||
bsr prtbyte
|
||||
move (sp)+,d0
|
||||
|
||||
prtbyte:
|
||||
* Print d0.b in hex format
|
||||
move d0,-(sp)
|
||||
lsr #4,d0
|
||||
bsr prtnib
|
||||
move (sp)+,d0
|
||||
|
||||
prtnib:
|
||||
andi #$f,d0
|
||||
cmpi #10,d0
|
||||
blt lt10
|
||||
addi.b #'A'-'9'-1,d0
|
||||
lt10:
|
||||
addi.b #'0',d0
|
||||
move d0,d1
|
||||
move #2,d0
|
||||
trap #2
|
||||
rts
|
||||
|
||||
|
||||
.data
|
||||
|
||||
excmsg1:
|
||||
.dc.b 13,10,10,'Exception $',0
|
||||
|
||||
excmsg2:
|
||||
.dc.b ' at user address $',0
|
||||
|
||||
excmsg3:
|
||||
.dc.b '. Aborted.',0
|
||||
|
||||
|
||||
.bss
|
||||
|
||||
evec_adr:
|
||||
.ds.l 1
|
||||
|
||||
.end
|
||||
659
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/fileio.c
Normal file
659
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/fileio.c
Normal file
@@ -0,0 +1,659 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-68K BDOS File I/O Module *
|
||||
* *
|
||||
* This module contains all file handling BDOS functions *
|
||||
* except for read and write for CP/M-68K. Included are: *
|
||||
* *
|
||||
* seldsk() - select disk *
|
||||
* openfile() - open file *
|
||||
* close_fi() - close file *
|
||||
* search() - search for first/next file match *
|
||||
* create() - create file *
|
||||
* delete() - delete file *
|
||||
* rename() - rename file *
|
||||
* set_attr() - set file attributes *
|
||||
* getsize() - get file size *
|
||||
* setran() - set random record field *
|
||||
* free_sp() - get disk free space *
|
||||
* move() - general purpose byte mover *
|
||||
* *
|
||||
* *
|
||||
* Compiled with Alcyon C on the VAX *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "bdosinc.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "pktio.h" /* Packet I/O definitions */
|
||||
|
||||
/* declare external fucntions */
|
||||
EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
EXTERN UWORD error(); /* disk error routine */
|
||||
EXTERN UWORD ro_err(); /* read-only file error routine */
|
||||
EXTERN UWORD do_phio(); /* packet disk i/o handler */
|
||||
EXTERN clraloc(); /* clear bit in allocation vector */
|
||||
EXTERN setaloc(); /* set bit in allocation vector */
|
||||
EXTERN UWORD swap(); /* assembly language byte swapper */
|
||||
EXTERN UWORD dir_wr(); /* directory write routine */
|
||||
EXTERN tmp_sel(); /* temporary select disk routine */
|
||||
EXTERN UWORD calcext(); /* calc max extent allocated for fcb */
|
||||
EXTERN UWORD udiv(); /* unsigned divide routine */
|
||||
|
||||
|
||||
/* declare external variables */
|
||||
EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
EXTERN UWORD crit_dsk; /* vector of disks in critical state */
|
||||
|
||||
|
||||
/************************************
|
||||
* This function passed to dirscan *
|
||||
* from seldsk (below) *
|
||||
************************************/
|
||||
|
||||
BOOLEAN alloc(fcbp, dirp, dirindx)
|
||||
/* Set up allocation vector for directory entry pointed to by dirp */
|
||||
|
||||
struct fcb *fcbp; /* not used in this function */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory for *dirp */
|
||||
{
|
||||
REG WORD i; /* loop counter */
|
||||
BSETUP
|
||||
|
||||
if ( UBWORD(dirp->entry) < 0x10 ) /* skip MP/M 2.x and CP/M 3.x XFCBs */
|
||||
{
|
||||
(GBL.dphp)->hiwater = dirindx; /* set up high water mark for disk */
|
||||
i = 0;
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{
|
||||
do setaloc( UBWORD(dirp->dskmap.small[i++]) );
|
||||
while (i <= 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
do setaloc(swap(dirp->dskmap.big[i++]));
|
||||
while (i <= 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* seldsk entry point *
|
||||
************************/
|
||||
|
||||
seldsk(dsknum)
|
||||
|
||||
REG UBYTE dsknum; /* disk number to select */
|
||||
|
||||
{
|
||||
struct iopb selpkt;
|
||||
REG WORD i;
|
||||
UWORD j;
|
||||
REG UBYTE logflag;
|
||||
BSETUP
|
||||
|
||||
logflag = ~(log_dsk >> dsknum) & 1;
|
||||
if ((GBL.curdsk != dsknum) || logflag)
|
||||
{ /* if not last used disk or not logged on */
|
||||
selpkt.iofcn = sel_info;
|
||||
GBL.curdsk = (selpkt.devnum = dsknum);
|
||||
if (UBWORD(dsknum) > 15) error(2);
|
||||
selpkt.ioflags = logflag ^ 1;
|
||||
do
|
||||
{
|
||||
do_phio(&selpkt); /* actually do the disk select */
|
||||
if ( (GBL.dphp = selpkt.infop) != NULL ) break;
|
||||
} while ( ! error(3) );
|
||||
|
||||
GBL.dirbufp = (GBL.dphp)->dbufp;
|
||||
/* set up GBL copies of dir_buf and dpb ptrs */
|
||||
GBL.parmp = (GBL.dphp)->dpbp;
|
||||
}
|
||||
if (logflag)
|
||||
{ /* if disk not previously logged on, do it now */
|
||||
LOCK /* must lock the file system while messing with alloc vec */
|
||||
i = (GBL.parmp)->dsm;
|
||||
do clraloc(i); while (i--); /* clear the allocation vector */
|
||||
i = udiv( (LONG)(((GBL.parmp)->drm) + 1),
|
||||
4 * (((GBL.parmp)->blm) + 1), &j);
|
||||
/* calculate nmbr of directory blks */
|
||||
if (j) i++; /* round up */
|
||||
do setaloc(--i); while (i); /* alloc directory blocks */
|
||||
dirscan(alloc, NULL, 0x0e); /* do directory scan & alloc blocks */
|
||||
log_dsk |= 1 << dsknum; /* mark disk as logged in */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
* General purpose byte mover *
|
||||
*******************************/
|
||||
|
||||
move(p1, p2, i)
|
||||
|
||||
REG BYTE *p1;
|
||||
REG BYTE *p2;
|
||||
REG WORD i;
|
||||
{
|
||||
while (i--)
|
||||
*p2++ = *p1++;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* General purpose filename matcher *
|
||||
*************************************/
|
||||
|
||||
BOOLEAN match(p1, p2, chk_ext)
|
||||
|
||||
REG UBYTE *p1;
|
||||
REG UBYTE *p2;
|
||||
BOOLEAN chk_ext;
|
||||
{
|
||||
REG WORD i;
|
||||
REG UBYTE temp;
|
||||
BSETUP
|
||||
|
||||
i = 12;
|
||||
do
|
||||
{
|
||||
temp = (*p1 ^ '?');
|
||||
if ( ((*p1++ ^ *p2++) & 0x7f) && temp )
|
||||
return(FALSE);
|
||||
i -= 1;
|
||||
} while (i);
|
||||
if (chk_ext)
|
||||
{
|
||||
if ( (*p1 != '?') && ((*p1 ^ *p2) & ~((GBL.parmp)->exm)) )
|
||||
return(FALSE);
|
||||
p1 += 2;
|
||||
p2 += 2;
|
||||
if ((*p1 ^ *p2) & 0x3f) return(FALSE);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* openfile entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN openfile(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to open */
|
||||
struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx;
|
||||
|
||||
{
|
||||
REG UBYTE fcb_ext; /* extent field from fcb */
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, TRUE) )
|
||||
{
|
||||
fcb_ext = fcbp->extent; /* save extent number from user's fcb */
|
||||
move(dirp, fcbp, sizeof *dirp);
|
||||
/* copy dir entry into user's fcb */
|
||||
fcbp->extent = fcb_ext;
|
||||
fcbp->s2 |= 0x80; /* set hi bit of S2 (write flag) */
|
||||
crit_dsk |= 1 << (GBL.curdsk);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/*************************/
|
||||
/* flush buffers routine */
|
||||
/*************************/
|
||||
|
||||
UWORD flushit()
|
||||
{
|
||||
REG UWORD rtn; /* return code from flush buffers call */
|
||||
struct iopb flushpkt; /* I/O packet for flush buffers call */
|
||||
|
||||
flushpkt.iofcn = flush;
|
||||
while ( rtn = do_phio(&flushpkt) )
|
||||
if ( error(1) ) break;
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
* file close routine for dirscan *
|
||||
*********************************/
|
||||
|
||||
BOOLEAN close(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG WORD i;
|
||||
REG UBYTE *fp;
|
||||
REG UBYTE *dp;
|
||||
REG UWORD fcb_ext;
|
||||
REG UWORD dir_ext;
|
||||
BSETUP
|
||||
|
||||
if ( match(fcbp, dirp, TRUE) )
|
||||
{ /* Note that FCB merging is done here as a final
|
||||
confirmation that disks haven't been swapped */
|
||||
LOCK
|
||||
fp = &(fcbp->dskmap.small[0]);
|
||||
dp = &(dirp->dskmap.small[0]);
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{ /* Small disk map merge routine */
|
||||
i = 16;
|
||||
do
|
||||
{
|
||||
if (*dp)
|
||||
{
|
||||
if (*fp)
|
||||
{
|
||||
if (*dp != *fp) goto badmerge;
|
||||
}
|
||||
else *fp = *dp;
|
||||
}
|
||||
else *dp = *fp;
|
||||
fp += 1;
|
||||
dp += 1;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
}
|
||||
else
|
||||
{ /* Large disk map merge routine */
|
||||
i = 8;
|
||||
do
|
||||
{
|
||||
if (*(UWORD *)dp)
|
||||
{
|
||||
if (*(UWORD *)fp)
|
||||
{
|
||||
if (*(UWORD *)dp != *(UWORD *)fp) goto badmerge;
|
||||
}
|
||||
else *(UWORD *)fp = *(UWORD *)dp;
|
||||
}
|
||||
else *(UWORD *)dp = *(UWORD *)fp;
|
||||
(UWORD *)fp += 1;
|
||||
(UWORD *)dp += 1;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
}
|
||||
/* Disk map merging complete */
|
||||
fcb_ext = calcext(fcbp); /* calc max extent for fcb */
|
||||
dir_ext = (UWORD)(dirp->extent) & 0x1f;
|
||||
if ( (fcb_ext > dir_ext) ||
|
||||
((fcb_ext == dir_ext) &&
|
||||
(UBWORD(fcbp->rcdcnt) > UBWORD(dirp->rcdcnt))) )
|
||||
/* if fcb points to larger file than dirp */
|
||||
{
|
||||
dirp->rcdcnt = fcbp->rcdcnt; /* set up rc, ext from fcb */
|
||||
dirp->extent = (BYTE)fcb_ext;
|
||||
}
|
||||
dirp->s1 = fcbp->s1;
|
||||
if ( (dirp->ftype[robit]) & 0x80) ro_err(fcbp,dirindx);
|
||||
/* read-only file error */
|
||||
dirp->ftype[arbit] &= 0x7f; /* clear archive bit */
|
||||
dir_wr(dirindx >> 2);
|
||||
UNLOCK
|
||||
return(TRUE);
|
||||
|
||||
badmerge:
|
||||
UNLOCK
|
||||
ro_dsk |= (1 << GBL.curdsk);
|
||||
return(FALSE);
|
||||
}
|
||||
else return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* close_fi entry point *
|
||||
************************/
|
||||
|
||||
UWORD close_fi(fcbp)
|
||||
|
||||
struct fcb *fcbp; /* pointer to fcb for file to close */
|
||||
{
|
||||
flushit(); /* first, flush the buffers */
|
||||
if ((fcbp->s2) & 0x80) return(0); /* if file write flag not on,
|
||||
don't need to do physical close */
|
||||
return( dirscan(close, fcbp, 0)); /* call dirscan with close function */
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* search entry point *
|
||||
************************/
|
||||
|
||||
/* First two functions for dirscan */
|
||||
|
||||
BOOLEAN alltrue(p1, p2, i)
|
||||
UBYTE *p1;
|
||||
UBYTE *p2;
|
||||
WORD i;
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
BOOLEAN matchit(p1, p2, i)
|
||||
UBYTE *p1;
|
||||
UBYTE *p2;
|
||||
WORD i;
|
||||
{
|
||||
return(match(p1, p2, TRUE));
|
||||
}
|
||||
|
||||
|
||||
/* search entry point */
|
||||
UWORD search(fcbp, dsparm, p)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to search */
|
||||
REG UWORD dsparm; /* parameter to pass through to dirscan */
|
||||
UBYTE *p; /* pointer to pass through to tmp_sel */
|
||||
|
||||
{
|
||||
REG UWORD rtn; /* return value */
|
||||
BSETUP
|
||||
|
||||
if (fcbp->drvcode == '?')
|
||||
{
|
||||
seldsk(GBL.dfltdsk);
|
||||
rtn = dirscan(alltrue, fcbp, dsparm);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_sel(p); /* temporarily select disk */
|
||||
if (fcbp->extent != '?') fcbp->extent = 0;
|
||||
fcbp->s2 = 0;
|
||||
rtn = dirscan(matchit, fcbp, dsparm);
|
||||
}
|
||||
move( GBL.dirbufp, GBL.dmaadr, SECLEN);
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* create entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN create(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to create */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BYTE *p;
|
||||
REG WORD i;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = ((dirp->entry) == 0xe5) )
|
||||
{
|
||||
p = &(fcbp->rcdcnt);
|
||||
i = 17;
|
||||
do
|
||||
{ /* clear fcb rcdcnt and disk map */
|
||||
*p++ = 0;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
move(fcbp, dirp, sizeof *dirp); /* move the fcb to the directory */
|
||||
dir_wr(dirindx >> 2); /* write the directory sector */
|
||||
if ( dirindx > (GBL.dphp)->hiwater )
|
||||
(GBL.dphp)->hiwater = dirindx;
|
||||
crit_dsk |= 1 << (GBL.curdsk);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* delete entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN delete(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG WORD i;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
if ( (dirp->ftype[robit]) & 0x80 ) ro_err(fcbp,dirindx);
|
||||
/* check for read-only file */
|
||||
dirp->entry = 0xe5;
|
||||
LOCK
|
||||
dir_wr(dirindx >> 2);
|
||||
/* Now free up the space in the allocation vector */
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{
|
||||
i = 16;
|
||||
do clraloc(UBWORD(dirp->dskmap.small[--i]));
|
||||
while (i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 8;
|
||||
do clraloc(swap(dirp->dskmap.big[--i]));
|
||||
while (i);
|
||||
}
|
||||
UNLOCK
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* rename entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN rename(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG UWORD i;
|
||||
REG BYTE *p; /* general purpose pointers */
|
||||
REG BYTE *q;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
if ( (dirp->ftype[robit]) & 0x80 ) ro_err(fcbp,dirindx);
|
||||
/* check for read-only file */
|
||||
p = &(fcbp->dskmap.small[1]);
|
||||
q = &(dirp->fname[0]);
|
||||
i = 11;
|
||||
do
|
||||
{
|
||||
*q++ = *p++ & 0x7f;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
dir_wr(dirindx >> 2);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* set_attr entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN set_attr(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
move(&fcbp->fname[0], &dirp->fname[0], 11);
|
||||
dir_wr(dirindx >> 2);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* utility routine used by *
|
||||
* setran and getsize *
|
||||
****************************/
|
||||
|
||||
LONG extsize(fcbp)
|
||||
/* Return size of extent pointed to by fcbp */
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
return( ((LONG)(fcbp->extent & 0x1f) << 7)
|
||||
| ((LONG)(fcbp->s2 & 0x3f) << 12) );
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* setran entry point *
|
||||
************************/
|
||||
|
||||
setran(fcbp)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to set ran rec */
|
||||
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
LONG random;
|
||||
|
||||
random = (LONG)UBWORD(fcbp->cur_rec) + extsize(fcbp);
|
||||
/* compute random record field */
|
||||
fcbp->ran0 = random.b2;
|
||||
fcbp->ran1 = random.b1;
|
||||
fcbp->ran2 = random.b0;
|
||||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
/* fsize is a funtion for dirscan */
|
||||
/* passed from getsize */
|
||||
/**********************************/
|
||||
|
||||
BOOLEAN fsize(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BOOLEAN rtn;
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
LONG temp;
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
temp = (LONG)UBWORD(dirp->rcdcnt) + extsize(dirp);
|
||||
/* compute file size */
|
||||
fcbp->ran0 = temp.b2;
|
||||
fcbp->ran1 = temp.b1;
|
||||
fcbp->ran2 = temp.b0;
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
/************************
|
||||
* getsize entry point *
|
||||
************************/
|
||||
|
||||
getsize(fcbp)
|
||||
/* get file size */
|
||||
REG struct fcb *fcbp; /* pointer to fcb to get file size for */
|
||||
|
||||
{
|
||||
LONG maxrcd;
|
||||
LONG temp;
|
||||
REG WORD dsparm;
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
|
||||
maxrcd = 0;
|
||||
dsparm = 0;
|
||||
temp = 0;
|
||||
while ( dirscan(fsize, fcbp, dsparm) < 255 )
|
||||
{ /* loop until no more matches */
|
||||
temp.b2 = fcbp->ran0;
|
||||
temp.b1 = fcbp->ran1;
|
||||
temp.b0 = fcbp->ran2;
|
||||
if (temp > maxrcd) maxrcd = temp;
|
||||
dsparm = 1;
|
||||
}
|
||||
fcbp->ran0 = maxrcd.b2;
|
||||
fcbp->ran1 = maxrcd.b1;
|
||||
fcbp->ran2 = maxrcd.b0;
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* free_sp entry point *
|
||||
************************/
|
||||
|
||||
free_sp(dsknum)
|
||||
|
||||
UBYTE dsknum; /* disk number to get free space of */
|
||||
{
|
||||
REG LONG records;
|
||||
REG UWORD *alvec;
|
||||
REG UWORD bitmask;
|
||||
REG UWORD alvword;
|
||||
REG WORD i;
|
||||
BSETUP
|
||||
|
||||
seldsk(dsknum); /* select the disk */
|
||||
records = (LONG)0; /* initialize the variables */
|
||||
alvec = (GBL.dphp)->alv;
|
||||
bitmask = 0;
|
||||
for (i = 0; i <= (GBL.parmp)->dsm; i++) /* for loop to compute */
|
||||
{
|
||||
if ( ! bitmask)
|
||||
{
|
||||
bitmask = 0x8000;
|
||||
alvword = ~(*alvec++);
|
||||
}
|
||||
if ( alvword & bitmask)
|
||||
records += (LONG)( ((GBL.parmp)->blm) + 1 );
|
||||
bitmask >>= 1;
|
||||
}
|
||||
*(LONG *)GBL.dmaadr = records; /* move # records to DMA address */
|
||||
}
|
||||
671
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/fileio.lis
Normal file
671
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/fileio.lis
Normal file
@@ -0,0 +1,671 @@
|
||||
1File: FILEIO.C Page 1
|
||||
1
|
||||
2 /****************************************************************
|
||||
3 * *
|
||||
4 * CP/M-68K BDOS File I/O Module *
|
||||
5 * *
|
||||
6 * This module contains all file handling BDOS functions *
|
||||
7 * except for read and write for CP/M-68K. Included are: *
|
||||
8 * *
|
||||
9 * seldsk() - select disk *
|
||||
10 * openfile() - open file *
|
||||
11 * close_fi() - close file *
|
||||
12 * search() - search for first/next file match *
|
||||
13 * create() - create file *
|
||||
14 * delete() - delete file *
|
||||
15 * rename() - rename file *
|
||||
16 * set_attr() - set file attributes *
|
||||
17 * getsize() - get file size *
|
||||
18 * setran() - set random record field *
|
||||
19 * free_sp() - get disk free space *
|
||||
20 * move() - general purpose byte mover *
|
||||
21 * *
|
||||
22 * *
|
||||
23 * Compiled with Alcyon C on the VAX *
|
||||
24 * *
|
||||
25 ****************************************************************/
|
||||
26
|
||||
27 #include "bdosinc.h" /* Standard I/O declarations */
|
||||
28
|
||||
29 #include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
30
|
||||
31 #include "pktio.h" /* Packet I/O definitions */
|
||||
32
|
||||
33 /* declare external fucntions */
|
||||
34 EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
35 EXTERN UWORD error(); /* disk error routine */
|
||||
36 EXTERN UWORD ro_err(); /* read-only file error routine */
|
||||
37 EXTERN UWORD do_phio(); /* packet disk i/o handler */
|
||||
38 EXTERN clraloc(); /* clear bit in allocation vector */
|
||||
39 EXTERN setaloc(); /* set bit in allocation vector */
|
||||
40 EXTERN UWORD swap(); /* assembly language byte swapper */
|
||||
41 EXTERN UWORD dir_wr(); /* directory write routine */
|
||||
42 EXTERN tmp_sel(); /* temporary select disk routine */
|
||||
43 EXTERN UWORD calcext(); /* calc max extent allocated for fcb */
|
||||
44 EXTERN UWORD udiv(); /* unsigned divide routine */
|
||||
45
|
||||
46
|
||||
47 /* declare external variables */
|
||||
48 EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
49 EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
50 EXTERN UWORD crit_dsk; /* vector of disks in critical state */
|
||||
51
|
||||
52
|
||||
53 /************************************
|
||||
54 * This function passed to dirscan *
|
||||
55 * from seldsk (below) *
|
||||
56 ************************************/
|
||||
57
|
||||
58 BOOLEAN alloc(fcbp, dirp, dirindx)
|
||||
59 /* Set up allocation vector for directory entry pointed to by dirp */
|
||||
1File: FILEIO.C Page 2
|
||||
60
|
||||
61 struct fcb *fcbp; /* not used in this function */
|
||||
62 REG struct dirent *dirp; /* pointer to directory entry */
|
||||
63 WORD dirindx; /* index into directory for *dirp */
|
||||
64 {
|
||||
65 REG WORD i; /* loop counter */
|
||||
66 BSETUP
|
||||
67
|
||||
68 if ( UBWORD(dirp->entry) < 0x10 ) /* skip MP/M 2.x and CP/M 3.x XFCBs */
|
||||
69 {
|
||||
70 (GBL.dphp)->hiwater = dirindx; /* set up high water mark for disk */
|
||||
71 i = 0;
|
||||
72 if ((GBL.parmp)->dsm < 256)
|
||||
73 {
|
||||
74 do setaloc( UBWORD(dirp->dskmap.small[i++]) );
|
||||
75 while (i <= 15);
|
||||
76 }
|
||||
77 else
|
||||
78 {
|
||||
79 do setaloc(swap(dirp->dskmap.big[i++]));
|
||||
80 while (i <= 7);
|
||||
81 }
|
||||
82 }
|
||||
83 }
|
||||
84
|
||||
85
|
||||
86 /************************
|
||||
87 * seldsk entry point *
|
||||
88 ************************/
|
||||
89
|
||||
90 seldsk(dsknum)
|
||||
91
|
||||
92 REG UBYTE dsknum; /* disk number to select */
|
||||
93
|
||||
94 {
|
||||
95 struct iopb selpkt;
|
||||
96 REG WORD i;
|
||||
97 UWORD j;
|
||||
98 REG UBYTE logflag;
|
||||
99 BSETUP
|
||||
100
|
||||
101 logflag = ~(log_dsk >> dsknum) & 1;
|
||||
102 if ((GBL.curdsk != dsknum) || logflag)
|
||||
103 { /* if not last used disk or not logged on */
|
||||
104 selpkt.iofcn = sel_info;
|
||||
105 GBL.curdsk = (selpkt.devnum = dsknum);
|
||||
106 if (UBWORD(dsknum) > 15) error(2);
|
||||
107 selpkt.ioflags = logflag ^ 1;
|
||||
108 do
|
||||
109 {
|
||||
110 do_phio(&selpkt); /* actually do the disk select */
|
||||
111 if ( (GBL.dphp = selpkt.infop) != NULL ) break;
|
||||
112 } while ( ! error(3) );
|
||||
113
|
||||
114 GBL.dirbufp = (GBL.dphp)->dbufp;
|
||||
115 /* set up GBL copies of dir_buf and dpb ptrs */
|
||||
116 GBL.parmp = (GBL.dphp)->dpbp;
|
||||
117 }
|
||||
118 if (logflag)
|
||||
1File: FILEIO.C Page 3
|
||||
119 { /* if disk not previously logged on, do it now */
|
||||
120 LOCK /* must lock the file system while messing with alloc vec */
|
||||
121 i = (GBL.parmp)->dsm;
|
||||
122 do clraloc(i); while (i--); /* clear the allocation vector */
|
||||
123 i = udiv( (LONG)(((GBL.parmp)->drm) + 1),
|
||||
124 4 * (((GBL.parmp)->blm) + 1), &j);
|
||||
125 /* calculate nmbr of directory blks */
|
||||
126 if (j) i++; /* round up */
|
||||
127 do setaloc(--i); while (i); /* alloc directory blocks */
|
||||
128 dirscan(alloc, NULL, 0x0e); /* do directory scan & alloc blocks */
|
||||
129 log_dsk |= 1 << dsknum; /* mark disk as logged in */
|
||||
130 }
|
||||
131 }
|
||||
132
|
||||
133
|
||||
134 /*******************************
|
||||
135 * General purpose byte mover *
|
||||
136 *******************************/
|
||||
137
|
||||
138 move(p1, p2, i)
|
||||
139
|
||||
140 REG BYTE *p1;
|
||||
141 REG BYTE *p2;
|
||||
142 REG WORD i;
|
||||
143 {
|
||||
144 while (i--)
|
||||
145 *p2++ = *p1++;
|
||||
146 }
|
||||
147
|
||||
148
|
||||
149 /*************************************
|
||||
150 * General purpose filename matcher *
|
||||
151 *************************************/
|
||||
152
|
||||
153 BOOLEAN match(p1, p2, chk_ext)
|
||||
154
|
||||
155 REG UBYTE *p1;
|
||||
156 REG UBYTE *p2;
|
||||
157 BOOLEAN chk_ext;
|
||||
158 {
|
||||
159 REG WORD i;
|
||||
160 REG UBYTE temp;
|
||||
161 BSETUP
|
||||
162
|
||||
163 i = 12;
|
||||
164 do
|
||||
165 {
|
||||
166 temp = (*p1 ^ '?');
|
||||
167 if ( ((*p1++ ^ *p2++) & 0x7f) && temp )
|
||||
168 return(FALSE);
|
||||
169 i -= 1;
|
||||
170 } while (i);
|
||||
171 if (chk_ext)
|
||||
172 {
|
||||
173 if ( (*p1 != '?') && ((*p1 ^ *p2) & ~((GBL.parmp)->exm)) )
|
||||
174 return(FALSE);
|
||||
175 p1 += 2;
|
||||
176 p2 += 2;
|
||||
177 if ((*p1 ^ *p2) & 0x3f) return(FALSE);
|
||||
1File: FILEIO.C Page 4
|
||||
178 }
|
||||
179 return(TRUE);
|
||||
180 }
|
||||
181
|
||||
182
|
||||
183 /************************
|
||||
184 * openfile entry point *
|
||||
185 ************************/
|
||||
186
|
||||
187 BOOLEAN openfile(fcbp, dirp, dirindx)
|
||||
188
|
||||
189 REG struct fcb *fcbp; /* pointer to fcb for file to open */
|
||||
190 struct dirent *dirp; /* pointer to directory entry */
|
||||
191 WORD dirindx;
|
||||
192
|
||||
193 {
|
||||
194 REG UBYTE fcb_ext; /* extent field from fcb */
|
||||
195 REG BOOLEAN rtn;
|
||||
196 BSETUP
|
||||
197
|
||||
198 if ( rtn = match(fcbp, dirp, TRUE) )
|
||||
199 {
|
||||
200 fcb_ext = fcbp->extent; /* save extent number from user's fcb */
|
||||
201 move(dirp, fcbp, sizeof *dirp);
|
||||
202 /* copy dir entry into user's fcb */
|
||||
203 fcbp->extent = fcb_ext;
|
||||
204 fcbp->s2 |= 0x80; /* set hi bit of S2 (write flag) */
|
||||
205 crit_dsk |= 1 << (GBL.curdsk);
|
||||
206 }
|
||||
207 return(rtn);
|
||||
208 }
|
||||
209
|
||||
210
|
||||
211 /*************************/
|
||||
212 /* flush buffers routine */
|
||||
213 /*************************/
|
||||
214
|
||||
215 UWORD flushit()
|
||||
216 {
|
||||
217 REG UWORD rtn; /* return code from flush buffers call */
|
||||
218 struct iopb flushpkt; /* I/O packet for flush buffers call */
|
||||
219
|
||||
220 flushpkt.iofcn = flush;
|
||||
221 while ( rtn = do_phio(&flushpkt) )
|
||||
222 if ( error(1) ) break;
|
||||
223 return(rtn);
|
||||
224 }
|
||||
225
|
||||
226
|
||||
227 /*********************************
|
||||
228 * file close routine for dirscan *
|
||||
229 *********************************/
|
||||
230
|
||||
231 BOOLEAN close(fcbp, dirp, dirindx)
|
||||
232
|
||||
233 REG struct fcb *fcbp; /* pointer to fcb */
|
||||
234 REG struct dirent *dirp; /* pointer to directory entry */
|
||||
235 WORD dirindx; /* index into directory */
|
||||
236
|
||||
1File: FILEIO.C Page 5
|
||||
237 {
|
||||
238 REG WORD i;
|
||||
239 REG UBYTE *fp;
|
||||
240 REG UBYTE *dp;
|
||||
241 REG UWORD fcb_ext;
|
||||
242 REG UWORD dir_ext;
|
||||
243 BSETUP
|
||||
244
|
||||
245 if ( match(fcbp, dirp, TRUE) )
|
||||
246 { /* Note that FCB merging is done here as a final
|
||||
247 confirmation that disks haven't been swapped */
|
||||
248 LOCK
|
||||
249 fp = &(fcbp->dskmap.small[0]);
|
||||
250 dp = &(dirp->dskmap.small[0]);
|
||||
251 if ((GBL.parmp)->dsm < 256)
|
||||
252 { /* Small disk map merge routine */
|
||||
253 i = 16;
|
||||
254 do
|
||||
255 {
|
||||
256 if (*dp)
|
||||
257 {
|
||||
258 if (*fp)
|
||||
259 {
|
||||
260 if (*dp != *fp) goto badmerge;
|
||||
261 }
|
||||
262 else *fp = *dp;
|
||||
263 }
|
||||
264 else *dp = *fp;
|
||||
265 fp += 1;
|
||||
266 dp += 1;
|
||||
267 i -= 1;
|
||||
268 } while (i);
|
||||
269 }
|
||||
270 else
|
||||
271 { /* Large disk map merge routine */
|
||||
272 i = 8;
|
||||
273 do
|
||||
274 {
|
||||
275 if (*(UWORD *)dp)
|
||||
276 {
|
||||
277 if (*(UWORD *)fp)
|
||||
278 {
|
||||
279 if (*(UWORD *)dp != *(UWORD *)fp) goto badmerge;
|
||||
280 }
|
||||
281 else *(UWORD *)fp = *(UWORD *)dp;
|
||||
282 }
|
||||
283 else *(UWORD *)dp = *(UWORD *)fp;
|
||||
284 (UWORD *)fp += 1;
|
||||
285 (UWORD *)dp += 1;
|
||||
286 i -= 1;
|
||||
287 } while (i);
|
||||
288 }
|
||||
289 /* Disk map merging complete */
|
||||
290 fcb_ext = calcext(fcbp); /* calc max extent for fcb */
|
||||
291 dir_ext = (UWORD)(dirp->extent) & 0x1f;
|
||||
292 if ( (fcb_ext > dir_ext) ||
|
||||
293 ((fcb_ext == dir_ext) &&
|
||||
294 (UBWORD(fcbp->rcdcnt) > UBWORD(dirp->rcdcnt))) )
|
||||
295 /* if fcb points to larger file than dirp */
|
||||
1File: FILEIO.C Page 6
|
||||
296 {
|
||||
297 dirp->rcdcnt = fcbp->rcdcnt; /* set up rc, ext from fcb */
|
||||
298 dirp->extent = (BYTE)fcb_ext;
|
||||
299 }
|
||||
300 dirp->s1 = fcbp->s1;
|
||||
301 if ( (dirp->ftype[robit]) & 0x80) ro_err(fcbp,dirindx);
|
||||
302 /* read-only file error */
|
||||
303 dirp->ftype[arbit] &= 0x7f; /* clear archive bit */
|
||||
304 dir_wr(dirindx >> 2);
|
||||
305 UNLOCK
|
||||
306 return(TRUE);
|
||||
307
|
||||
308 badmerge:
|
||||
309 UNLOCK
|
||||
310 ro_dsk |= (1 << GBL.curdsk);
|
||||
311 return(FALSE);
|
||||
312 }
|
||||
313 else return(FALSE);
|
||||
314 }
|
||||
315
|
||||
316
|
||||
317 /************************
|
||||
318 * close_fi entry point *
|
||||
319 ************************/
|
||||
320
|
||||
321 UWORD close_fi(fcbp)
|
||||
322
|
||||
323 struct fcb *fcbp; /* pointer to fcb for file to close */
|
||||
324 {
|
||||
325 flushit(); /* first, flush the buffers */
|
||||
326 if ((fcbp->s2) & 0x80) return(0); /* if file write flag not on,
|
||||
327 don't need to do physical close */
|
||||
328 return( dirscan(close, fcbp, 0)); /* call dirscan with close function */
|
||||
329 }
|
||||
330
|
||||
331
|
||||
332 /************************
|
||||
333 * search entry point *
|
||||
334 ************************/
|
||||
335
|
||||
336 /* First two functions for dirscan */
|
||||
337
|
||||
338 BOOLEAN alltrue(p1, p2, i)
|
||||
339 UBYTE *p1;
|
||||
340 UBYTE *p2;
|
||||
341 WORD i;
|
||||
342 {
|
||||
343 return(TRUE);
|
||||
344 }
|
||||
345
|
||||
346 BOOLEAN matchit(p1, p2, i)
|
||||
347 UBYTE *p1;
|
||||
348 UBYTE *p2;
|
||||
349 WORD i;
|
||||
350 {
|
||||
351 return(match(p1, p2, TRUE));
|
||||
352 }
|
||||
353
|
||||
354
|
||||
1File: FILEIO.C Page 7
|
||||
355 /* search entry point */
|
||||
356 UWORD search(fcbp, dsparm, p)
|
||||
357
|
||||
358 REG struct fcb *fcbp; /* pointer to fcb for file to search */
|
||||
359 REG UWORD dsparm; /* parameter to pass through to dirscan */
|
||||
360 UBYTE *p; /* pointer to pass through to tmp_sel */
|
||||
361
|
||||
362 {
|
||||
363 REG UWORD rtn; /* return value */
|
||||
364 BSETUP
|
||||
365
|
||||
366 if (fcbp->drvcode == '?')
|
||||
367 {
|
||||
368 seldsk(GBL.dfltdsk);
|
||||
369 rtn = dirscan(alltrue, fcbp, dsparm);
|
||||
370 }
|
||||
371 else
|
||||
372 {
|
||||
373 tmp_sel(p); /* temporarily select disk */
|
||||
374 if (fcbp->extent != '?') fcbp->extent = 0;
|
||||
375 fcbp->s2 = 0;
|
||||
376 rtn = dirscan(matchit, fcbp, dsparm);
|
||||
377 }
|
||||
378 move( GBL.dirbufp, GBL.dmaadr, SECLEN);
|
||||
379 return(rtn);
|
||||
380 }
|
||||
381
|
||||
382
|
||||
383 /************************
|
||||
384 * create entry point *
|
||||
385 ************************/
|
||||
386
|
||||
387 BOOLEAN create(fcbp, dirp, dirindx)
|
||||
388
|
||||
389 REG struct fcb *fcbp; /* pointer to fcb for file to create */
|
||||
390 REG struct dirent *dirp; /* pointer to directory entry */
|
||||
391 REG WORD dirindx; /* index into directory */
|
||||
392
|
||||
393 {
|
||||
394 REG BYTE *p;
|
||||
395 REG WORD i;
|
||||
396 REG BOOLEAN rtn;
|
||||
397 BSETUP
|
||||
398
|
||||
399 if ( rtn = ((dirp->entry) == 0xe5) )
|
||||
400 {
|
||||
401 p = &(fcbp->rcdcnt);
|
||||
402 i = 17;
|
||||
403 do
|
||||
404 { /* clear fcb rcdcnt and disk map */
|
||||
405 *p++ = 0;
|
||||
406 i -= 1;
|
||||
407 } while (i);
|
||||
408 move(fcbp, dirp, sizeof *dirp); /* move the fcb to the directory */
|
||||
409 dir_wr(dirindx >> 2); /* write the directory sector */
|
||||
410 if ( dirindx > (GBL.dphp)->hiwater )
|
||||
411 (GBL.dphp)->hiwater = dirindx;
|
||||
412 crit_dsk |= 1 << (GBL.curdsk);
|
||||
413 }
|
||||
1File: FILEIO.C Page 8
|
||||
414 return(rtn);
|
||||
415 }
|
||||
416
|
||||
417
|
||||
418 /************************
|
||||
419 * delete entry point *
|
||||
420 ************************/
|
||||
421
|
||||
422 BOOLEAN delete(fcbp, dirp, dirindx)
|
||||
423
|
||||
424 REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
425 REG struct dirent *dirp; /* pointer to directory entry */
|
||||
426 REG WORD dirindx; /* index into directory */
|
||||
427
|
||||
428 {
|
||||
429 REG WORD i;
|
||||
430 REG BOOLEAN rtn;
|
||||
431 BSETUP
|
||||
432
|
||||
433 if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
434 {
|
||||
435 if ( (dirp->ftype[robit]) & 0x80 ) ro_err(fcbp,dirindx);
|
||||
436 /* check for read-only file */
|
||||
437 dirp->entry = 0xe5;
|
||||
438 LOCK
|
||||
439 dir_wr(dirindx >> 2);
|
||||
440 /* Now free up the space in the allocation vector */
|
||||
441 if ((GBL.parmp)->dsm < 256)
|
||||
442 {
|
||||
443 i = 16;
|
||||
444 do clraloc(UBWORD(dirp->dskmap.small[--i]));
|
||||
445 while (i);
|
||||
446 }
|
||||
447 else
|
||||
448 {
|
||||
449 i = 8;
|
||||
450 do clraloc(swap(dirp->dskmap.big[--i]));
|
||||
451 while (i);
|
||||
452 }
|
||||
453 UNLOCK
|
||||
454 }
|
||||
455 return(rtn);
|
||||
456 }
|
||||
457
|
||||
458
|
||||
459 /************************
|
||||
460 * rename entry point *
|
||||
461 ************************/
|
||||
462
|
||||
463 BOOLEAN rename(fcbp, dirp, dirindx)
|
||||
464
|
||||
465 REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
466 REG struct dirent *dirp; /* pointer to directory entry */
|
||||
467 REG WORD dirindx; /* index into directory */
|
||||
468
|
||||
469 {
|
||||
470 REG UWORD i;
|
||||
471 REG BYTE *p; /* general purpose pointers */
|
||||
472 REG BYTE *q;
|
||||
1File: FILEIO.C Page 9
|
||||
473 REG BOOLEAN rtn;
|
||||
474 BSETUP
|
||||
475
|
||||
476 if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
477 {
|
||||
478 if ( (dirp->ftype[robit]) & 0x80 ) ro_err(fcbp,dirindx);
|
||||
479 /* check for read-only file */
|
||||
480 p = &(fcbp->dskmap.small[1]);
|
||||
481 q = &(dirp->fname[0]);
|
||||
482 i = 11;
|
||||
483 do
|
||||
484 {
|
||||
485 *q++ = *p++ & 0x7f;
|
||||
486 i -= 1;
|
||||
487 } while (i);
|
||||
488 dir_wr(dirindx >> 2);
|
||||
489 }
|
||||
490 return(rtn);
|
||||
491 }
|
||||
492
|
||||
493
|
||||
494 /************************
|
||||
495 * set_attr entry point *
|
||||
496 ************************/
|
||||
497
|
||||
498 BOOLEAN set_attr(fcbp, dirp, dirindx)
|
||||
499
|
||||
500 REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
501 REG struct dirent *dirp; /* pointer to directory entry */
|
||||
502 REG WORD dirindx; /* index into directory */
|
||||
503
|
||||
504 {
|
||||
505 REG BOOLEAN rtn;
|
||||
506 BSETUP
|
||||
507
|
||||
508 if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
509 {
|
||||
510 move(&fcbp->fname[0], &dirp->fname[0], 11);
|
||||
511 dir_wr(dirindx >> 2);
|
||||
512 }
|
||||
513 return(rtn);
|
||||
514 }
|
||||
515
|
||||
516
|
||||
517 /****************************
|
||||
518 * utility routine used by *
|
||||
519 * setran and getsize *
|
||||
520 ****************************/
|
||||
521
|
||||
522 LONG extsize(fcbp)
|
||||
523 /* Return size of extent pointed to by fcbp */
|
||||
524 REG struct fcb *fcbp;
|
||||
525
|
||||
526 {
|
||||
527 return( ((LONG)(fcbp->extent & 0x1f) << 7)
|
||||
528 | ((LONG)(fcbp->s2 & 0x3f) << 12) );
|
||||
529 }
|
||||
530
|
||||
531
|
||||
1File: FILEIO.C Page 10
|
||||
532 /************************
|
||||
533 * setran entry point *
|
||||
534 ************************/
|
||||
535
|
||||
536 setran(fcbp)
|
||||
537
|
||||
538 REG struct fcb *fcbp; /* pointer to fcb for file to set ran rec */
|
||||
539
|
||||
540 {
|
||||
541 struct
|
||||
542 {
|
||||
543 BYTE b3;
|
||||
544 BYTE b2;
|
||||
545 BYTE b1;
|
||||
546 BYTE b0;
|
||||
547 };
|
||||
548 LONG random;
|
||||
549
|
||||
550 random = (LONG)UBWORD(fcbp->cur_rec) + extsize(fcbp);
|
||||
551 /* compute random record field */
|
||||
552 fcbp->ran0 = random.b2;
|
||||
553 fcbp->ran1 = random.b1;
|
||||
554 fcbp->ran2 = random.b0;
|
||||
555 }
|
||||
556
|
||||
557
|
||||
558 /**********************************/
|
||||
559 /* fsize is a funtion for dirscan */
|
||||
560 /* passed from getsize */
|
||||
561 /**********************************/
|
||||
562
|
||||
563 BOOLEAN fsize(fcbp, dirp, dirindx)
|
||||
564
|
||||
565 REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
566 REG struct dirent *dirp; /* pointer to directory entry */
|
||||
567 WORD dirindx; /* index into directory */
|
||||
568
|
||||
569 {
|
||||
570 REG BOOLEAN rtn;
|
||||
571 struct
|
||||
572 {
|
||||
573 BYTE b3;
|
||||
574 BYTE b2;
|
||||
575 BYTE b1;
|
||||
576 BYTE b0;
|
||||
577 };
|
||||
578 LONG temp;
|
||||
579
|
||||
580 if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
581 {
|
||||
582 temp = (LONG)UBWORD(dirp->rcdcnt) + extsize(dirp);
|
||||
583 /* compute file size */
|
||||
584 fcbp->ran0 = temp.b2;
|
||||
585 fcbp->ran1 = temp.b1;
|
||||
586 fcbp->ran2 = temp.b0;
|
||||
587 }
|
||||
588 return(rtn);
|
||||
589 }
|
||||
590
|
||||
1File: FILEIO.C Page 11
|
||||
591 /************************
|
||||
592 * getsize entry point *
|
||||
593 ************************/
|
||||
594
|
||||
595 getsize(fcbp)
|
||||
596 /* get file size */
|
||||
597 REG struct fcb *fcbp; /* pointer to fcb to get file size for */
|
||||
598
|
||||
599 {
|
||||
600 LONG maxrcd;
|
||||
601 LONG temp;
|
||||
602 REG WORD dsparm;
|
||||
603 struct
|
||||
604 {
|
||||
605 BYTE b3;
|
||||
606 BYTE b2;
|
||||
607 BYTE b1;
|
||||
608 BYTE b0;
|
||||
609 };
|
||||
610
|
||||
611 maxrcd = 0;
|
||||
612 dsparm = 0;
|
||||
613 temp = 0;
|
||||
614 while ( dirscan(fsize, fcbp, dsparm) < 255 )
|
||||
615 { /* loop until no more matches */
|
||||
616 temp.b2 = fcbp->ran0;
|
||||
617 temp.b1 = fcbp->ran1;
|
||||
618 temp.b0 = fcbp->ran2;
|
||||
619 if (temp > maxrcd) maxrcd = temp;
|
||||
620 dsparm = 1;
|
||||
621 }
|
||||
622 fcbp->ran0 = maxrcd.b2;
|
||||
623 fcbp->ran1 = maxrcd.b1;
|
||||
624 fcbp->ran2 = maxrcd.b0;
|
||||
625 }
|
||||
626
|
||||
627
|
||||
628 /************************
|
||||
629 * free_sp entry point *
|
||||
630 ************************/
|
||||
631
|
||||
632 free_sp(dsknum)
|
||||
633
|
||||
634 UBYTE dsknum; /* disk number to get free space of */
|
||||
635 {
|
||||
636 REG LONG records;
|
||||
637 REG UWORD *alvec;
|
||||
638 REG UWORD bitmask;
|
||||
639 REG UWORD alvword;
|
||||
640 REG WORD i;
|
||||
641 BSETUP
|
||||
642
|
||||
643 seldsk(dsknum); /* select the disk */
|
||||
644 records = (LONG)0; /* initialize the variables */
|
||||
645 alvec = (GBL.dphp)->alv;
|
||||
646 bitmask = 0;
|
||||
647 for (i = 0; i <= (GBL.parmp)->dsm; i++) /* for loop to compute */
|
||||
648 {
|
||||
649 if ( ! bitmask)
|
||||
1File: FILEIO.C Page 12
|
||||
650 {
|
||||
651 bitmask = 0x8000;
|
||||
652 alvword = ~(*alvec++);
|
||||
653 }
|
||||
654 if ( alvword & bitmask)
|
||||
655 records += (LONG)( ((GBL.parmp)->blm) + 1 );
|
||||
656 bitmask >>= 1;
|
||||
657 }
|
||||
658 *(LONG *)GBL.dmaadr = records; /* move # records to DMA address */
|
||||
659 }
|
||||
@@ -0,0 +1,113 @@
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 1
|
||||
Source File: filetyps.s
|
||||
|
||||
1
|
||||
2 *
|
||||
3 * CP/M-68K table driven file search module
|
||||
4 * ========================================
|
||||
5 *
|
||||
6
|
||||
7 * GLOBALS
|
||||
8
|
||||
9
|
||||
10 .globl _load_tbl * loader table
|
||||
11 .globl _load68k * default load program
|
||||
12 .globl init_tbl * initializes table on COLD BOOT
|
||||
13
|
||||
14 00000000 .text
|
||||
15 *************************************************************************
|
||||
16 * *
|
||||
17 * This is the DUAL PROCESSOR,ROMABLE version of CP/M-68K *
|
||||
18 * ====================================================== *
|
||||
19 * *
|
||||
20 * (c) Copyright Digital Research 1983 *
|
||||
21 * all rights reserved *
|
||||
22 * *
|
||||
23 *************************************************************************
|
||||
24
|
||||
25 *
|
||||
26 * The following code allows CP/M-68K to be ROM-able.
|
||||
27 * -------------------------------------------------
|
||||
28 *
|
||||
29
|
||||
30 init_tbl:
|
||||
31 00000000 23FC0000000000000000 move.l #typ1,typ1p
|
||||
32 0000000A 23FC000000040000000A move.l #typ2,typ2p * init the pointers to the filetypes
|
||||
33 00000014 23FC0000000800000014 move.l #typ3,typ3p
|
||||
34 0000001E 23FC0000000C0000001E move.l #null,typ4p
|
||||
35
|
||||
36 00000028 23FC0000000000000004 move.l #_load68k,pgld1
|
||||
37 00000032 23FC000000000000000E move.l #_load68k,pgld2 * init the pointers to the loaders
|
||||
38 0000003C 23FC0000000000000018 move.l #_load68k,pgld3
|
||||
39 00000046 23FC0000000000000022 move.l #_load68k,pgld4
|
||||
40
|
||||
41 00000050 4E75 rts
|
||||
42 00000000 .bss
|
||||
43 .even
|
||||
44 *************************************************************************
|
||||
45 * *
|
||||
46 * CP/M-68K LOADER TABLE *
|
||||
47 * ===================== *
|
||||
48 * *
|
||||
49 *-----------------------------------------------------------------------*
|
||||
50 * *
|
||||
51 * STRUCTURE OF A LOADER TABLE ENTRY: *
|
||||
52 * ================================= *
|
||||
53 * *
|
||||
54 * (1) LONG WORD pointer to a filetype *
|
||||
55 * (2) LONG WORD address of the program loader for the above type *
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 2
|
||||
Source File: filetyps.s
|
||||
|
||||
56 * (3) BYTE flag #1 *
|
||||
57 * (4) BYTE flag #2 *
|
||||
58 * *
|
||||
59 *************************************************************************
|
||||
60
|
||||
61
|
||||
62 _load_tbl:
|
||||
63 00000000 typ1p: .ds.l 1
|
||||
64 00000004 pgld1: .ds.l 1
|
||||
65 00000008 .ds.b 1
|
||||
66 00000009 .ds.b 1
|
||||
67 0000000A typ2p: .ds.l 1
|
||||
68 0000000E pgld2: .ds.l 1
|
||||
69 00000012 .ds.b 1
|
||||
70 00000013 .ds.b 1
|
||||
71 00000014 typ3p: .ds.l 1
|
||||
72 00000018 pgld3: .ds.l 1
|
||||
73 0000001C .ds.b 1
|
||||
74 0000001D .ds.b 1
|
||||
75 0000001E typ4p: .ds.l 1
|
||||
76 00000022 pgld4: .ds.l 1
|
||||
77 00000026 .ds.b 1
|
||||
78 00000027 .ds.b 1
|
||||
79
|
||||
80
|
||||
81 *****************************************
|
||||
82 * *
|
||||
83 * FILETYPE TABLE *
|
||||
84 * ============== *
|
||||
85 * *
|
||||
86 *****************************************
|
||||
87
|
||||
88
|
||||
89 00000000 .data
|
||||
90 .even
|
||||
91 00000000 36384B00 typ1: .dc.b '68K',0
|
||||
92 .even
|
||||
93 00000004 20202000 typ2: .dc.b ' ',0
|
||||
94 .even
|
||||
95 00000008 53554200 typ3: .dc.b 'SUB',0
|
||||
96 .even
|
||||
97 0000000C 00000000 null: .dc.l 0
|
||||
98 00000010 .end
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 3
|
||||
Source File: filetyps.s
|
||||
|
||||
S y m b o l T a b l e
|
||||
|
||||
_load68k ******** EXT _load_tb 00000000 BSS init_tbl 00000000 TEXT null 0000000C DATA
|
||||
pgld1 00000004 BSS pgld2 0000000E BSS pgld3 00000018 BSS pgld4 00000022 BSS
|
||||
typ1 00000000 DATA typ1p 00000000 BSS typ2 00000004 DATA typ2p 0000000A BSS
|
||||
typ3 00000008 DATA typ3p 00000014 BSS typ4p 0000001E BSS
|
||||
106
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/filetyps.s
Normal file
106
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/filetyps.s
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
*
|
||||
* CP/M-68K table driven file search module
|
||||
* ========================================
|
||||
*
|
||||
|
||||
* GLOBALS
|
||||
|
||||
|
||||
.globl _load_tbl * loader table
|
||||
.globl _load68k * default load program
|
||||
.globl init_tbl * initializes table on COLD BOOT
|
||||
|
||||
.text
|
||||
*************************************************************************
|
||||
* *
|
||||
* This is the DUAL PROCESSOR,ROMABLE version of CP/M-68K *
|
||||
* ====================================================== *
|
||||
* *
|
||||
* (c) Copyright Digital Research 1983 *
|
||||
* all rights reserved *
|
||||
* *
|
||||
*************************************************************************
|
||||
|
||||
*
|
||||
* The following code allows CP/M-68K to be ROM-able.
|
||||
* -------------------------------------------------
|
||||
*
|
||||
|
||||
init_tbl:
|
||||
move.l #typ1,typ1p
|
||||
move.l #typ2,typ2p * init the pointers to the filetypes
|
||||
move.l #typ3,typ3p
|
||||
move.l #null,typ4p
|
||||
|
||||
move.l #_load68k,pgld1
|
||||
move.l #_load68k,pgld2 * init the pointers to the loaders
|
||||
move.l #_load68k,pgld3
|
||||
move.l #_load68k,pgld4
|
||||
|
||||
rts
|
||||
.bss
|
||||
.even
|
||||
*************************************************************************
|
||||
* *
|
||||
* CP/M-68K LOADER TABLE *
|
||||
* ===================== *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* STRUCTURE OF A LOADER TABLE ENTRY: *
|
||||
* ================================= *
|
||||
* *
|
||||
* (1) LONG WORD pointer to a filetype *
|
||||
* (2) LONG WORD address of the program loader for the above type *
|
||||
* (3) BYTE flag #1 *
|
||||
* (4) BYTE flag #2 *
|
||||
* *
|
||||
*************************************************************************
|
||||
|
||||
|
||||
_load_tbl:
|
||||
typ1p: .ds.l 1
|
||||
pgld1: .ds.l 1
|
||||
.ds.b 1
|
||||
.ds.b 1
|
||||
typ2p: .ds.l 1
|
||||
pgld2: .ds.l 1
|
||||
.ds.b 1
|
||||
.ds.b 1
|
||||
typ3p: .ds.l 1
|
||||
pgld3: .ds.l 1
|
||||
.ds.b 1
|
||||
.ds.b 1
|
||||
typ4p: .ds.l 1
|
||||
pgld4: .ds.l 1
|
||||
.ds.b 1
|
||||
.ds.b 1
|
||||
|
||||
|
||||
*****************************************
|
||||
* *
|
||||
* FILETYPE TABLE *
|
||||
* ============== *
|
||||
* *
|
||||
*****************************************
|
||||
|
||||
|
||||
.data
|
||||
.even
|
||||
typ1: .dc.b '68K',0
|
||||
.even
|
||||
typ2: .dc.b ' ',0
|
||||
.even
|
||||
typ3: .dc.b 'SUB',0
|
||||
.even
|
||||
null: .dc.l 0
|
||||
.end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-68K BDOS Disk I/O System Module *
|
||||
* *
|
||||
* This module translates from the packet oriented I/O *
|
||||
* passed from the other BDOS modules into BIOS calls. *
|
||||
* *
|
||||
* It includes only one external entry point:
|
||||
* do_phio() - do physical i/o *
|
||||
* *
|
||||
* *
|
||||
* Configured for Alcyon C on the VAX *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "bdosinc.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "pktio.h" /* Packet I/O definitions */
|
||||
|
||||
#include "biosdef.h" /* Declarations for BIOS entry points */
|
||||
|
||||
EXTERN udiv(); /* Assembly language unsigned divide routine */
|
||||
/* in bdosif.s. It's used because Alcyon C */
|
||||
/* can't do / or % without an external */
|
||||
|
||||
/************************
|
||||
* do_phio entry point *
|
||||
************************/
|
||||
|
||||
UWORD do_phio(iop)
|
||||
|
||||
REG struct iopb *iop; /* iop is a pointer to a i/o parameter block */
|
||||
|
||||
{
|
||||
MLOCAL UBYTE last_dsk; /* static variable to tell which disk
|
||||
was last used, to avoid disk selects */
|
||||
REG struct dph *hdrp; /* pointer to disk parameter header */
|
||||
REG struct dpb *dparmp; /* pointer to disk parameter block */
|
||||
REG UWORD rtn; /* return parameter */
|
||||
UWORD iosect; /* sector number returned from divide rtn */
|
||||
|
||||
LOCK /* lock the disk system while doing physical i/o */
|
||||
|
||||
rtn = 0;
|
||||
switch (iop->iofcn)
|
||||
{
|
||||
case sel_info:
|
||||
last_dsk = iop->devnum;
|
||||
iop->infop = bseldsk(last_dsk, iop->ioflags);
|
||||
break;
|
||||
|
||||
case read:
|
||||
case write:
|
||||
if (last_dsk != iop->devnum)
|
||||
bseldsk((last_dsk = iop->devnum), 0);
|
||||
/* guaranteed disk is logged on, because temp_sel in
|
||||
BDOSMAIN does it */
|
||||
hdrp = iop->infop;
|
||||
dparmp = hdrp->dpbp;
|
||||
|
||||
bsettrk( udiv( iop->devadr, dparmp->spt, &iosect )
|
||||
+ dparmp->trk_off );
|
||||
bsetsec( bsectrn( iosect, hdrp->xlt ) );
|
||||
bsetdma(iop->xferadr);
|
||||
if ((iop->iofcn) == read) rtn = bread();
|
||||
else rtn = bwrite(iop->ioflags);
|
||||
break;
|
||||
|
||||
case flush:
|
||||
rtn = bflush();
|
||||
}
|
||||
|
||||
UNLOCK
|
||||
return(rtn);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
1File: IOSYS.C Page 1
|
||||
1 /****************************************************************
|
||||
2 * *
|
||||
3 * CP/M-68K BDOS Disk I/O System Module *
|
||||
4 * *
|
||||
5 * This module translates from the packet oriented I/O *
|
||||
6 * passed from the other BDOS modules into BIOS calls. *
|
||||
7 * *
|
||||
8 * It includes only one external entry point:
|
||||
9 * do_phio() - do physical i/o *
|
||||
10 * *
|
||||
11 * *
|
||||
12 * Configured for Alcyon C on the VAX *
|
||||
13 * *
|
||||
14 ****************************************************************/
|
||||
15
|
||||
16 #include "bdosinc.h" /* Standard I/O declarations */
|
||||
17
|
||||
18 #include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
19
|
||||
20 #include "pktio.h" /* Packet I/O definitions */
|
||||
21
|
||||
22 #include "biosdef.h" /* Declarations for BIOS entry points */
|
||||
23
|
||||
24 EXTERN udiv(); /* Assembly language unsigned divide routine */
|
||||
25 /* in bdosif.s. It's used because Alcyon C */
|
||||
26 /* can't do / or % without an external */
|
||||
27
|
||||
28 /************************
|
||||
29 * do_phio entry point *
|
||||
30 ************************/
|
||||
31
|
||||
32 UWORD do_phio(iop)
|
||||
33
|
||||
34 REG struct iopb *iop; /* iop is a pointer to a i/o parameter block */
|
||||
35
|
||||
36 {
|
||||
37 MLOCAL UBYTE last_dsk; /* static variable to tell which disk
|
||||
38 was last used, to avoid disk selects */
|
||||
39 REG struct dph *hdrp; /* pointer to disk parameter header */
|
||||
40 REG struct dpb *dparmp; /* pointer to disk parameter block */
|
||||
41 REG UWORD rtn; /* return parameter */
|
||||
42 UWORD iosect; /* sector number returned from divide rtn */
|
||||
43
|
||||
44 LOCK /* lock the disk system while doing physical i/o */
|
||||
45
|
||||
46 rtn = 0;
|
||||
47 switch (iop->iofcn)
|
||||
48 {
|
||||
49 case sel_info:
|
||||
50 last_dsk = iop->devnum;
|
||||
51 iop->infop = bseldsk(last_dsk, iop->ioflags);
|
||||
52 break;
|
||||
53
|
||||
54 case read:
|
||||
55 case write:
|
||||
56 if (last_dsk != iop->devnum)
|
||||
57 bseldsk((last_dsk = iop->devnum), 0);
|
||||
58 /* guaranteed disk is logged on, because temp_sel in
|
||||
59 BDOSMAIN does it */
|
||||
1File: IOSYS.C Page 2
|
||||
60 hdrp = iop->infop;
|
||||
61 dparmp = hdrp->dpbp;
|
||||
62
|
||||
63 bsettrk( udiv( iop->devadr, dparmp->spt, &iosect )
|
||||
64 + dparmp->trk_off );
|
||||
65 bsetsec( bsectrn( iosect, hdrp->xlt ) );
|
||||
66 bsetdma(iop->xferadr);
|
||||
67 if ((iop->iofcn) == read) rtn = bread();
|
||||
68 else rtn = bwrite(iop->ioflags);
|
||||
69 break;
|
||||
70
|
||||
71 case flush:
|
||||
72 rtn = bflush();
|
||||
73 }
|
||||
74
|
||||
75 UNLOCK
|
||||
76 return(rtn);
|
||||
77 }
|
||||
@@ -0,0 +1,39 @@
|
||||
$ num
|
||||
BDOSMAIN.C
|
||||
BDOSMAIN.lis
|
||||
$ num
|
||||
BDOSMISC.C
|
||||
BDOSMISC.lis
|
||||
$ num
|
||||
BDOSRW.C
|
||||
BDOSRW.lis
|
||||
$ num
|
||||
CCP.C
|
||||
CCP.lis
|
||||
$ num
|
||||
CONBDOS.C
|
||||
CONBDOS.lis
|
||||
$ num
|
||||
DSKUTIL.C
|
||||
DSKUTIL.lis
|
||||
$ num
|
||||
FILEIO.C
|
||||
FILEIO.lis
|
||||
$ num
|
||||
IOSYS.C
|
||||
IOSYS.lis
|
||||
$ num
|
||||
BDOSDEF.H
|
||||
BDOSDEF.lst
|
||||
$ num
|
||||
BDOSINC.H
|
||||
BDOSINC.lst
|
||||
$ num
|
||||
BIOSDEF.H
|
||||
BIOSDEF.lst
|
||||
$ num
|
||||
CCPDEF.H
|
||||
CCPDEF.lst
|
||||
$ num
|
||||
PKTIO.H
|
||||
PKTIO.lst
|
||||
@@ -0,0 +1,83 @@
|
||||
$1cp68 bdosmain.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic bdosmain.s -ld
|
||||
era $1x.ic
|
||||
$1as68 -s 0$1 -l -u -f $1 bdosmain.s
|
||||
era bdosmain.s
|
||||
|
||||
$1cp68 bdosmisc.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic bdosmisc.s -ld
|
||||
era $1x.ic
|
||||
$1as68 -s 0$1 -l -u -f $1 bdosmisc.s
|
||||
era bdosmisc.s
|
||||
|
||||
$1cp68 bdosrw.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic bdosrw.s -ld
|
||||
era $1x.ic
|
||||
$1as68 -s 0$1 -l -u -f $1 bdosrw.s
|
||||
era bdosrw.s
|
||||
|
||||
$1cp68 conbdos.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic conbdos.s -ld
|
||||
era $1x.ic
|
||||
$1as68 -s 0$1 -l -u -f $1 conbdos.s
|
||||
era conbdos.s
|
||||
|
||||
$1cp68 dskutil.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic dskutil.s -ld
|
||||
era $1x.ic
|
||||
$1as68 -s 0$1 -l -u -f $1 dskutil.s
|
||||
era dskutil.s
|
||||
|
||||
$1cp68 fileio.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic fileio.s -ld
|
||||
era $1x.ic
|
||||
$1as68 -s 0$1 -l -u -f $1 fileio.s
|
||||
era fileio.s
|
||||
|
||||
$1cp68 iosys.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic iosys.s -ld
|
||||
era $1x.ic
|
||||
$1as68 -s 0$1 -l -u -f $1 iosys.s
|
||||
era iosys.s
|
||||
|
||||
$1cp68 ccp.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic ccp.s -ld
|
||||
era $1x.ic
|
||||
$1as68 -s 0$1 -l -u -f $1 ccp.s
|
||||
era ccp.s
|
||||
|
||||
|
||||
$1as68 -s 0$1 -l -u -f $1 bdosif.s
|
||||
$1as68 -s 0$1 -l -u -f $1 -n exceptn.s
|
||||
$1as68 -s 0$1 -l -u -f $1 pgmld.s
|
||||
$1as68 -s 0$1 -l -u -f $1 ccpbdos.s
|
||||
$1as68 -s 0$1 -l -u -f $1 ccpif.s
|
||||
$1as68 -s 0$1 -l -u -f $1 ccpload.s
|
||||
$1as68 -s 0$1 -l -u -f $1 filetyps.s
|
||||
$1as68 -s 0$1 -l -u -f $1 stack.s
|
||||
|
||||
rear $1
|
||||
595
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/pgmld.lis
Normal file
595
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/pgmld.lis
Normal file
@@ -0,0 +1,595 @@
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 1
|
||||
Source File: pgmld.s
|
||||
|
||||
1
|
||||
2 *********************************
|
||||
3 * *
|
||||
4 * Function 59 -- Program Load *
|
||||
5 * Assembly language version *
|
||||
6 * *
|
||||
7 * June 8, 1982 *
|
||||
8 * *
|
||||
9 *********************************
|
||||
10
|
||||
11 .globl _pgmld * this routine is public
|
||||
12
|
||||
13 secsize = 128 * CP/M sector size
|
||||
14
|
||||
15 * d0 always contains the return parameter from pgmld
|
||||
16 * d1 is the return register from local subroutines
|
||||
17 * a0 contains the pointer to the Load Parm Block passed to pgmld
|
||||
18
|
||||
19 * Return parameters in d0 are:
|
||||
20 * 00 - function successful
|
||||
21 * 01 - insufficient memory or bad header in file
|
||||
22 * 02 - read error on file
|
||||
23 * 03 - bad relocation information in file
|
||||
24
|
||||
25
|
||||
26 * Entry point for Program Load routine
|
||||
27 _pgmld:
|
||||
28 00000000 48E77FFE movem.l d1-d7/a0-a6, -(sp) * save everything, just to be safe
|
||||
29 00000004 206F003C move.l 60(sp),a0 * get pointer to LPB
|
||||
30 00000008 4280 clr.l d0 * start with return parm cleared
|
||||
31 0000000A 6154 bsr gethdr * get header
|
||||
32 0000000C 4A40 tst d0
|
||||
33 0000000E 662A bne lddone * if unsuccessful, return
|
||||
34 00000010 61000108 bsr setaddr * set up load addresses
|
||||
35 00000014 4A40 tst d0
|
||||
36 00000016 6622 bne lddone * if unsuccessful, return
|
||||
37 00000018 61000258 bsr rdtxt * read code and data text segments into mem
|
||||
38 0000001C 4A40 tst d0
|
||||
39 0000001E 661A bne lddone * if unsuccessful, return
|
||||
40 00000020 2E3900000016 move.l tstart,d7
|
||||
41 00000026 BEB900000024 cmp.l cseg,d7
|
||||
42 0000002C 6704 beq noreloc
|
||||
43 0000002E 61000350 bsr reloc * do relocation if necessary
|
||||
44 noreloc:
|
||||
45 00000032 4A40 tst d0
|
||||
46 00000034 6604 bne lddone
|
||||
47 00000036 610003E8 bsr setrtn * set up return parameters
|
||||
48 lddone:
|
||||
49 0000003A 222F0040 move.l 64(sp), d1
|
||||
50 0000003E 6116 bsr setdma * restore dma address
|
||||
51 00000040 4CDF7FFE movem.l (sp)+,d1-d7/a0-a6
|
||||
52 00000044 4E75 rts
|
||||
53
|
||||
54 * Subroutines
|
||||
55
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 2
|
||||
Source File: pgmld.s
|
||||
|
||||
56 readseq:
|
||||
57 * CP/M read sequential function
|
||||
58 00000046 2F00 move.l d0,-(sp) * save return parm
|
||||
59 00000048 22280000 move.l FCBPtr(a0),d1
|
||||
60 0000004C 7014 moveq #20,d0 * read seq function
|
||||
61 0000004E 4E42 trap #2 * call bdos
|
||||
62 00000050 2200 move.l d0,d1 * return parm in d1
|
||||
63 00000052 201F move.l (sp)+,d0
|
||||
64 00000054 4E75 rts
|
||||
65
|
||||
66
|
||||
67 setdma:
|
||||
68 * CP/M set dma function
|
||||
69 00000056 2F00 move.l d0,-(sp) * save return parm
|
||||
70 00000058 701A moveq #26,d0 * set dma function
|
||||
71 0000005A 4E42 trap #2 * call bdos
|
||||
72 0000005C 201F move.l (sp)+,d0 * restore d0
|
||||
73 0000005E 4E75 rts
|
||||
74
|
||||
75
|
||||
76 gethdr:
|
||||
77 * Get header into buffer in data segment
|
||||
78 00000060 22280004 move.l LoAdr(a0),d1
|
||||
79 00000064 61F0 bsr setdma
|
||||
80 00000066 61DE bsr readseq
|
||||
81 00000068 4A41 tst d1 * read ok?
|
||||
82 0000006A 6614 bne badhdr * if no, return bad
|
||||
83 0000006C 7E12 moveq #18,d7
|
||||
84 0000006E 2A680004 movea.l LoAdr(a0),a5
|
||||
85 00000072 2C7C00000000 movea.l #hdr,a6
|
||||
86 00000078 3CDD geth1: move.w (a5)+,(a6)+ * move header into hdr
|
||||
87 0000007A 51CFFFFC dbf d7,geth1
|
||||
88 0000007E 4E75 rts
|
||||
89 00000080 7002 badhdr: moveq #2,d0
|
||||
90 00000082 4E75 rts
|
||||
91
|
||||
92
|
||||
93 conflict:
|
||||
94 * input parms: d2, d3 = 4 * segment nmbr
|
||||
95 * if segment d2/4 overlaps segment d3/4, then return 1 in d1
|
||||
96 * else return 0 in d1
|
||||
97 * uses d7, a2, a3
|
||||
98 00000084 4281 clr.l d1 * assume it will work
|
||||
99 00000086 247C00000024 movea.l #cseg,a2 * a2 points to start of segment addresses
|
||||
100 0000008C 267C00000002 movea.l #csize,a3 * a3 points to start of segment lengths
|
||||
101 00000092 2E322000 move.l 0(a2,d2),d7 * get 1st seg start
|
||||
102 00000096 BEB23000 cmp.l 0(a2,d3),d7 * is 1st seg above 2nd seg?
|
||||
103 0000009A 6C0C bge conf1
|
||||
104 0000009C DEB32000 add.l 0(a3,d2),d7 * yes, find top of 1st seg
|
||||
105 000000A0 BEB23000 cmp.l 0(a2,d3),d7 * above start of 2nd seg?
|
||||
106 000000A4 6E10 bgt confbd * if yes, we have a conflict
|
||||
107 000000A6 4E75 rts * else, return good
|
||||
108 conf1:
|
||||
109 000000A8 2E323000 move.l 0(a2,d3),d7
|
||||
110 000000AC DEB33000 add.l 0(a3,d3),d7 * find top of 2nd seg
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 3
|
||||
Source File: pgmld.s
|
||||
|
||||
111 000000B0 BEB22000 cmp.l 0(a2,d2),d7 * above start of 1st seg?
|
||||
112 000000B4 6F02 ble confgd * if no, we're ok
|
||||
113 000000B6 7201 confbd: moveq.l #1,d1
|
||||
114 000000B8 4E75 confgd: rts
|
||||
115
|
||||
116
|
||||
117 trymemtp:
|
||||
118 * entry: d2 is a segment nmbr [0..4]
|
||||
119 * try to fit it at top of memory
|
||||
120 * uses d3, d6, d7, a5, a6
|
||||
121 * returns 0 in d1 if ok
|
||||
122 000000BA 2C02 move.l d2,d6 * d6 is loop counter for chksegs
|
||||
123 000000BC 5346 subq #1,d6
|
||||
124 000000BE E54A lsl #2,d2 * multiply d2 by 4
|
||||
125 000000C0 2E280008 move.l HiAdr(a0),d7 * top of mem to d7
|
||||
126
|
||||
127 chksegs:
|
||||
128 * entry: d2 = 4 * (segment nmbr to try)
|
||||
129 * d6 = (d2/4) - 1 (loop counter)
|
||||
130 * d7 = address below which to try it
|
||||
131 * check for conflicts with segments [0..d6] and low memory boundary
|
||||
132 * return 0 in d1 if no conflicts, else d1 = 1
|
||||
133 * uses d3, a5, a6
|
||||
134 000000C4 2A7C00000024 movea.l #cseg,a5
|
||||
135 000000CA 2C7C00000002 movea.l #csize,a6
|
||||
136 000000D0 9EB62000 sub.l 0(a6,d2),d7 * subtract size of segment to try
|
||||
137 000000D4 08870000 bclr #0,d7 * make it even address
|
||||
138 000000D8 2B872000 move.l d7,0(a5,d2) * insert address in segment table
|
||||
139 000000DC BEA80004 cmp.l LoAdr(a0),d7 * check for conflict with low memory
|
||||
140 000000E0 6DD4 blt confbd
|
||||
141 000000E2 4283 clr.l d3 * check for conflicts with 0..d6
|
||||
142 chk1:
|
||||
143 000000E4 619E bsr conflict
|
||||
144 000000E6 5883 addq.l #4,d3
|
||||
145 000000E8 4A81 tst.l d1 * conflict with this seg?
|
||||
146 000000EA 56CEFFF8 dbne d6,chk1 * if no, try next
|
||||
147 000000EE 4E75 rts
|
||||
148
|
||||
149
|
||||
150 fndseg:
|
||||
151 * entry: d2 is a segment nmbr [0..4]
|
||||
152 * try to fit segment d2 directly below segments 0..(d2-1)
|
||||
153 * uses d3-d7, a5, a6
|
||||
154 000000F0 2A02 move.l d2,d5 * d5 is loop counter to find fit
|
||||
155 000000F2 5385 subq.l #1,d5
|
||||
156 000000F4 23C50000003C move.l d5,temp
|
||||
157 000000FA E58A lsl.l #2,d2 * multiply segment by 4
|
||||
158 000000FC 4284 clr.l d4 * d4 is segment to try to fit below
|
||||
159 fnd1:
|
||||
160 000000FE 2C390000003C move.l temp,d6 * d6 is loop counter for chksegs
|
||||
161 00000104 2A7C00000024 movea.l #cseg,a5
|
||||
162 0000010A 2E354000 move.l 0(a5,d4),d7 * segment address to d7
|
||||
163 0000010E 61B4 bsr chksegs * check for conflicts
|
||||
164 00000110 5884 addq.l #4,d4
|
||||
165 00000112 4A81 tst.l d1
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 4
|
||||
Source File: pgmld.s
|
||||
|
||||
166 00000114 57CDFFE8 dbeq d5,fnd1 * if conflict, try next
|
||||
167 00000118 4E75 rts
|
||||
168
|
||||
169
|
||||
170 setaddr:
|
||||
171 * Set up load addresses for cseg, dseg, bss, basepg, and stack
|
||||
172 0000011A 3C3900000000 move.w magic,d6
|
||||
173 00000120 0246FFFE andi.w #$fffe,d6
|
||||
174 00000124 0C46601A cmpi.w #$601a,d6
|
||||
175 00000128 66000120 bne badadr * if magic nmbr <> 601a or 601b, skip
|
||||
176 0000012C 23F90000000E00000038 move.l bpsize,symsize
|
||||
177 00000136 2E3C00000100 move.l #256,d7
|
||||
178 0000013C 23C70000000E move.l d7,bpsize * base page is 256 bytes
|
||||
179 00000142 45F900000012 lea stksize,a2
|
||||
180 00000148 BE52 cmp (a2),d7
|
||||
181 0000014A 6D02 blt set0 * if stack size < 256, set to 256
|
||||
182 0000014C 2487 move.l d7,(a2)
|
||||
183 0000014E 0C79601B00000000 set0: cmpi.w #$601b,magic
|
||||
184 00000156 6708 beq seta
|
||||
185 00000158 4A790000001A tst.w rlbflg
|
||||
186 0000015E 670C beq set1
|
||||
187 00000160 23F90000001600000024 seta: move.l tstart,cseg * if not relocatable or hdr = $601b,
|
||||
188 0000016A 6040 bra set2 * cseg starts at tstart
|
||||
189 0000016C 082800000015 set1: btst #0,Flags(a0)
|
||||
190 00000172 6616 bne sldhi
|
||||
191 * relocatable, load low
|
||||
192 00000174 2E280004 move.l LoAdr(a0),d7
|
||||
193 00000178 DEBC00000101 add.l #$101,d7 * leave room for base page
|
||||
194 0000017E 08870000 bclr #0,d7
|
||||
195 00000182 23C700000024 move.l d7,cseg * cseg is bottom of mem + $100 (even boundary)
|
||||
196 00000188 6022 bra set2
|
||||
197 sldhi:
|
||||
198 * relocatable, load high
|
||||
199 0000018A 2E280008 move.l HiAdr(a0),d7
|
||||
200 0000018E 9EB900000002 sub.l csize,d7
|
||||
201 00000194 9EB900000006 sub.l dsize,d7
|
||||
202 0000019A 9EB90000000A sub.l bsize,d7
|
||||
203 000001A0 5987 subq.l #4,d7
|
||||
204 000001A2 08870000 bclr #0,d7 * put cseg at next even address below
|
||||
205 000001A6 23C700000024 move.l d7,cseg * high memory - (sum of sizes)
|
||||
206 set2:
|
||||
207 * Cseg has been set up. Now do dseg, bseg
|
||||
208 000001AC 0C79601B00000000 cmpi.w #$601b,magic
|
||||
209 000001B4 6616 bne set3
|
||||
210 * if magic # = 601b, take addr from hdr
|
||||
211 000001B6 23F90000001C00000028 move.l dstart,dseg
|
||||
212 000001C0 23F9000000200000002C move.l bstart,bseg
|
||||
213 000001CA 602A bra set4
|
||||
214 set3:
|
||||
215 * if short header, dseg and bseg follow cseg
|
||||
216 000001CC 2E3900000024 move.l cseg,d7
|
||||
217 000001D2 DEB900000002 add.l csize,d7
|
||||
218 000001D8 5287 addq.l #1,d7
|
||||
219 000001DA 08870000 bclr #0,d7
|
||||
220 000001DE 23C700000028 move.l d7,dseg
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 5
|
||||
Source File: pgmld.s
|
||||
|
||||
221 000001E4 DEB900000006 add.l dsize,d7
|
||||
222 000001EA 5287 addq.l #1,d7
|
||||
223 000001EC 08870000 bclr #0,d7
|
||||
224 000001F0 23C70000002C move.l d7,bseg
|
||||
225 set4:
|
||||
226 * cseg, dseg, bseg set up
|
||||
227 * now find a place for the base page and stack
|
||||
228 000001F6 7403 moveq.l #3,d2
|
||||
229 000001F8 6100FEF6 bsr fndseg * try to fit base page below cseg, dseg, bseg
|
||||
230 000001FC 4A81 tst.l d1
|
||||
231 000001FE 670A beq set5 * if found, skip
|
||||
232 00000200 7403 moveq.l #3,d2
|
||||
233 00000202 6100FEB6 bsr trymemtp * else, try top of memory
|
||||
234 00000206 4A81 tst.l d1
|
||||
235 00000208 6640 bne badadr * if fail, exit
|
||||
236 0000020A 7404 set5: moveq.l #4,d2
|
||||
237 0000020C 6100FEAC bsr trymemtp * try to fit stack at top of memory
|
||||
238 00000210 4A81 tst.l d1
|
||||
239 00000212 670A beq set6 * if ok, skip
|
||||
240 00000214 7404 moveq.l #4,d2
|
||||
241 00000216 6100FED8 bsr fndseg * else, try to fit below other segs
|
||||
242 0000021A 4A81 tst.l d1
|
||||
243 0000021C 662C bne badadr
|
||||
244 set6:
|
||||
245 * now check all segments for conflicts with low and high memory boundaries
|
||||
246 0000021E 2A7C00000024 movea.l #cseg,a5
|
||||
247 00000224 2C7C00000002 movea.l #csize,a6
|
||||
248 0000022A 4282 clr.l d2
|
||||
249 0000022C 7604 moveq #4,d3 * loop counter
|
||||
250 0000022E 2E352000 set7: move.l 0(a5,d2),d7 * get segment base
|
||||
251 00000232 BEA80004 cmp.l LoAdr(a0),d7 * above bottom of memory?
|
||||
252 00000236 6D12 blt badadr
|
||||
253 00000238 DEB62000 add.l 0(a6,d2),d7 * find top of segment
|
||||
254 0000023C BEA80008 cmp.l HiAdr(a0),d7 * below top of memory?
|
||||
255 00000240 6E08 bgt badadr
|
||||
256 00000242 5882 addq.l #4,d2 * point to next segment
|
||||
257 00000244 51CBFFE8 dbf d3,set7
|
||||
258 00000248 4E75 rts
|
||||
259 0000024A 7001 badadr: moveq.l #1,d0
|
||||
260 0000024C 4E75 rts
|
||||
261
|
||||
262
|
||||
263 movebuf:
|
||||
264 * move (d3) bytes from the base page buffer to (a2)
|
||||
265 * uses d6
|
||||
266 0000024E 227900000030 movea.l basepg,a1
|
||||
267 00000254 2C3C00000080 move.l #secsize,d6
|
||||
268 0000025A 9C7900000042 sub.w bufbyts,d6 * address to move from =
|
||||
269 00000260 D2C6 adda.w d6,a1 * (basepg) + secsize - (bufbyts)
|
||||
270 00000262 977900000042 sub.w d3,bufbyts * update # bytes buffered
|
||||
271 00000268 6002 bra moveb2
|
||||
272 0000026A 14D9 moveb1: move.b (a1)+,(a2)+ * do the move
|
||||
273 0000026C 51CBFFFC moveb2: dbf d3,moveb1
|
||||
274 00000270 4E75 rts
|
||||
275
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 6
|
||||
Source File: pgmld.s
|
||||
|
||||
276
|
||||
277 rdtxt:
|
||||
278 * Read code and data text into memory
|
||||
279 * during this routine, a2 is always the load address,
|
||||
280 * d2 is number of bytes left to load
|
||||
281 00000272 7E3F moveq #63,d7
|
||||
282 00000274 2A680004 movea.l LoAdr(a0),a5
|
||||
283 00000278 2C7900000030 movea.l basepg,a6
|
||||
284 0000027E 3CDD rdtxt1: move.w (a5)+,(a6)+ * move header sector to base page
|
||||
285 00000280 51CFFFFC dbf d7,rdtxt1
|
||||
286 00000284 3E3C0064 move.w #secsize-28,d7
|
||||
287 00000288 0C79601A00000000 cmpi.w #$601a,magic * short header?
|
||||
288 00000290 6702 beq rdtxt2
|
||||
289 00000292 5147 subq.w #8,d7
|
||||
290 00000294 33C700000042 rdtxt2: move.w d7,bufbyts * indicate # bytes of text in buffer
|
||||
291 0000029A 33FC000200000040 move.w #2,loop * do for code, data segments
|
||||
292 000002A2 247900000024 move.l cseg,a2 * start at cseg
|
||||
293 000002A8 243900000002 move.l csize,d2 * for csize bytes
|
||||
294 rdtxt3:
|
||||
295 000002AE 4283 clr.l d3
|
||||
296 000002B0 363900000042 move.w bufbyts,d3
|
||||
297 000002B6 B682 cmp.l d2,d3 * # bytes in buffer >= # bytes to load?
|
||||
298 000002B8 6D06 blt rdtxt4
|
||||
299 000002BA 2602 move.l d2,d3
|
||||
300 000002BC 6190 bsr movebuf * if yes, move # bytes to load
|
||||
301 000002BE 6048 bra finrd
|
||||
302 rdtxt4:
|
||||
303 000002C0 9483 sub.l d3,d2 * if no, update # bytes to load
|
||||
304 000002C2 618A bsr movebuf * move remainder of buffer
|
||||
305 000002C4 263C00000080 move.l #secsize,d3 * d3 = secsize fo following loop
|
||||
306 rdtxt5:
|
||||
307 000002CA B483 cmp.l d3,d2 * have at least one more full sector?
|
||||
308 000002CC 6D18 blt rdtxt6
|
||||
309 000002CE 220A move.l a2,d1
|
||||
310 000002D0 6100FD84 bsr setdma * if yes, set up dma address
|
||||
311 000002D4 6100FD70 bsr readseq * read next sector
|
||||
312 000002D8 4A41 tst.w d1
|
||||
313 000002DA 6656 bne rdbad * if no good, exit
|
||||
314 000002DC 9483 sub.l d3,d2 * decrement # bytes to load
|
||||
315 000002DE D5FC00000080 adda.l #secsize,a2 * increment dma address
|
||||
316 000002E4 60E4 bra rdtxt5
|
||||
317 rdtxt6:
|
||||
318 000002E6 4A82 tst.l d2 * any more bytes to read?
|
||||
319 000002E8 671E beq finrd
|
||||
320 000002EA 223900000030 move.l basepg,d1
|
||||
321 000002F0 6100FD64 bsr setdma
|
||||
322 000002F4 6100FD50 bsr readseq * if yes, read into base page
|
||||
323 000002F8 4A41 tst.w d1
|
||||
324 000002FA 6636 bne rdbad
|
||||
325 000002FC 33C300000042 move.w d3,bufbyts * indicate that we've buffered a sector
|
||||
326 00000302 2602 move.l d2,d3
|
||||
327 00000304 6100FF48 bsr movebuf * move remainder of segment
|
||||
328 finrd:
|
||||
329 00000308 247900000028 move.l dseg,a2 * set up to load data segment
|
||||
330 0000030E 243900000006 move.l dsize,d2
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 7
|
||||
Source File: pgmld.s
|
||||
|
||||
331 00000314 537900000040 sub.w #1,loop
|
||||
332 0000031A 6692 bne rdtxt3
|
||||
333 0000031C 24790000002C move.l bseg,a2 * clear the bss segment
|
||||
334 00000322 24390000000A move.l bsize,d2
|
||||
335 00000328 6706 beq rdtxt8
|
||||
336 0000032A 421A rdtxt7: clr.b (a2)+
|
||||
337 0000032C 5382 subq.l #1,d2
|
||||
338 0000032E 66FA bne rdtxt7
|
||||
339 00000330 4E75 rdtxt8: rts
|
||||
340
|
||||
341 00000332 7002 rdbad: moveq.l #2,d0
|
||||
342 00000334 4E75 rts
|
||||
343
|
||||
344
|
||||
345 relocword:
|
||||
346 * relocate word at (a2) based on reloc bits at (a3)
|
||||
347 * lsb of d2 indicates whether previous word was 1st half of long-word
|
||||
348 00000336 3E1B move.w (a3)+,d7 * get relocation info
|
||||
349 00000338 02470007 andi.w #7,d7 * strip off symbol table bits
|
||||
350 0000033C E34F lsl #1,d7 * multiply by 2
|
||||
351 0000033E 4EFB7002 jmp 2(pc,d7)
|
||||
352
|
||||
353 00000342 6014 bra relabs
|
||||
354 00000344 6022 bra reldata
|
||||
355 00000346 6020 bra relcode
|
||||
356 00000348 601E bra relbss
|
||||
357 0000034A 6006 bra relbad
|
||||
358 0000034C 6012 bra rellong
|
||||
359 0000034E 6002 bra relbad
|
||||
360 00000350 6006 bra relop
|
||||
361
|
||||
362 00000352 201F relbad: move.l (sp)+,d0 * pop return address
|
||||
363 00000354 7003 moveq #3,d0 * return bad relocation to main routine
|
||||
364 00000356 4E75 rts
|
||||
365
|
||||
366 relabs:
|
||||
367 00000358 08820000 relop: bclr #0,d2 * reset long word flag
|
||||
368 0000035C 4A5A tst.w (a2)+ * point to next word of segment
|
||||
369 0000035E 4E75 rts
|
||||
370
|
||||
371 rellong:
|
||||
372 00000360 08C20000 bset #0,d2 * set long word flag
|
||||
373 00000364 4A5A tst.w (a2)+ * point to next word of segment
|
||||
374 00000366 4E75 rts
|
||||
375
|
||||
376 reldata:
|
||||
377 relbss:
|
||||
378 relcode:
|
||||
379 00000368 08820000 bclr #0,d2 * long word flag set?
|
||||
380 0000036C 6608 bne relc1 * if yes, skip
|
||||
381 0000036E 3C12 move.w (a2),d6
|
||||
382 00000370 DC45 add.w d5,d6
|
||||
383 00000372 34C6 move.w d6,(a2)+
|
||||
384 00000374 4E75 rts
|
||||
385
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 8
|
||||
Source File: pgmld.s
|
||||
|
||||
386 00000376 4A62 relc1: tst.w -(a2) * point to first word of long
|
||||
387 00000378 2C12 move.l (a2),d6
|
||||
388 0000037A DC85 add.l d5,d6
|
||||
389 0000037C 24C6 move.l d6,(a2)+ * note that a2 points past long word
|
||||
390 0000037E 4E75 rts
|
||||
391
|
||||
392
|
||||
393 reloc:
|
||||
394 * Modify address references of code and data segments based on relocation bits
|
||||
395 * During this routine,
|
||||
396 * a2 points to text file to relocate
|
||||
397 * a3 points to relocation word in basepg
|
||||
398 * lsb of d2 is long word flag (set on reloc type 5, reset on next word)
|
||||
399 * d3 is # words in relocation buffer
|
||||
400 * d4 is nmbr of words left to relocate
|
||||
401 * d5 is relocation offset
|
||||
402
|
||||
403 00000380 223900000030 move.l basepg,d1
|
||||
404 00000386 6100FCCE bsr setdma * we will always read into base page
|
||||
405 * skip past the symbol table
|
||||
406 0000038A 2E3900000038 move.l symsize,d7
|
||||
407 00000390 8EFC0080 divu #secsize,d7 * calculate how many sectors to skip
|
||||
408 * note that max # symbols is 8k, which is 896 sectors of 128 bytes
|
||||
409 00000394 3C07 move.w d7,d6 * d6 is nmbr sectors to skip
|
||||
410 00000396 4847 swap d7 * d7 is nmbr bytes to skip
|
||||
411 00000398 363900000042 move.w bufbyts,d3
|
||||
412 0000039E 9647 sub.w d7,d3 * subtract bytes to skip from buffer
|
||||
413 000003A0 6C06 bge skip1
|
||||
414 000003A2 06430080 addi #secsize,d3 *if amt in buffer < # bytes to skip,
|
||||
415 000003A6 5246 addq #1,d6 * read in 1 extra sector
|
||||
416 000003A8 267900000030 skip1: move.l basepg,a3
|
||||
417 000003AE D6FC0080 adda #secsize,a3
|
||||
418 000003B2 96C3 suba.w d3,a3 * set up a3 to point to buffer
|
||||
419 000003B4 E24B lsr #1,d3 * d3 is nmbr words in buffer
|
||||
420 000003B6 600A bra skip3
|
||||
421 skip2:
|
||||
422 000003B8 6100FC8C bsr readseq * read next symbol table sector
|
||||
423 000003BC 4A41 tst.w d1
|
||||
424 000003BE 6600FF72 bne rdbad
|
||||
425 000003C2 51CEFFF4 skip3: dbf d6,skip2
|
||||
426 * we got past symbol table
|
||||
427 * a3, d3 are set up
|
||||
428 000003C6 2A3900000024 move.l cseg,d5
|
||||
429 000003CC 2445 move.l d5,a2 * relocate cseg first
|
||||
430 000003CE 9AB900000016 sub.l tstart,d5 * d5 contains the relocation offset
|
||||
431 000003D4 283900000002 move.l csize,d4 * nmbr of bytes to relocate
|
||||
432 000003DA 33FC000200000040 move.w #2,loop * we're going to relocate 2 segments
|
||||
433 reloc1:
|
||||
434 * relocate one segment
|
||||
435 000003E2 4282 clr.l d2 * clear long word flag
|
||||
436 000003E4 E28C lsr.l #1,d4 * make d4 indicate # words
|
||||
437 000003E6 601E bra reloc4
|
||||
438 reloc2:
|
||||
439 000003E8 5343 subq.w #1,d3
|
||||
440 000003EA 6A14 bpl reloc3
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 9
|
||||
Source File: pgmld.s
|
||||
|
||||
441 000003EC 6100FC58 bsr readseq * if no more words in buffer, refill it
|
||||
442 000003F0 4A41 tst.w d1
|
||||
443 000003F2 6600FF3E bne rdbad
|
||||
444 000003F6 267900000030 move.l basepg,a3
|
||||
445 000003FC 363C003F move.w #(secsize/2)-1,d3
|
||||
446 reloc3:
|
||||
447 00000400 6100FF34 bsr relocword * relocate one word
|
||||
448 00000404 5384 subq.l #1,d4
|
||||
449 reloc4:
|
||||
450 00000406 4A84 tst.l d4 * any more to relocate in this segment?
|
||||
451 00000408 66DE bne reloc2 * if yes, do it
|
||||
452 0000040A 247900000028 move.l dseg,a2 * else, set up for dseg
|
||||
453 00000410 283900000006 move.l dsize,d4
|
||||
454 00000416 537900000040 sub.w #1,loop
|
||||
455 0000041C 66C4 bne reloc1
|
||||
456 0000041E 4E75 rts
|
||||
457
|
||||
458
|
||||
459 setrtn:
|
||||
460 * Set up the return parameters in Ld Parm Blk and Base Page
|
||||
461 00000420 217900000030000C move.l basepg,BasPage(a0)
|
||||
462 00000428 2E3900000034 move.l stk,d7
|
||||
463 0000042E DEB900000012 add.l stksize,d7
|
||||
464 00000434 08870000 bclr #0,d7
|
||||
465 00000438 21470010 move.l d7,Stack(a0)
|
||||
466 0000043C 227900000030 move.l basepg,a1
|
||||
467 00000442 22E80004 move.l LoAdr(a0),(a1)+
|
||||
468 00000446 22E80008 move.l HiAdr(a0),(a1)+
|
||||
469 0000044A 22F900000024 move.l cseg,(a1)+
|
||||
470 00000450 22F900000002 move.l csize,(a1)+
|
||||
471 00000456 22F900000028 move.l dseg,(a1)+
|
||||
472 0000045C 22F900000006 move.l dsize,(a1)+
|
||||
473 00000462 22F90000002C move.l bseg,(a1)+
|
||||
474 00000468 22B90000000A move.l bsize,(a1)
|
||||
475 * find size of free memory after bss segment
|
||||
476 0000046E 2E280008 move.l HiAdr(a0),d7 * d7 contains next segment above bss
|
||||
477 00000472 2C29FFFC move.l -4(a1),d6
|
||||
478 00000476 DC99 add.l (a1)+,d6 * d6 points to start of free mem after bss
|
||||
479 00000478 2C7C00000024 movea.l #cseg,a6 * a6 points to segment to try
|
||||
480 0000047E 7A04 moveq #4,d5 * try for all segments
|
||||
481 00000480 42B90000002C clr.l bseg * but force bss not to appear
|
||||
482 00000486 BC96 setb1: cmp.l (a6),d6 * segment above bss?
|
||||
483 00000488 6206 bhi setb2
|
||||
484 0000048A BE96 cmp.l (a6),d7 * segment is above bss. Is it below previous?
|
||||
485 0000048C 6302 bls setb2
|
||||
486 0000048E 2E16 move.l (a6),d7
|
||||
487 00000490 4A9E setb2: tst.l (a6)+ * point to next segment
|
||||
488 00000492 51CDFFF2 dbf d5,setb1
|
||||
489 00000496 9E86 sub.l d6,d7 * diff between bss top and next segment abv
|
||||
490 00000498 22C7 move.l d7,(a1)+
|
||||
491 * now put disk number that we loaded from into base page
|
||||
492 0000049A 24680000 movea.l FCBPtr(a0),a2
|
||||
493 0000049E 1012 move.b (a2),d0 * get disk select byte
|
||||
494 000004A0 6606 bne setb3 * if not auto-select, skip
|
||||
495 000004A2 7019 move #25,d0
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 10
|
||||
Source File: pgmld.s
|
||||
|
||||
496 000004A4 4E42 trap #2 * get default disk
|
||||
497 000004A6 5240 addq #1,d0 * we want it in range of 1..16
|
||||
498 000004A8 12C0 setb3: move.b d0,(a1)+ * move disk number into base page
|
||||
499 000004AA 4280 clr.l d0 * function OK
|
||||
500 000004AC 4E75 rts
|
||||
501
|
||||
502
|
||||
503 00000000 .bss
|
||||
504
|
||||
505 * offsets from start of parameter block
|
||||
506 FCBPtr = 0
|
||||
507 LoAdr = 4
|
||||
508 HiAdr = 8
|
||||
509 BasPage = 12 * return parameters
|
||||
510 Stack = 16
|
||||
511 Flags = 21
|
||||
512
|
||||
513 hdr:
|
||||
514 * load file header is read into here
|
||||
515 00000000 magic: .ds.w 1
|
||||
516 00000002 csize: .ds.l 1
|
||||
517 00000006 dsize: .ds.l 1
|
||||
518 0000000A bsize: .ds.l 1
|
||||
519 0000000E bpsize: .ds.l 1 * symb tbl size is swapped with base page size
|
||||
520 00000012 stksize: .ds.l 1
|
||||
521 00000016 tstart: .ds.l 1
|
||||
522 0000001A rlbflg: .ds.w 1
|
||||
523 0000001C dstart: .ds.l 1
|
||||
524 00000020 bstart: .ds.l 1
|
||||
525
|
||||
526 00000024 cseg: .ds.l 1
|
||||
527 00000028 dseg: .ds.l 1
|
||||
528 0000002C bseg: .ds.l 1
|
||||
529 00000030 basepg: .ds.l 1
|
||||
530 00000034 stk: .ds.l 1
|
||||
531
|
||||
532 00000038 symsize: .ds.l 1
|
||||
533 0000003C temp: .ds.l 1
|
||||
534 00000040 loop: .ds.w 1
|
||||
535 00000042 bufbyts: .ds.w 1
|
||||
536
|
||||
537 00000044 .end
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 11
|
||||
Source File: pgmld.s
|
||||
|
||||
S y m b o l T a b l e
|
||||
|
||||
BasPage 0000000C ABS FCBPtr 00000000 ABS Flags 00000015 ABS HiAdr 00000008 ABS
|
||||
LoAdr 00000004 ABS Stack 00000010 ABS _pgmld 00000000 TEXT badadr 0000024A TEXT
|
||||
badhdr 00000080 TEXT basepg 00000030 BSS bpsize 0000000E BSS bseg 0000002C BSS
|
||||
bsize 0000000A BSS bstart 00000020 BSS bufbyts 00000042 BSS chk1 000000E4 TEXT
|
||||
chksegs 000000C4 TEXT conf1 000000A8 TEXT confbd 000000B6 TEXT confgd 000000B8 TEXT
|
||||
conflict 00000084 TEXT cseg 00000024 BSS csize 00000002 BSS dseg 00000028 BSS
|
||||
dsize 00000006 BSS dstart 0000001C BSS finrd 00000308 TEXT fnd1 000000FE TEXT
|
||||
fndseg 000000F0 TEXT geth1 00000078 TEXT gethdr 00000060 TEXT hdr 00000000 BSS
|
||||
lddone 0000003A TEXT loop 00000040 BSS magic 00000000 BSS moveb1 0000026A TEXT
|
||||
moveb2 0000026C TEXT movebuf 0000024E TEXT noreloc 00000032 TEXT rdbad 00000332 TEXT
|
||||
rdtxt 00000272 TEXT rdtxt1 0000027E TEXT rdtxt2 00000294 TEXT rdtxt3 000002AE TEXT
|
||||
rdtxt4 000002C0 TEXT rdtxt5 000002CA TEXT rdtxt6 000002E6 TEXT rdtxt7 0000032A TEXT
|
||||
rdtxt8 00000330 TEXT readseq 00000046 TEXT relabs 00000358 TEXT relbad 00000352 TEXT
|
||||
relbss 00000368 TEXT relc1 00000376 TEXT relcode 00000368 TEXT reldata 00000368 TEXT
|
||||
rellong 00000360 TEXT reloc 00000380 TEXT reloc1 000003E2 TEXT reloc2 000003E8 TEXT
|
||||
reloc3 00000400 TEXT reloc4 00000406 TEXT relocwor 00000336 TEXT relop 00000358 TEXT
|
||||
rlbflg 0000001A BSS secsize 00000080 ABS set0 0000014E TEXT set1 0000016C TEXT
|
||||
set2 000001AC TEXT set3 000001CC TEXT set4 000001F6 TEXT set5 0000020A TEXT
|
||||
set6 0000021E TEXT set7 0000022E TEXT seta 00000160 TEXT setaddr 0000011A TEXT
|
||||
setb1 00000486 TEXT setb2 00000490 TEXT setb3 000004A8 TEXT setdma 00000056 TEXT
|
||||
setrtn 00000420 TEXT skip1 000003A8 TEXT skip2 000003B8 TEXT skip3 000003C2 TEXT
|
||||
sldhi 0000018A TEXT stk 00000034 BSS stksize 00000012 BSS symsize 00000038 BSS
|
||||
temp 0000003C BSS trymemtp 000000BA TEXT tstart 00000016 BSS
|
||||
537
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/pgmld.s
Normal file
537
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/bdos/pgmld.s
Normal file
@@ -0,0 +1,537 @@
|
||||
|
||||
*********************************
|
||||
* *
|
||||
* Function 59 -- Program Load *
|
||||
* Assembly language version *
|
||||
* *
|
||||
* June 8, 1982 *
|
||||
* *
|
||||
*********************************
|
||||
|
||||
.globl _pgmld * this routine is public
|
||||
|
||||
secsize = 128 * CP/M sector size
|
||||
|
||||
* d0 always contains the return parameter from pgmld
|
||||
* d1 is the return register from local subroutines
|
||||
* a0 contains the pointer to the Load Parm Block passed to pgmld
|
||||
|
||||
* Return parameters in d0 are:
|
||||
* 00 - function successful
|
||||
* 01 - insufficient memory or bad header in file
|
||||
* 02 - read error on file
|
||||
* 03 - bad relocation information in file
|
||||
|
||||
|
||||
* Entry point for Program Load routine
|
||||
_pgmld:
|
||||
movem.l d1-d7/a0-a6, -(sp) * save everything, just to be safe
|
||||
move.l 60(sp),a0 * get pointer to LPB
|
||||
clr.l d0 * start with return parm cleared
|
||||
bsr gethdr * get header
|
||||
tst d0
|
||||
bne lddone * if unsuccessful, return
|
||||
bsr setaddr * set up load addresses
|
||||
tst d0
|
||||
bne lddone * if unsuccessful, return
|
||||
bsr rdtxt * read code and data text segments into mem
|
||||
tst d0
|
||||
bne lddone * if unsuccessful, return
|
||||
move.l tstart,d7
|
||||
cmp.l cseg,d7
|
||||
beq noreloc
|
||||
bsr reloc * do relocation if necessary
|
||||
noreloc:
|
||||
tst d0
|
||||
bne lddone
|
||||
bsr setrtn * set up return parameters
|
||||
lddone:
|
||||
move.l 64(sp), d1
|
||||
bsr setdma * restore dma address
|
||||
movem.l (sp)+,d1-d7/a0-a6
|
||||
rts
|
||||
|
||||
* Subroutines
|
||||
|
||||
readseq:
|
||||
* CP/M read sequential function
|
||||
move.l d0,-(sp) * save return parm
|
||||
move.l FCBPtr(a0),d1
|
||||
moveq #20,d0 * read seq function
|
||||
trap #2 * call bdos
|
||||
move.l d0,d1 * return parm in d1
|
||||
move.l (sp)+,d0
|
||||
rts
|
||||
|
||||
|
||||
setdma:
|
||||
* CP/M set dma function
|
||||
move.l d0,-(sp) * save return parm
|
||||
moveq #26,d0 * set dma function
|
||||
trap #2 * call bdos
|
||||
move.l (sp)+,d0 * restore d0
|
||||
rts
|
||||
|
||||
|
||||
gethdr:
|
||||
* Get header into buffer in data segment
|
||||
move.l LoAdr(a0),d1
|
||||
bsr setdma
|
||||
bsr readseq
|
||||
tst d1 * read ok?
|
||||
bne badhdr * if no, return bad
|
||||
moveq #18,d7
|
||||
movea.l LoAdr(a0),a5
|
||||
movea.l #hdr,a6
|
||||
geth1: move.w (a5)+,(a6)+ * move header into hdr
|
||||
dbf d7,geth1
|
||||
rts
|
||||
badhdr: moveq #2,d0
|
||||
rts
|
||||
|
||||
|
||||
conflict:
|
||||
* input parms: d2, d3 = 4 * segment nmbr
|
||||
* if segment d2/4 overlaps segment d3/4, then return 1 in d1
|
||||
* else return 0 in d1
|
||||
* uses d7, a2, a3
|
||||
clr.l d1 * assume it will work
|
||||
movea.l #cseg,a2 * a2 points to start of segment addresses
|
||||
movea.l #csize,a3 * a3 points to start of segment lengths
|
||||
move.l 0(a2,d2),d7 * get 1st seg start
|
||||
cmp.l 0(a2,d3),d7 * is 1st seg above 2nd seg?
|
||||
bge conf1
|
||||
add.l 0(a3,d2),d7 * yes, find top of 1st seg
|
||||
cmp.l 0(a2,d3),d7 * above start of 2nd seg?
|
||||
bgt confbd * if yes, we have a conflict
|
||||
rts * else, return good
|
||||
conf1:
|
||||
move.l 0(a2,d3),d7
|
||||
add.l 0(a3,d3),d7 * find top of 2nd seg
|
||||
cmp.l 0(a2,d2),d7 * above start of 1st seg?
|
||||
ble confgd * if no, we're ok
|
||||
confbd: moveq.l #1,d1
|
||||
confgd: rts
|
||||
|
||||
|
||||
trymemtp:
|
||||
* entry: d2 is a segment nmbr [0..4]
|
||||
* try to fit it at top of memory
|
||||
* uses d3, d6, d7, a5, a6
|
||||
* returns 0 in d1 if ok
|
||||
move.l d2,d6 * d6 is loop counter for chksegs
|
||||
subq #1,d6
|
||||
lsl #2,d2 * multiply d2 by 4
|
||||
move.l HiAdr(a0),d7 * top of mem to d7
|
||||
|
||||
chksegs:
|
||||
* entry: d2 = 4 * (segment nmbr to try)
|
||||
* d6 = (d2/4) - 1 (loop counter)
|
||||
* d7 = address below which to try it
|
||||
* check for conflicts with segments [0..d6] and low memory boundary
|
||||
* return 0 in d1 if no conflicts, else d1 = 1
|
||||
* uses d3, a5, a6
|
||||
movea.l #cseg,a5
|
||||
movea.l #csize,a6
|
||||
sub.l 0(a6,d2),d7 * subtract size of segment to try
|
||||
bclr #0,d7 * make it even address
|
||||
move.l d7,0(a5,d2) * insert address in segment table
|
||||
cmp.l LoAdr(a0),d7 * check for conflict with low memory
|
||||
blt confbd
|
||||
clr.l d3 * check for conflicts with 0..d6
|
||||
chk1:
|
||||
bsr conflict
|
||||
addq.l #4,d3
|
||||
tst.l d1 * conflict with this seg?
|
||||
dbne d6,chk1 * if no, try next
|
||||
rts
|
||||
|
||||
|
||||
fndseg:
|
||||
* entry: d2 is a segment nmbr [0..4]
|
||||
* try to fit segment d2 directly below segments 0..(d2-1)
|
||||
* uses d3-d7, a5, a6
|
||||
move.l d2,d5 * d5 is loop counter to find fit
|
||||
subq.l #1,d5
|
||||
move.l d5,temp
|
||||
lsl.l #2,d2 * multiply segment by 4
|
||||
clr.l d4 * d4 is segment to try to fit below
|
||||
fnd1:
|
||||
move.l temp,d6 * d6 is loop counter for chksegs
|
||||
movea.l #cseg,a5
|
||||
move.l 0(a5,d4),d7 * segment address to d7
|
||||
bsr chksegs * check for conflicts
|
||||
addq.l #4,d4
|
||||
tst.l d1
|
||||
dbeq d5,fnd1 * if conflict, try next
|
||||
rts
|
||||
|
||||
|
||||
setaddr:
|
||||
* Set up load addresses for cseg, dseg, bss, basepg, and stack
|
||||
move.w magic,d6
|
||||
andi.w #$fffe,d6
|
||||
cmpi.w #$601a,d6
|
||||
bne badadr * if magic nmbr <> 601a or 601b, skip
|
||||
move.l bpsize,symsize
|
||||
move.l #256,d7
|
||||
move.l d7,bpsize * base page is 256 bytes
|
||||
lea stksize,a2
|
||||
cmp (a2),d7
|
||||
blt set0 * if stack size < 256, set to 256
|
||||
move.l d7,(a2)
|
||||
set0: cmpi.w #$601b,magic
|
||||
beq seta
|
||||
tst.w rlbflg
|
||||
beq set1
|
||||
seta: move.l tstart,cseg * if not relocatable or hdr = $601b,
|
||||
bra set2 * cseg starts at tstart
|
||||
set1: btst #0,Flags(a0)
|
||||
bne sldhi
|
||||
* relocatable, load low
|
||||
move.l LoAdr(a0),d7
|
||||
add.l #$101,d7 * leave room for base page
|
||||
bclr #0,d7
|
||||
move.l d7,cseg * cseg is bottom of mem + $100 (even boundary)
|
||||
bra set2
|
||||
sldhi:
|
||||
* relocatable, load high
|
||||
move.l HiAdr(a0),d7
|
||||
sub.l csize,d7
|
||||
sub.l dsize,d7
|
||||
sub.l bsize,d7
|
||||
subq.l #4,d7
|
||||
bclr #0,d7 * put cseg at next even address below
|
||||
move.l d7,cseg * high memory - (sum of sizes)
|
||||
set2:
|
||||
* Cseg has been set up. Now do dseg, bseg
|
||||
cmpi.w #$601b,magic
|
||||
bne set3
|
||||
* if magic # = 601b, take addr from hdr
|
||||
move.l dstart,dseg
|
||||
move.l bstart,bseg
|
||||
bra set4
|
||||
set3:
|
||||
* if short header, dseg and bseg follow cseg
|
||||
move.l cseg,d7
|
||||
add.l csize,d7
|
||||
addq.l #1,d7
|
||||
bclr #0,d7
|
||||
move.l d7,dseg
|
||||
add.l dsize,d7
|
||||
addq.l #1,d7
|
||||
bclr #0,d7
|
||||
move.l d7,bseg
|
||||
set4:
|
||||
* cseg, dseg, bseg set up
|
||||
* now find a place for the base page and stack
|
||||
moveq.l #3,d2
|
||||
bsr fndseg * try to fit base page below cseg, dseg, bseg
|
||||
tst.l d1
|
||||
beq set5 * if found, skip
|
||||
moveq.l #3,d2
|
||||
bsr trymemtp * else, try top of memory
|
||||
tst.l d1
|
||||
bne badadr * if fail, exit
|
||||
set5: moveq.l #4,d2
|
||||
bsr trymemtp * try to fit stack at top of memory
|
||||
tst.l d1
|
||||
beq set6 * if ok, skip
|
||||
moveq.l #4,d2
|
||||
bsr fndseg * else, try to fit below other segs
|
||||
tst.l d1
|
||||
bne badadr
|
||||
set6:
|
||||
* now check all segments for conflicts with low and high memory boundaries
|
||||
movea.l #cseg,a5
|
||||
movea.l #csize,a6
|
||||
clr.l d2
|
||||
moveq #4,d3 * loop counter
|
||||
set7: move.l 0(a5,d2),d7 * get segment base
|
||||
cmp.l LoAdr(a0),d7 * above bottom of memory?
|
||||
blt badadr
|
||||
add.l 0(a6,d2),d7 * find top of segment
|
||||
cmp.l HiAdr(a0),d7 * below top of memory?
|
||||
bgt badadr
|
||||
addq.l #4,d2 * point to next segment
|
||||
dbf d3,set7
|
||||
rts
|
||||
badadr: moveq.l #1,d0
|
||||
rts
|
||||
|
||||
|
||||
movebuf:
|
||||
* move (d3) bytes from the base page buffer to (a2)
|
||||
* uses d6
|
||||
movea.l basepg,a1
|
||||
move.l #secsize,d6
|
||||
sub.w bufbyts,d6 * address to move from =
|
||||
adda.w d6,a1 * (basepg) + secsize - (bufbyts)
|
||||
sub.w d3,bufbyts * update # bytes buffered
|
||||
bra moveb2
|
||||
moveb1: move.b (a1)+,(a2)+ * do the move
|
||||
moveb2: dbf d3,moveb1
|
||||
rts
|
||||
|
||||
|
||||
rdtxt:
|
||||
* Read code and data text into memory
|
||||
* during this routine, a2 is always the load address,
|
||||
* d2 is number of bytes left to load
|
||||
moveq #63,d7
|
||||
movea.l LoAdr(a0),a5
|
||||
movea.l basepg,a6
|
||||
rdtxt1: move.w (a5)+,(a6)+ * move header sector to base page
|
||||
dbf d7,rdtxt1
|
||||
move.w #secsize-28,d7
|
||||
cmpi.w #$601a,magic * short header?
|
||||
beq rdtxt2
|
||||
subq.w #8,d7
|
||||
rdtxt2: move.w d7,bufbyts * indicate # bytes of text in buffer
|
||||
move.w #2,loop * do for code, data segments
|
||||
move.l cseg,a2 * start at cseg
|
||||
move.l csize,d2 * for csize bytes
|
||||
rdtxt3:
|
||||
clr.l d3
|
||||
move.w bufbyts,d3
|
||||
cmp.l d2,d3 * # bytes in buffer >= # bytes to load?
|
||||
blt rdtxt4
|
||||
move.l d2,d3
|
||||
bsr movebuf * if yes, move # bytes to load
|
||||
bra finrd
|
||||
rdtxt4:
|
||||
sub.l d3,d2 * if no, update # bytes to load
|
||||
bsr movebuf * move remainder of buffer
|
||||
move.l #secsize,d3 * d3 = secsize fo following loop
|
||||
rdtxt5:
|
||||
cmp.l d3,d2 * have at least one more full sector?
|
||||
blt rdtxt6
|
||||
move.l a2,d1
|
||||
bsr setdma * if yes, set up dma address
|
||||
bsr readseq * read next sector
|
||||
tst.w d1
|
||||
bne rdbad * if no good, exit
|
||||
sub.l d3,d2 * decrement # bytes to load
|
||||
adda.l #secsize,a2 * increment dma address
|
||||
bra rdtxt5
|
||||
rdtxt6:
|
||||
tst.l d2 * any more bytes to read?
|
||||
beq finrd
|
||||
move.l basepg,d1
|
||||
bsr setdma
|
||||
bsr readseq * if yes, read into base page
|
||||
tst.w d1
|
||||
bne rdbad
|
||||
move.w d3,bufbyts * indicate that we've buffered a sector
|
||||
move.l d2,d3
|
||||
bsr movebuf * move remainder of segment
|
||||
finrd:
|
||||
move.l dseg,a2 * set up to load data segment
|
||||
move.l dsize,d2
|
||||
sub.w #1,loop
|
||||
bne rdtxt3
|
||||
move.l bseg,a2 * clear the bss segment
|
||||
move.l bsize,d2
|
||||
beq rdtxt8
|
||||
rdtxt7: clr.b (a2)+
|
||||
subq.l #1,d2
|
||||
bne rdtxt7
|
||||
rdtxt8: rts
|
||||
|
||||
rdbad: moveq.l #2,d0
|
||||
rts
|
||||
|
||||
|
||||
relocword:
|
||||
* relocate word at (a2) based on reloc bits at (a3)
|
||||
* lsb of d2 indicates whether previous word was 1st half of long-word
|
||||
move.w (a3)+,d7 * get relocation info
|
||||
andi.w #7,d7 * strip off symbol table bits
|
||||
lsl #1,d7 * multiply by 2
|
||||
jmp 2(pc,d7)
|
||||
|
||||
bra relabs
|
||||
bra reldata
|
||||
bra relcode
|
||||
bra relbss
|
||||
bra relbad
|
||||
bra rellong
|
||||
bra relbad
|
||||
bra relop
|
||||
|
||||
relbad: move.l (sp)+,d0 * pop return address
|
||||
moveq #3,d0 * return bad relocation to main routine
|
||||
rts
|
||||
|
||||
relabs:
|
||||
relop: bclr #0,d2 * reset long word flag
|
||||
tst.w (a2)+ * point to next word of segment
|
||||
rts
|
||||
|
||||
rellong:
|
||||
bset #0,d2 * set long word flag
|
||||
tst.w (a2)+ * point to next word of segment
|
||||
rts
|
||||
|
||||
reldata:
|
||||
relbss:
|
||||
relcode:
|
||||
bclr #0,d2 * long word flag set?
|
||||
bne relc1 * if yes, skip
|
||||
move.w (a2),d6
|
||||
add.w d5,d6
|
||||
move.w d6,(a2)+
|
||||
rts
|
||||
|
||||
relc1: tst.w -(a2) * point to first word of long
|
||||
move.l (a2),d6
|
||||
add.l d5,d6
|
||||
move.l d6,(a2)+ * note that a2 points past long word
|
||||
rts
|
||||
|
||||
|
||||
reloc:
|
||||
* Modify address references of code and data segments based on relocation bits
|
||||
* During this routine,
|
||||
* a2 points to text file to relocate
|
||||
* a3 points to relocation word in basepg
|
||||
* lsb of d2 is long word flag (set on reloc type 5, reset on next word)
|
||||
* d3 is # words in relocation buffer
|
||||
* d4 is nmbr of words left to relocate
|
||||
* d5 is relocation offset
|
||||
|
||||
move.l basepg,d1
|
||||
bsr setdma * we will always read into base page
|
||||
* skip past the symbol table
|
||||
move.l symsize,d7
|
||||
divu #secsize,d7 * calculate how many sectors to skip
|
||||
* note that max # symbols is 8k, which is 896 sectors of 128 bytes
|
||||
move.w d7,d6 * d6 is nmbr sectors to skip
|
||||
swap d7 * d7 is nmbr bytes to skip
|
||||
move.w bufbyts,d3
|
||||
sub.w d7,d3 * subtract bytes to skip from buffer
|
||||
bge skip1
|
||||
addi #secsize,d3 *if amt in buffer < # bytes to skip,
|
||||
addq #1,d6 * read in 1 extra sector
|
||||
skip1: move.l basepg,a3
|
||||
adda #secsize,a3
|
||||
suba.w d3,a3 * set up a3 to point to buffer
|
||||
lsr #1,d3 * d3 is nmbr words in buffer
|
||||
bra skip3
|
||||
skip2:
|
||||
bsr readseq * read next symbol table sector
|
||||
tst.w d1
|
||||
bne rdbad
|
||||
skip3: dbf d6,skip2
|
||||
* we got past symbol table
|
||||
* a3, d3 are set up
|
||||
move.l cseg,d5
|
||||
move.l d5,a2 * relocate cseg first
|
||||
sub.l tstart,d5 * d5 contains the relocation offset
|
||||
move.l csize,d4 * nmbr of bytes to relocate
|
||||
move.w #2,loop * we're going to relocate 2 segments
|
||||
reloc1:
|
||||
* relocate one segment
|
||||
clr.l d2 * clear long word flag
|
||||
lsr.l #1,d4 * make d4 indicate # words
|
||||
bra reloc4
|
||||
reloc2:
|
||||
subq.w #1,d3
|
||||
bpl reloc3
|
||||
bsr readseq * if no more words in buffer, refill it
|
||||
tst.w d1
|
||||
bne rdbad
|
||||
move.l basepg,a3
|
||||
move.w #(secsize/2)-1,d3
|
||||
reloc3:
|
||||
bsr relocword * relocate one word
|
||||
subq.l #1,d4
|
||||
reloc4:
|
||||
tst.l d4 * any more to relocate in this segment?
|
||||
bne reloc2 * if yes, do it
|
||||
move.l dseg,a2 * else, set up for dseg
|
||||
move.l dsize,d4
|
||||
sub.w #1,loop
|
||||
bne reloc1
|
||||
rts
|
||||
|
||||
|
||||
setrtn:
|
||||
* Set up the return parameters in Ld Parm Blk and Base Page
|
||||
move.l basepg,BasPage(a0)
|
||||
move.l stk,d7
|
||||
add.l stksize,d7
|
||||
bclr #0,d7
|
||||
move.l d7,Stack(a0)
|
||||
move.l basepg,a1
|
||||
move.l LoAdr(a0),(a1)+
|
||||
move.l HiAdr(a0),(a1)+
|
||||
move.l cseg,(a1)+
|
||||
move.l csize,(a1)+
|
||||
move.l dseg,(a1)+
|
||||
move.l dsize,(a1)+
|
||||
move.l bseg,(a1)+
|
||||
move.l bsize,(a1)
|
||||
* find size of free memory after bss segment
|
||||
move.l HiAdr(a0),d7 * d7 contains next segment above bss
|
||||
move.l -4(a1),d6
|
||||
add.l (a1)+,d6 * d6 points to start of free mem after bss
|
||||
movea.l #cseg,a6 * a6 points to segment to try
|
||||
moveq #4,d5 * try for all segments
|
||||
clr.l bseg * but force bss not to appear
|
||||
setb1: cmp.l (a6),d6 * segment above bss?
|
||||
bhi setb2
|
||||
cmp.l (a6),d7 * segment is above bss. Is it below previous?
|
||||
bls setb2
|
||||
move.l (a6),d7
|
||||
setb2: tst.l (a6)+ * point to next segment
|
||||
dbf d5,setb1
|
||||
sub.l d6,d7 * diff between bss top and next segment abv
|
||||
move.l d7,(a1)+
|
||||
* now put disk number that we loaded from into base page
|
||||
movea.l FCBPtr(a0),a2
|
||||
move.b (a2),d0 * get disk select byte
|
||||
bne setb3 * if not auto-select, skip
|
||||
move #25,d0
|
||||
trap #2 * get default disk
|
||||
addq #1,d0 * we want it in range of 1..16
|
||||
setb3: move.b d0,(a1)+ * move disk number into base page
|
||||
clr.l d0 * function OK
|
||||
rts
|
||||
|
||||
|
||||
.bss
|
||||
|
||||
* offsets from start of parameter block
|
||||
FCBPtr = 0
|
||||
LoAdr = 4
|
||||
HiAdr = 8
|
||||
BasPage = 12 * return parameters
|
||||
Stack = 16
|
||||
Flags = 21
|
||||
|
||||
hdr:
|
||||
* load file header is read into here
|
||||
magic: .ds.w 1
|
||||
csize: .ds.l 1
|
||||
dsize: .ds.l 1
|
||||
bsize: .ds.l 1
|
||||
bpsize: .ds.l 1 * symb tbl size is swapped with base page size
|
||||
stksize: .ds.l 1
|
||||
tstart: .ds.l 1
|
||||
rlbflg: .ds.w 1
|
||||
dstart: .ds.l 1
|
||||
bstart: .ds.l 1
|
||||
|
||||
cseg: .ds.l 1
|
||||
dseg: .ds.l 1
|
||||
bseg: .ds.l 1
|
||||
basepg: .ds.l 1
|
||||
stk: .ds.l 1
|
||||
|
||||
symsize: .ds.l 1
|
||||
temp: .ds.l 1
|
||||
loop: .ds.w 1
|
||||
bufbyts: .ds.w 1
|
||||
|
||||
.end
|
||||
@@ -0,0 +1,57 @@
|
||||
/********************************************************
|
||||
* *
|
||||
* CP/M-68K header file *
|
||||
* Copyright (c) 1982 by Digital Research, Inc. *
|
||||
* Structure definitions for doing I/O in packets *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
/* May use this information structure instead of disk parameter header and
|
||||
disk parameter block in future, but for now it's unused
|
||||
struct dskinfo
|
||||
{
|
||||
UBYTE *dbuffp;
|
||||
UBYTE *csv;
|
||||
UBYTE *alv;
|
||||
UBYTE blksize;
|
||||
UBYTE didummy;
|
||||
UWORD dskmax;
|
||||
UWORD dirmax;
|
||||
UWORD chksize;
|
||||
};
|
||||
*/
|
||||
|
||||
struct iopb
|
||||
{
|
||||
UBYTE iofcn; /* function number, see defines below */
|
||||
UBYTE ioflags; /* used for login flag and write flag */
|
||||
UBYTE devtype; /* device type, see defines below */
|
||||
/* currently unused */
|
||||
UBYTE devnum; /* device number, or, devtype and devnum
|
||||
taken together form int device number */
|
||||
LONG devadr; /* item nmbr on device to start xfer at */
|
||||
/* note -- item is sector for disks, byte for char devs */
|
||||
UWORD xferlen; /* number items to transfer */
|
||||
UBYTE *xferadr; /* memory address to xfer to/from */
|
||||
struct dph *infop; /* pointer to disk parameter header */
|
||||
/* return parm for fcn 0, input for rest */
|
||||
};
|
||||
|
||||
|
||||
/* Definitions for iofcn, the function number */
|
||||
#define sel_info 0 /* select and return info on device */
|
||||
#define read 1
|
||||
#define write 2
|
||||
#define flush 3
|
||||
#define status 4 /* not currently used */
|
||||
|
||||
|
||||
/* Definitions for devtype, the device type */
|
||||
/* This field not currently used */
|
||||
#define console 0
|
||||
#define printer 1
|
||||
#define disk 2
|
||||
#define memory 3 /* gets TPA boundaries */
|
||||
#define redir 4 /* read/write IOByte */
|
||||
#define exc_vec 5 /* set exception vector */
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
1File: PKTIO.H Page 1
|
||||
1 /********************************************************
|
||||
2 * *
|
||||
3 * CP/M-68K header file *
|
||||
4 * Copyright (c) 1982 by Digital Research, Inc. *
|
||||
5 * Structure definitions for doing I/O in packets *
|
||||
6 * *
|
||||
7 ********************************************************/
|
||||
8
|
||||
9 /* May use this information structure instead of disk parameter header and
|
||||
10 disk parameter block in future, but for now it's unused
|
||||
11 struct dskinfo
|
||||
12 {
|
||||
13 UBYTE *dbuffp;
|
||||
14 UBYTE *csv;
|
||||
15 UBYTE *alv;
|
||||
16 UBYTE blksize;
|
||||
17 UBYTE didummy;
|
||||
18 UWORD dskmax;
|
||||
19 UWORD dirmax;
|
||||
20 UWORD chksize;
|
||||
21 };
|
||||
22 */
|
||||
23
|
||||
24 struct iopb
|
||||
25 {
|
||||
26 UBYTE iofcn; /* function number, see defines below */
|
||||
27 UBYTE ioflags; /* used for login flag and write flag */
|
||||
28 UBYTE devtype; /* device type, see defines below */
|
||||
29 /* currently unused */
|
||||
30 UBYTE devnum; /* device number, or, devtype and devnum
|
||||
31 taken together form int device number */
|
||||
32 LONG devadr; /* item nmbr on device to start xfer at */
|
||||
33 /* note -- item is sector for disks, byte for char devs */
|
||||
34 UWORD xferlen; /* number items to transfer */
|
||||
35 UBYTE *xferadr; /* memory address to xfer to/from */
|
||||
36 struct dph *infop; /* pointer to disk parameter header */
|
||||
37 /* return parm for fcn 0, input for rest */
|
||||
38 };
|
||||
39
|
||||
40
|
||||
41 /* Definitions for iofcn, the function number */
|
||||
42 #define sel_info 0 /* select and return info on device */
|
||||
43 #define read 1
|
||||
44 #define write 2
|
||||
45 #define flush 3
|
||||
46 #define status 4 /* not currently used */
|
||||
47
|
||||
48
|
||||
49 /* Definitions for devtype, the device type */
|
||||
50 /* This field not currently used */
|
||||
51 #define console 0
|
||||
52 #define printer 1
|
||||
53 #define disk 2
|
||||
54 #define memory 3 /* gets TPA boundaries */
|
||||
55 #define redir 4 /* read/write IOByte */
|
||||
56 #define exc_vec 5 /* set exception vector */
|
||||
57
|
||||
@@ -0,0 +1,4 @@
|
||||
$1ar68 rvf $1 cpmlib ccpif.o ccpbdos.o ccpload.o ccp.o bdosif.o conbdos.o
|
||||
$1ar68 rvf $1 cpmlib bdosmisc.o dskutil.o fileio.o bdosrw.o bdosmain.o
|
||||
$1ar68 rvf $1 cpmlib iosys.o pgmld.o exceptn.o filetyps.o stack.o
|
||||
era *.o
|
||||
@@ -0,0 +1,25 @@
|
||||
E:SEND REAR.SUB
|
||||
E:SEND MAKE.SUB
|
||||
E:SEND BDOSDEF.H
|
||||
E:SEND BDOSIF.S
|
||||
E:SEND BDOSINC.H
|
||||
E:SEND BDOSMAIN.C
|
||||
E:SEND BDOSMISC.C
|
||||
E:SEND BDOSRW.C
|
||||
E:SEND BIOSDEF.H
|
||||
E:SEND CONBDOS.C
|
||||
E:SEND CPMC.DOC
|
||||
E:SEND DSKUTIL.C
|
||||
E:SEND EXCEPTN.S
|
||||
E:SEND FILEIO.C
|
||||
E:SEND IOSYS.C
|
||||
E:SEND PGMLD.S
|
||||
E:SEND PKTIO.H
|
||||
E:SEND CCP.C
|
||||
E:SEND CCPBDOS.S
|
||||
E:SEND CCPDEF.H
|
||||
E:SEND CCPIF.S
|
||||
E:SEND CCPLOAD.S
|
||||
E:SEND FILETYPS.S
|
||||
E:SEND STACK.S
|
||||
E:SEND SEND2.SUB
|
||||
@@ -0,0 +1,24 @@
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 1
|
||||
Source File: stack.s
|
||||
|
||||
1 *************************************************************************
|
||||
2 * *
|
||||
3 * THIS IS THE SYSTEM STACK AREA *
|
||||
4 * *
|
||||
5 * *
|
||||
6 * THIS IS THE DUAL PROCESSOR,ROMABLE CP/M-68K SYSTEM *
|
||||
7 * ================================================== *
|
||||
8 *************************************************************************
|
||||
9
|
||||
10 .globl stack
|
||||
11 00000000 .bss
|
||||
12 00000000 .ds.l 400
|
||||
13 stack:
|
||||
14 00000640 .ds.w 1
|
||||
15 00000642 .end
|
||||
C P / M 6 8 0 0 0 A s s e m b l e r Revision 02.03 Page 2
|
||||
Source File: stack.s
|
||||
|
||||
S y m b o l T a b l e
|
||||
|
||||
stack 00000640 BSS
|
||||
@@ -0,0 +1,15 @@
|
||||
*************************************************************************
|
||||
* *
|
||||
* THIS IS THE SYSTEM STACK AREA *
|
||||
* *
|
||||
* *
|
||||
* THIS IS THE DUAL PROCESSOR,ROMABLE CP/M-68K SYSTEM *
|
||||
* ================================================== *
|
||||
*************************************************************************
|
||||
|
||||
.globl stack
|
||||
.bss
|
||||
.ds.l 400
|
||||
stack:
|
||||
.ds.w 1
|
||||
.end
|
||||
@@ -0,0 +1,26 @@
|
||||
vax REAR.SUB s
|
||||
vax MAKE.SUB s
|
||||
vax BDOSDEF.H s
|
||||
vax BDOSIF.S s
|
||||
vax BDOSINC.H s
|
||||
vax BDOSMAIN.C s
|
||||
vax BDOSMISC.C s
|
||||
vax BDOSRW.C s
|
||||
vax BIOSDEF.H s
|
||||
vax CONBDOS.C s
|
||||
vax CPMC.DOC s
|
||||
vax DSKUTIL.C s
|
||||
vax EXCEPTN.S s
|
||||
vax FILEIO.C s
|
||||
vax IOSYS.C s
|
||||
vax PGMLD.S s
|
||||
vax PKTIO.H s
|
||||
vax CCP.C s
|
||||
vax CCPBDOS.S s
|
||||
vax CCPDEF.H s
|
||||
vax CCPIF.S s
|
||||
vax CCPLOAD.S s
|
||||
vax FILETYPS.S s
|
||||
vax STACK.S s
|
||||
vax SEND2.SUB s
|
||||
vax up2.sub s
|
||||
@@ -0,0 +1,25 @@
|
||||
$ bdos
|
||||
$ !
|
||||
$ ! VMS command file to build CPMLIB using cross tools
|
||||
$ !
|
||||
$ set noon
|
||||
$ cc68 bdosmain
|
||||
$ cc68 bdosmisc
|
||||
$ cc68 bdosrw
|
||||
$ cc68 conbdos
|
||||
$ cc68 dskutil
|
||||
$ cc68 fileio
|
||||
$ cc68 iosys
|
||||
$ cc68 ccp
|
||||
$ as68 -l -u bdosif.s
|
||||
$ as68 -l -u -n exceptn.s
|
||||
$ as68 -l -u pgmld.s
|
||||
$ as68 -l -u ccpbdos.s
|
||||
$ as68 -l -u ccpif.s
|
||||
$ as68 -l -u ccpload.s
|
||||
$ as68 -l -u filetyps.s
|
||||
$ as68 -l -u stack.s
|
||||
$ ar68 r cpmlib ccpif.o ccpbdos.o ccpload.o ccp.o bdosif.o conbdos.o
|
||||
$ ar68 r cpmlib bdosmisc.o dskutil.o fileio.o bdosrw.o bdosmain.o
|
||||
$ ar68 r cpmlib iosys.o pgmld.o exceptn.o filetyps.o stack.o
|
||||
$ del *.o;*
|
||||
@@ -0,0 +1,30 @@
|
||||
$ set noon
|
||||
$ vsend BDOSDEF.H
|
||||
$ vsend BDOSIF.S
|
||||
$ vsend BDOSINC.H
|
||||
$ vsend BDOSMAIN.C
|
||||
$ vsend BDOSMISC.C
|
||||
$ vsend BDOSRW.C
|
||||
$ vsend BIOSDEF.H
|
||||
$ vsend CCP.C
|
||||
$ vsend CCPBDOS.S
|
||||
$ vsend CCPDEF.H
|
||||
$ vsend CCPIF.S
|
||||
$ vsend CCPLOAD.S
|
||||
$ vsend CONBDOS.C
|
||||
$ vsend CPMC.DOC
|
||||
$ vsend DOWN2.SUB
|
||||
$ vsend DSKUTIL.C
|
||||
$ vsend EXCEPTN.S
|
||||
$ vsend FILEIO.C
|
||||
$ vsend FILETYPS.S
|
||||
$ vsend IOSYS.C
|
||||
$ vsend MAKE.SUB
|
||||
$ vsend PGMLD.S
|
||||
$ vsend PKTIO.H
|
||||
$ vsend REAR.SUB
|
||||
$ vsend SEND2.SUB
|
||||
$ vsend STACK.S
|
||||
$ vsend UP2.SUB
|
||||
$ vsend VMAKE.COM
|
||||
$ vsend done
|
||||
@@ -0,0 +1,13 @@
|
||||
$ xer BDOSMAIN.LIS
|
||||
$ xer BDOSMISC.LIS
|
||||
$ xer BDOSRW.LIS
|
||||
$ xer CCP.LIS
|
||||
$ xer CONBDOS.LIS
|
||||
$ xer DSKUTIL.LIS
|
||||
$ xer FILEIO.LIS
|
||||
$ xer IOSYS.LIS
|
||||
$ xer BDOSDEF.LST
|
||||
$ xer BDOSINC.LST
|
||||
$ xer BIOSDEF.LST
|
||||
$ xer CCPDEF.LST
|
||||
$ xer PKTIO.LST
|
||||
@@ -0,0 +1,8 @@
|
||||
$ xer BDOSIF.lis
|
||||
$ xer CCPBDOS.lis
|
||||
$ xer CCPIF.lis
|
||||
$ xer CCPLOAD.lis
|
||||
$ xer EXCEPTN.lis
|
||||
$ xer FILETYPS.lis
|
||||
$ xer PGMLD.lis
|
||||
$ xer STACK.lis
|
||||
Reference in New Issue
Block a user