1 /*************************************************************************
3 * $Id: flashwriter2.c 1753 2008-01-02 16:36:47Z Hharte $ *
5 * Copyright (c) 2007-2008 Howard M. Harte. *
6 * http:/*www.hartetec.com *
8 * Permission is hereby granted, free of charge, to any person obtaining *
9 * a copy of this software and associated documentation files (the *
10 * "Software"), to deal in the Software without restriction, including *
11 * without limitation the rights to use, copy, modify, merge, publish, *
12 * distribute, sublicense, and/or sell copies of the Software, and to *
13 * permit persons to whom the Software is furnished to do so, subject to *
14 * the following conditions: *
16 * The above copyright notice and this permission notice shall be *
17 * included in all copies or substantial portions of the Software. *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
22 * NONINFRINGEMENT. IN NO EVENT SHALL HOWARD M. HARTE BE LIABLE FOR ANY *
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
27 * Except as contained in this notice, the name of Howard M. Harte shall *
28 * not be used in advertising or otherwise to promote the sale, use or *
29 * other dealings in this Software without prior written authorization *
32 * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. *
34 * Module Description: *
35 * Vector Graphic, Inc. FlashWriter II module for SIMH *
40 *************************************************************************/
44 #include "altairz80_defs.h"
55 #define DBG_PRINT(args) printf args
57 #define DBG_PRINT(args)
61 extern int32
sio0s(const int32 port
, const int32 io
, const int32 data
);
62 extern int32
sio0d(const int32 port
, const int32 io
, const int32 data
);
63 extern uint32
sim_map_resource(uint32 baseaddr
, uint32 size
, uint32 resource_type
,
64 int32 (*routine
)(const int32
, const int32
, const int32
), uint8 unmap
);
66 static char ansibuf
[10];
68 #define FW2_MAX_BOARDS 4
69 #define UNIT_V_FW2_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
70 #define UNIT_FW2_VERBOSE (1 << UNIT_V_FW2_VERBOSE)
71 #define FW2_CAPACITY (2048) /* FlashWriter II Memory Size */
74 UNIT
*uptr
; /* UNIT pointer */
75 uint8 cur_FL_Row
; /* Current Flashwriter Row */
76 uint8 cur_FL_Col
; /* Current Flashwriter Column */
79 uint8 reversevideo
; /* Flag set if reverse video is currently on */
80 uint8 M
[FW2_CAPACITY
]; /* FlashWriter 2K Video Memory */
83 static FW2_INFO
*fw2_info
[4];
84 static uint8 port_map
[4] = { 0x11, 0x15, 0x17, 0x19 };
86 static int32
fw2dev(const int32 Addr
, const int32 rw
, const int32 data
);
87 static t_stat
fw2_reset(DEVICE
*dptr
);
88 static t_stat
fw2_attach(UNIT
*uptr
, char *cptr
);
89 static t_stat
fw2_detach(UNIT
*uptr
);
90 static uint8
FW2_Read(const uint32 Addr
);
91 static uint8
FW2_Write(const uint32 Addr
, uint8 cData
);
92 static t_stat
get_base_address(char *cptr
, uint32
*baseaddr
);
94 static int32 FWIITrace
= FALSE
;
96 static UNIT fw2_unit
[] = {
97 { UDATA (NULL
, UNIT_FIX
+ UNIT_ATTABLE
+ UNIT_DISABLE
+ UNIT_ROABLE
, FW2_CAPACITY
) },
98 { UDATA (NULL
, UNIT_FIX
+ UNIT_ATTABLE
+ UNIT_DISABLE
+ UNIT_ROABLE
, FW2_CAPACITY
) },
99 { UDATA (NULL
, UNIT_FIX
+ UNIT_ATTABLE
+ UNIT_DISABLE
+ UNIT_ROABLE
, FW2_CAPACITY
) },
100 { UDATA (NULL
, UNIT_FIX
+ UNIT_ATTABLE
+ UNIT_DISABLE
+ UNIT_ROABLE
, FW2_CAPACITY
) }
103 static REG fw2_reg
[] = {
104 { DRDATA (FWIITRACE
, FWIITrace
, 8), },
108 static MTAB fw2_mod
[] = {
109 /* quiet, no warning messages */
110 { UNIT_FW2_VERBOSE
, 0, "QUIET", "QUIET", NULL
},
111 /* verbose, show warning messages */
112 { UNIT_FW2_VERBOSE
, UNIT_FW2_VERBOSE
, "VERBOSE", "VERBOSE", NULL
},
117 "FWII", fw2_unit
, fw2_reg
, fw2_mod
,
118 FW2_MAX_BOARDS
, 10, 31, 1, FW2_MAX_BOARDS
, FW2_MAX_BOARDS
,
119 NULL
, NULL
, &fw2_reset
,
120 NULL
, &fw2_attach
, &fw2_detach
,
126 static t_stat
fw2_reset(DEVICE
*dptr
)
132 static t_stat
fw2_attach(UNIT
*uptr
, char *cptr
)
139 r
= get_base_address(cptr
, &baseaddr
);
140 if(r
!= SCPE_OK
) /* error?*/
143 DBG_PRINT(("%s\n", __FUNCTION__
));
145 for(i
= 0; i
< FW2_MAX_BOARDS
; i
++) {
146 if(&fw2_dev
.units
[i
] == uptr
) {
147 if(uptr
->flags
& UNIT_FW2_VERBOSE
) {
148 printf("Attaching unit %d\n at %04x", i
, baseaddr
);
154 fw2_info
[i
] = calloc(1, sizeof(FW2_INFO
));
155 fw2_info
[i
]->uptr
= uptr
;
156 fw2_info
[i
]->uptr
->u3
= baseaddr
;
158 if(sim_map_resource(baseaddr
, FW2_CAPACITY
, RESOURCE_TYPE_MEMORY
, &fw2dev
, FALSE
) != 0) {
159 printf("%s: error mapping MEM resource at 0x%04x\n", __FUNCTION__
, baseaddr
);
163 if(sim_map_resource(0x00, 1, RESOURCE_TYPE_IO
, &sio0s
, FALSE
) != 0) {
164 printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__
, 0x00);
168 if(sim_map_resource(0x01, 1, RESOURCE_TYPE_IO
, &sio0d
, FALSE
) != 0) {
169 printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__
, 0x01);
173 tptr
= (char *) malloc (strlen (cptr
) + 3); /* get string buf */
174 if (tptr
== NULL
) return SCPE_MEM
; /* no more mem? */
175 sprintf(tptr
, "0x%04x", baseaddr
); /* copy base address */
176 uptr
->filename
= tptr
; /* save */
177 uptr
->flags
= uptr
->flags
| UNIT_ATT
;
183 static t_stat
fw2_detach(UNIT
*uptr
)
187 DBG_PRINT(("%s\n", __FUNCTION__
));
189 for(i
= 0; i
< FW2_MAX_BOARDS
; i
++) {
190 if(&fw2_dev
.units
[i
] == uptr
) {
195 if (i
>= FW2_MAX_BOARDS
) return SCPE_ARG
;
197 /* Disconnect FlashWriter2: unmap memory and I/O resources */
198 sim_map_resource(fw2_info
[i
]->uptr
->u3
, FW2_CAPACITY
, RESOURCE_TYPE_MEMORY
, &fw2dev
, TRUE
);
199 sim_map_resource(0x00, 1, RESOURCE_TYPE_IO
, &sio0s
, TRUE
);
200 sim_map_resource(0x01, 1, RESOURCE_TYPE_IO
, &sio0d
, TRUE
);
206 free (uptr
->filename
); /* free base address string */
207 uptr
->filename
= NULL
;
208 uptr
->flags
= uptr
->flags
& ~UNIT_ATT
; /* not attached */
212 static t_stat
get_base_address(char *cptr
, uint32
*baseaddr
) {
214 sscanf(cptr
, "%x", &b
);
215 if(b
& (FW2_CAPACITY
-1)) {
216 printf("FWII must be on a %d-byte boundary.\n", FW2_CAPACITY
);
219 *baseaddr
= b
& ~(FW2_CAPACITY
-1);
223 extern int32
getBankSelect(void);
225 /* This is the main entry point into the Flashwriter2 emulation. */
226 static int32
fw2dev(const int32 Addr
, const int32 rw
, const int32 data
)
228 int32 bank
= getBankSelect();
230 if(rw
== 0) { /* Read */
231 return(FW2_Read(Addr
));
233 return(FW2_Write(Addr
, data
));
239 static uint8
FW2_Write(const uint32 Addr
, uint8 Value
)
241 FW2_INFO
*fw2
= NULL
;
249 for(i
= 0; i
< FW2_MAX_BOARDS
; i
++) {
250 if(fw2_info
[i
] != NULL
) {
251 baseaddr
= fw2_info
[i
]->uptr
->u3
;
252 if((Addr
>= baseaddr
) && (Addr
< (baseaddr
+ FW2_CAPACITY
))) {
258 if(i
== FW2_MAX_BOARDS
) {
265 fw2
->M
[Addr
- baseaddr
] = Value
;
267 /* Only print if it is in the visible part of the Flashwriter memory */
268 if((Addr
>= baseaddr
) && (Addr
< (baseaddr
+ (80 * 24)))) {
269 FL_Col
= ((Addr
-baseaddr
) % 80) + 1;
270 FL_Row
= ((Addr
-baseaddr
) / 80) + 1;
272 if(Value
& 0x80) { /* reverse video */
273 if(fw2
->reversevideo
== 0) {
274 fw2
->reversevideo
= 1;
275 sprintf(ansibuf
, "\x1b[07m");
276 for(i
=0;i
<strlen(ansibuf
);i
++) {
277 sio0d(port
, 1, ansibuf
[i
]);
281 if(fw2
->reversevideo
== 1) {
282 fw2
->reversevideo
= 0;
283 sprintf(ansibuf
, "\x1b[00m");
284 for(i
=0;i
<strlen(ansibuf
);i
++) {
285 sio0d(port
, 1, ansibuf
[i
]);
290 outchar
= Value
& 0x7F;
294 if(outchar
== 0x7F) { /* this is supposed to be a square Block character on FW2 */
298 if((fw2
->cur_FL_Row
== FL_Row
) && (FL_Col
== fw2
->cur_FL_Col
+ 1)) {
299 sio0d(port
, 1, outchar
);
302 sprintf(ansibuf
, "\x1b[%d;%dH%c", FL_Row
, FL_Col
, outchar
);
303 for(i
=0;i
<strlen(ansibuf
);i
++) {
304 sio0d(port
, 1, ansibuf
[i
]);
307 fw2
->cur_FL_Col
= FL_Col
;
308 fw2
->cur_FL_Row
= FL_Row
;
315 static uint8
FW2_Read(const uint32 Addr
)
320 for(i
= 0; i
< FW2_MAX_BOARDS
; i
++) {
321 if(fw2_info
[i
] != NULL
) {
322 baseaddr
= fw2_info
[i
]->uptr
->u3
;
323 if((Addr
>= baseaddr
) && (Addr
< (baseaddr
+ FW2_CAPACITY
))) {
329 if(i
== FW2_MAX_BOARDS
) {
333 return(fw2_info
[i
]->M
[Addr
- baseaddr
]);