llvm-mos-sdk
cpm.h
Go to the documentation of this file.
1 /* CP/M entrypoints for C.
2  *
3  * © 2022 David Given
4  * This file is part of the llvm-mos-sdk project and is redistributable under
5  * the terms of the Apache 2.0 license with the LLVM exceptions. See the LICENSE
6  * file in the project root for the full text.
7  */
8 
9 #ifndef CPM_H
10 #define CPM_H
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 #include <stdint.h>
17 
18 /* Standard FCB used for file access. */
19 
20 typedef struct __attribute__((packed)) {
21  uint8_t dr; /* drive number (1-based, or 0 for default) */
22  uint8_t f[11]; /* filename, space padded */
23  uint8_t ex; /* extent low: set to zero on open and otherwise ignore */
24  uint8_t s1; /* spare: ignore */
25  uint8_t s2; /* extent high: ignore */
26  uint8_t rc; /* number of records in this extent: ignore */
27  uint8_t al[16]; /* allocation map: ignore */
28  uint8_t cr; /* current record: ignore */
29  uint16_t r; /* random-access pointer: set when doing random-access calls */
30  uint8_t r2; /* random-access overflow: used only by cpm_seek_to_end */
31 } FCB;
32 
33 /* Rename control block, used only by cpm_rename_file. */
34 
35 typedef struct __attribute__((packed)) {
36  uint8_t dr; /* drive number (1-based, or 0 for default) */
37  uint8_t src[11]; /* source filename */
38  uint8_t _padding[5]; /* unused; ignore */
39  uint8_t dest[11]; /* destination filename */
40 } RCB;
41 
42 /* Directory entry on disk */
43 
44 typedef struct __attribute__((packed)) {
45  uint8_t us; /* user number */
46  uint8_t f[11]; /* filename, space padded */
47  uint8_t ex; /* extent low */
48  uint8_t s1; /* unused */
49  uint8_t s2; /* extent high */
50  uint8_t rc; /* number of records in the last extent in this dirent */
51  uint8_t al[16]; /* allocation map */
52 } DIRE;
53 
54 typedef struct __attribute__((packed)) {
55  uint16_t spt; /* number of 128-byte sectors per track (unused on CP/M-65) */
56  uint8_t bsh; /* block shift; 3=1kB, 4=2kB, 5=4kB etc */
57  uint8_t blm; /* block mask; 0x07=1kB, 0x0f=2kB, 0x1f=4k etc */
58  uint8_t exm; /* extent mask */
59  uint16_t dsm; /* maximum block number */
60  uint16_t drm; /* maximum directory entry number */
61  uint8_t al[2]; /* directory allocation bitmap */
62  uint16_t cks; /* checksum vector size */
63  uint16_t off; /* number of reserved tracks */
64 } DPB;
65 
66 typedef struct __attribute__((packed)) {
67  uint8_t *xlt; /* address of translation vector */
68  uint8_t scratch[6]; /* BDOS scratchpad */
69  uint8_t *dirbuf; /* address of directory scratchpad */
70  DPB *dpb; /* address of DPB */
71  uint8_t *csv; /* address of disk change scratchpad */
72  uint8_t *alv; /* address of allocation bitmap */
73 } DPH;
74 
75 typedef struct {
77  const char *name;
78  void *strategy;
79 } DRIVER;
80 
81 enum {
82  CPME_OK = 0x00, /* success (usually) */
83  CPME_NOBLOCK = 0x01, /* or EOF */
84  CPME_DISKFULL = 0x02, /* no free blocks on disk */
85  CPME_CANTCLOSE = 0x03, /* can't write extent back to disk */
86  CPME_NOEXTENT = 0x04, /* only on random access reads */
87  CPME_DIRFULL = 0x05, /* no free dirents on disk */
88  CPME_BADFCB = 0x09, /* FCB couldn't be parsed */
89  CPME_FAILED = 0xff, /* general purpose failure code */
90 };
91 
92 extern FCB cpm_fcb; /* primary FCB */
93 extern FCB cpm_fcb2; /* secondary FCB (special purpose, overlaps cpm_fcb) */
94 
95 extern uint8_t cpm_default_dma[128]; /* also contains the parsed command line */
96 extern uint8_t cpm_ram[];
97 extern uint8_t cpm_cmdlinelen;
98 extern char cpm_cmdline[0x7f];
99 extern uint8_t cpm_errno;
100 
101 /* 0 */ extern __attribute__((leaf)) void _Noreturn cpm_warmboot(void);
102 /* 1 */ extern __attribute__((leaf)) uint8_t cpm_conin(void);
103 /* 2 */ extern __attribute__((leaf)) void cpm_conout(uint8_t b);
104 /* 3 */ extern __attribute__((leaf)) uint8_t cpm_auxin(void);
105 /* 4 */ extern __attribute__((leaf)) void cpm_auxout(uint8_t b);
106 /* 5 */ extern __attribute__((leaf)) void cpm_lstout(uint8_t b);
107 /* 6 */ extern __attribute__((leaf)) uint8_t cpm_conio(uint8_t b);
108 /* 7 */ extern __attribute__((leaf)) uint8_t cpm_get_iobyte(void);
109 /* 8 */ extern __attribute__((leaf)) void cpm_set_iobyte(uint8_t iob);
110 /* 9 */ extern __attribute__((leaf)) void cpm_printstring_i(uint16_t s);
111 extern void cpm_printstring(const char *s); /* $-terminated */
112 /* 10 */ extern __attribute__((leaf)) uint8_t cpm_readline_i(uint16_t buffer);
113 /* */ extern uint8_t cpm_readline(uint8_t *buffer);
114 /* 11 */ extern __attribute__((leaf)) uint8_t cpm_const(void);
115 /* 12 */ extern __attribute__((leaf)) uint16_t cpm_get_version(void);
116 /* 13 */ extern __attribute__((leaf)) void cpm_reset_disk_system(void);
117 /* 14 */ extern __attribute__((leaf)) void cpm_select_drive(uint8_t disk);
118 /* 15 */ extern __attribute__((leaf)) uint8_t cpm_open_file_i(uint16_t fcb);
119 extern uint8_t cpm_open_file(FCB *fcb);
120 /* 16 */ extern __attribute__((leaf)) uint8_t cpm_close_file_i(uint16_t fcb);
121 extern uint8_t cpm_close_file(FCB *fcb);
122 /* 17 */ extern __attribute__((leaf)) uint8_t cpm_findfirst_i(uint16_t fcb);
123 extern uint8_t cpm_findfirst(FCB *fcb);
124 /* 18 */ extern __attribute__((leaf)) uint8_t cpm_findnext_i(uint16_t fcb);
125 extern uint8_t cpm_findnext(FCB *fcb);
126 /* 19 */ extern __attribute__((leaf)) uint8_t cpm_delete_file_i(uint16_t fcb);
127 extern uint8_t cpm_delete_file(FCB *fcb);
128 /* 20 */ extern __attribute__((leaf)) uint8_t
129 cpm_read_sequential_i(uint16_t fcb);
130 extern uint8_t cpm_read_sequential(FCB *fcb);
131 /* 21 */ extern __attribute__((leaf)) uint8_t
132 cpm_write_sequential_i(uint16_t fcb);
133 extern uint8_t cpm_write_sequential(FCB *fcb);
134 /* 22 */ extern __attribute__((leaf)) uint8_t cpm_make_file_i(uint16_t fcb);
135 extern uint8_t cpm_make_file(FCB *fcb);
136 /* 23 */ extern __attribute__((leaf)) uint8_t cpm_rename_file_i(uint16_t rcb);
137 extern uint8_t cpm_rename_file(RCB *rcb);
138 /* 24 */ extern __attribute__((leaf)) uint16_t cpm_get_login_vector(void);
139 /* 25 */ extern __attribute__((leaf)) uint8_t cpm_get_current_drive(void);
140 /* 26 */ extern __attribute__((leaf)) void cpm_set_dma_i(uint16_t ptr);
141 extern void cpm_set_dma(void *ptr);
142 /* 27 */ extern __attribute__((leaf)) uint16_t
143 cpm_get_allocation_vector_i(void);
144 extern uint8_t *cpm_get_allocation_vector(void);
145 /* 28 */ extern __attribute__((leaf)) void cpm_write_protect_drive(void);
146 /* 29 */ extern __attribute__((leaf)) uint16_t cpm_get_readonly_vector(void);
147 /* 30 */ extern __attribute__((leaf)) uint8_t
148 cpm_set_file_attributes_i(uint16_t fcb);
149 extern uint8_t cpm_set_file_attributes(FCB *fcb);
150 /* 31 */ extern __attribute__((leaf)) uint16_t cpm_get_dpb_i(void);
151 extern DPB *cpm_get_dpb(void);
152 /* 32 */ extern __attribute__((leaf)) uint8_t cpm_get_set_user(uint8_t user);
153 /* 33 */ extern __attribute__((leaf)) uint8_t cpm_read_random_i(uint16_t fcb);
154 extern uint8_t cpm_read_random(FCB *fcb);
155 /* 34 */ extern __attribute__((leaf)) uint8_t cpm_write_random_i(uint16_t fcb);
156 extern uint8_t cpm_write_random(FCB *fcb);
157 /* 35 */ extern __attribute__((leaf)) void cpm_seek_to_end_i(uint16_t fcb);
158 extern void cpm_seek_to_end(FCB *fcb);
159 /* 36 */ extern __attribute__((leaf)) void cpm_seek_to_seq_pos_i(uint16_t fcb);
160 extern void cpm_seek_to_seq_pos(FCB *fcb);
161 /* 37 */ extern __attribute__((leaf)) uint8_t
162 cpm_reset_drives(uint16_t drive_bitmap);
163 /* 40 */ extern __attribute__((leaf)) uint8_t
164 cpm_write_random_filled_i(uint16_t fcb);
165 extern uint8_t cpm_write_random_filled(FCB *fcb);
166 /* 41 */ extern __attribute__((leaf)) uint16_t cpm_getzp(void);
167 /* 42 */ extern __attribute__((leaf)) uint16_t cpm_gettpa(void);
168 /* 43 */ extern __attribute__((leaf)) uint16_t
169 cpm_parse_filename_i(uint16_t buffer);
170 extern const char *cpm_parse_filename(const char *buffer);
171 
172 #define cpm_get_user() cpm_get_set_user(0xff)
173 #define cpm_set_user(u) cpm_get_set_user(u)
174 
175 extern __attribute__((leaf)) uint8_t cpm_bios_const(void);
176 extern __attribute__((leaf)) uint8_t cpm_bios_conin(void);
177 extern __attribute__((leaf)) void cpm_bios_conout(uint8_t c);
178 extern uint16_t cpm_bios_seldsk_i(uint8_t disk);
179 extern DPH *cpm_bios_seldsk(uint8_t disk);
180 extern __attribute__((leaf)) void
181 cpm_bios_setsec_i(uint16_t sector); /* actually only 24 bits */
182 extern void cpm_bios_setsec(uint32_t *sector); /* actually only 24 bits */
183 extern __attribute__((leaf)) void cpm_bios_setdma_i(uint16_t dma);
184 extern void cpm_bios_setdma(void *dma);
185 extern __attribute__((leaf)) uint8_t cpm_bios_read(void);
186 extern __attribute__((leaf)) uint8_t cpm_bios_write(uint8_t deblock);
187 extern __attribute__((leaf)) void cpm_bios_relocate(uint8_t zp, uint8_t mem);
188 extern __attribute__((leaf)) uint16_t cpm_bios_gettpa(void);
189 extern __attribute__((leaf)) void cpm_bios_settpa(uint8_t start, uint8_t end);
190 extern __attribute__((leaf)) uint16_t cpm_bios_getzp(void);
191 extern __attribute__((leaf)) void cpm_bios_setzp(uint8_t start, uint8_t end);
192 extern __attribute__((leaf)) void cpm_bios_adddrv_i(uint16_t driver);
193 extern void cpm_bios_adddrv(DRIVER *driver);
194 extern __attribute__((leaf)) uint16_t cpm_bios_finddrv_i(uint16_t id);
195 extern void *cpm_bios_finddrv(uint16_t id);
196 
197 #ifdef __cplusplus
198 }
199 #endif
200 
201 #endif
202 
203 // vim: ts=4 sw=4 et
end
uint8_t end
Definition: cpm.h:189
cpm_parse_filename
const char * cpm_parse_filename(const char *buffer)
cpm_read_sequential
uint8_t cpm_read_sequential(FCB *fcb)
DRIVER
Definition: cpm.h:75
f
byte byte byte byte byte f
Definition: api.h:27
RCB
RCB
Definition: cpm.h:40
DRIVER::id
uint16_t id
Definition: cpm.h:76
cpm_delete_file
uint8_t cpm_delete_file(FCB *fcb)
cpm_write_random
uint8_t cpm_write_random(FCB *fcb)
std::uint16_t
::uint16_t uint16_t
Definition: cstdint:22
DRIVER::name
const char * name
Definition: cpm.h:77
cpm_ram
uint8_t cpm_ram[]
cpm_cmdlinelen
uint8_t cpm_cmdlinelen
cpm_get_dpb
DPB * cpm_get_dpb(void)
CPME_DISKFULL
@ CPME_DISKFULL
Definition: cpm.h:84
CPME_NOEXTENT
@ CPME_NOEXTENT
Definition: cpm.h:86
cpm_read_random
uint8_t cpm_read_random(FCB *fcb)
cpm_printstring
void cpm_printstring(const char *s)
DRIVER::strategy
void * strategy
Definition: cpm.h:78
cpm_bios_finddrv
void * cpm_bios_finddrv(uint16_t id)
cpm_bios_adddrv
void cpm_bios_adddrv(DRIVER *driver)
cpm_bios_setsec
void cpm_bios_setsec(uint32_t *sector)
cpm_close_file
uint8_t cpm_close_file(FCB *fcb)
mem
uint8_t mem
Definition: cpm.h:187
std::uint8_t
::uint8_t uint8_t
Definition: cstdint:21
CPME_FAILED
@ CPME_FAILED
Definition: cpm.h:89
cpm_write_random_filled
uint8_t cpm_write_random_filled(FCB *fcb)
CPME_DIRFULL
@ CPME_DIRFULL
Definition: cpm.h:87
cpm_get_allocation_vector
uint8_t * cpm_get_allocation_vector(void)
cpm_fcb
FCB cpm_fcb
cpm_bios_seldsk
DPH * cpm_bios_seldsk(uint8_t disk)
cpm_errno
uint8_t cpm_errno
cpm_open_file
uint8_t cpm_open_file(FCB *fcb)
CPME_BADFCB
@ CPME_BADFCB
Definition: cpm.h:88
cpm_cmdline
char cpm_cmdline[0x7f]
src
const void * src
Definition: memory.h:57
cpm_set_dma
void cpm_set_dma(void *ptr)
CPME_OK
@ CPME_OK
Definition: cpm.h:82
CPME_CANTCLOSE
@ CPME_CANTCLOSE
Definition: cpm.h:85
cpm_findfirst
uint8_t cpm_findfirst(FCB *fcb)
cpm_bios_setdma
void cpm_bios_setdma(void *dma)
FCB
FCB
Definition: cpm.h:31
cpm_make_file
uint8_t cpm_make_file(FCB *fcb)
cpm_seek_to_seq_pos
void cpm_seek_to_seq_pos(FCB *fcb)
cpm_write_sequential
uint8_t cpm_write_sequential(FCB *fcb)
cpm_default_dma
uint8_t cpm_default_dma[128]
cpm_readline
uint8_t cpm_readline(uint8_t *buffer)
DPB
DPB
Definition: cpm.h:64
cpm_seek_to_end
void cpm_seek_to_end(FCB *fcb)
CPME_NOBLOCK
@ CPME_NOBLOCK
Definition: cpm.h:83
DPH
DPH
Definition: cpm.h:73
std::uint32_t
::uint32_t uint32_t
Definition: cstdint:23
cpm_findnext
uint8_t cpm_findnext(FCB *fcb)
DIRE
DIRE
Definition: cpm.h:52
cpm_rename_file
uint8_t cpm_rename_file(RCB *rcb)
cpm_bios_seldsk_i
uint16_t cpm_bios_seldsk_i(uint8_t disk)
c
byte byte c
Definition: api.h:59
cpm_set_file_attributes
uint8_t cpm_set_file_attributes(FCB *fcb)
cpm_fcb2
FCB cpm_fcb2