fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation

chipset: Add support for the 80186 timer / counter

Hampa Hug 7bbfa5f5 d7c59fd7

+411 -1
+3
Makefile.dep
··· 1221 1221 src/chipset/80186/icu.o: src/chipset/80186/icu.c \ 1222 1222 src/chipset/80186/icu.h 1223 1223 1224 + src/chipset/80186/tcu.o: src/chipset/80186/tcu.c \ 1225 + src/chipset/80186/tcu.h 1226 + 1224 1227 src/chipset/82xx/e8237.o: src/chipset/82xx/e8237.c \ 1225 1228 src/chipset/82xx/e8237.h 1226 1229
+2 -1
src/chipset/80186/Makefile.inc
··· 5 5 DIRS += $(rel) 6 6 DIST += $(rel)/Makefile.inc 7 7 8 - CS_80186_BAS := dma icu 8 + CS_80186_BAS := dma icu tcu 9 9 CS_80186_SRC := $(foreach f,$(CS_80186_BAS),$(rel)/$(f).c) 10 10 CS_80186_OBJ := $(foreach f,$(CS_80186_BAS),$(rel)/$(f).o) 11 11 CS_80186_HDR := $(foreach f,$(CS_80186_BAS),$(rel)/$(f).h) ··· 15 15 16 16 $(rel)/dma.o: $(rel)/dma.c $(rel)/dma.h 17 17 $(rel)/icu.o: $(rel)/icu.c $(rel)/icu.h 18 + $(rel)/tcu.o: $(rel)/tcu.c $(rel)/tcu.h
+330
src/chipset/80186/tcu.c
··· 1 + /***************************************************************************** 2 + * pce * 3 + *****************************************************************************/ 4 + 5 + /***************************************************************************** 6 + * File name: src/chipset/80186/tcu.c * 7 + * Created: 2012-06-30 by Hampa Hug <hampa@hampa.ch> * 8 + * Copyright: (C) 2012 Hampa Hug <hampa@hampa.ch> * 9 + *****************************************************************************/ 10 + 11 + /***************************************************************************** 12 + * This program is free software. You can redistribute it and / or modify it * 13 + * under the terms of the GNU General Public License version 2 as published * 14 + * by the Free Software Foundation. * 15 + * * 16 + * This program is distributed in the hope that it will be useful, but * 17 + * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 + * Public License for more details. * 20 + *****************************************************************************/ 21 + 22 + 23 + #include "tcu.h" 24 + 25 + #include <stdio.h> 26 + #include <stdlib.h> 27 + 28 + 29 + #define TCON_EN 0x8000 30 + #define TCON_INH 0x4000 31 + #define TCON_INT 0x2000 32 + #define TCON_RIU 0x1000 33 + #define TCON_MC 0x0020 34 + #define TCON_RTG 0x0010 35 + #define TCON_P 0x0008 36 + #define TCON_EXT 0x0004 37 + #define TCON_ALT 0x0002 38 + #define TCON_CONT 0x0001 39 + 40 + 41 + #ifndef DEBUG_TCU 42 + #define DEBUG_TCU 0 43 + #endif 44 + 45 + 46 + static 47 + void e80186_tcu_init_cntr (e80186_tcu_t *tcu, unsigned idx) 48 + { 49 + e80186_tcu_cntr_t *cnt; 50 + 51 + cnt = &tcu->cntr[idx]; 52 + 53 + cnt->control = 0; 54 + cnt->count = 0; 55 + cnt->max_count_a = 0; 56 + cnt->max_count_b = 0; 57 + cnt->last_input = 0; 58 + cnt->current_input = 0; 59 + cnt->mc = 0; 60 + 61 + cnt->intr_val = 0; 62 + cnt->intr_ext = NULL; 63 + cnt->intr = NULL; 64 + 65 + cnt->out_val = 0; 66 + cnt->out_ext = NULL; 67 + cnt->out = NULL; 68 + } 69 + 70 + void e80186_tcu_init (e80186_tcu_t *tcu) 71 + { 72 + e80186_tcu_init_cntr (tcu, 0); 73 + e80186_tcu_init_cntr (tcu, 1); 74 + e80186_tcu_init_cntr (tcu, 2); 75 + 76 + tcu->clock = 0; 77 + } 78 + 79 + void e80186_tcu_free (e80186_tcu_t *tcu) 80 + { 81 + } 82 + 83 + void e80186_tcu_set_int_fct (e80186_tcu_t *tcu, unsigned idx, void *ext, void *fct) 84 + { 85 + tcu->cntr[idx].intr_ext = ext; 86 + tcu->cntr[idx].intr = fct; 87 + } 88 + 89 + void e80186_tcu_set_out_fct (e80186_tcu_t *tcu, unsigned idx, void *ext, void *fct) 90 + { 91 + tcu->cntr[idx].out_ext = ext; 92 + tcu->cntr[idx].out = fct; 93 + } 94 + 95 + static 96 + void e80186_tcu_set_int (e80186_tcu_t *tcu, unsigned idx, unsigned char val) 97 + { 98 + e80186_tcu_cntr_t *cnt; 99 + 100 + cnt = &tcu->cntr[idx]; 101 + 102 + val = (val != 0); 103 + 104 + if (cnt->intr_val == val) { 105 + return; 106 + } 107 + 108 + cnt->intr_val = val; 109 + 110 + if (cnt->intr != NULL) { 111 + cnt->intr (cnt->intr_ext, val); 112 + } 113 + } 114 + 115 + static 116 + void e80186_tcu_set_out (e80186_tcu_t *tcu, unsigned idx, unsigned char val) 117 + { 118 + e80186_tcu_cntr_t *cnt; 119 + 120 + cnt = &tcu->cntr[idx]; 121 + 122 + val = (val != 0); 123 + 124 + if (cnt->out_val == val) { 125 + return; 126 + } 127 + 128 + cnt->out_val = val; 129 + 130 + if (cnt->out != NULL) { 131 + cnt->out (cnt->out_ext, val); 132 + } 133 + } 134 + 135 + unsigned short e80186_tcu_get_control (const e80186_tcu_t *tcu, unsigned idx) 136 + { 137 + return (tcu->cntr[idx].control); 138 + } 139 + 140 + void e80186_tcu_set_control (e80186_tcu_t *tcu, unsigned idx, unsigned short val) 141 + { 142 + e80186_tcu_cntr_t *cnt; 143 + 144 + cnt = &tcu->cntr[idx]; 145 + 146 + if ((val & TCON_INH) == 0) { 147 + val = (val & ~TCON_EN) | (cnt->control & TCON_EN); 148 + } 149 + 150 + val = (val & ~TCON_RIU) | (cnt->control & TCON_RIU); 151 + 152 + cnt->control = val; 153 + 154 + #if DEBUG_TCU >= 1 155 + if (cnt->control & TCON_EN) { 156 + fprintf (stderr, "TCU: TIMER %u ENABLE (%04X)\n", idx, cnt->control); 157 + } 158 + #endif 159 + } 160 + 161 + unsigned short e80186_tcu_get_count (const e80186_tcu_t *tcu, unsigned idx) 162 + { 163 + return (tcu->cntr[idx].count); 164 + } 165 + 166 + void e80186_tcu_set_count (e80186_tcu_t *tcu, unsigned idx, unsigned short val) 167 + { 168 + tcu->cntr[idx].count = val; 169 + } 170 + 171 + unsigned short e80186_tcu_get_max_count_a (const e80186_tcu_t *tcu, unsigned idx) 172 + { 173 + return (tcu->cntr[idx].max_count_a); 174 + } 175 + 176 + void e80186_tcu_set_max_count_a (e80186_tcu_t *tcu, unsigned idx, unsigned short val) 177 + { 178 + tcu->cntr[idx].max_count_a = val; 179 + } 180 + 181 + unsigned short e80186_tcu_get_max_count_b (const e80186_tcu_t *tcu, unsigned idx) 182 + { 183 + return (tcu->cntr[idx].max_count_b); 184 + } 185 + 186 + void e80186_tcu_set_max_count_b (e80186_tcu_t *tcu, unsigned idx, unsigned short val) 187 + { 188 + tcu->cntr[idx].max_count_b = val; 189 + } 190 + 191 + void e80186_tcu_set_input (e80186_tcu_t *tcu, unsigned idx, unsigned char val) 192 + { 193 + tcu->cntr[idx].current_input = (val != 0); 194 + } 195 + 196 + static 197 + void e80186_tcu_reset_cntr (e80186_tcu_t *tcu, unsigned idx) 198 + { 199 + e80186_tcu_cntr_t *cnt; 200 + 201 + cnt = &tcu->cntr[idx]; 202 + 203 + cnt->control = 0; 204 + cnt->count = 0; 205 + cnt->max_count_a = 0; 206 + cnt->max_count_b = 0; 207 + cnt->mc = 0; 208 + } 209 + 210 + void e80186_tcu_reset (e80186_tcu_t *tcu) 211 + { 212 + e80186_tcu_reset_cntr (tcu, 0); 213 + e80186_tcu_reset_cntr (tcu, 1); 214 + e80186_tcu_reset_cntr (tcu, 2); 215 + } 216 + 217 + static 218 + void e80186_tcu_clock_cntr (e80186_tcu_t *tcu, unsigned idx) 219 + { 220 + e80186_tcu_cntr_t *cnt; 221 + unsigned char inp0, inp1; 222 + unsigned short ctl; 223 + 224 + cnt = &tcu->cntr[idx]; 225 + 226 + ctl = cnt->control; 227 + 228 + inp0 = cnt->last_input; 229 + inp1 = cnt->current_input; 230 + 231 + cnt->last_input = cnt->current_input; 232 + 233 + cnt->mc = 0; 234 + 235 + if ((ctl & TCON_EN) == 0) { 236 + return; 237 + } 238 + 239 + if (ctl & TCON_EXT) { 240 + if ((inp0 != 0) || (inp1 == 0)) { 241 + return; 242 + } 243 + } 244 + else { 245 + if (ctl & TCON_RTG) { 246 + if ((inp0 == 0) && (inp1 != 0)) { 247 + cnt->count = 0; 248 + return; 249 + } 250 + } 251 + else { 252 + if (inp1 == 0) { 253 + return; 254 + } 255 + } 256 + 257 + if (ctl & TCON_P) { 258 + if (tcu->cntr[2].mc == 0) { 259 + return; 260 + } 261 + } 262 + } 263 + 264 + cnt->count = (cnt->count + 1) & 0xffff; 265 + 266 + if (ctl & TCON_ALT) { 267 + if (ctl & TCON_RIU) { 268 + if (cnt->count != cnt->max_count_b) { 269 + return; 270 + } 271 + 272 + cnt->control &= ~TCON_RIU; 273 + 274 + e80186_tcu_set_out (tcu, idx, 1); 275 + 276 + if ((ctl & TCON_CONT) == 0) { 277 + cnt->control &= ~TCON_EN; 278 + } 279 + } 280 + else { 281 + if (cnt->count != cnt->max_count_a) { 282 + return; 283 + } 284 + 285 + cnt->control |= TCON_RIU; 286 + 287 + e80186_tcu_set_out (tcu, idx, 0); 288 + } 289 + } 290 + else { 291 + if (cnt->count != cnt->max_count_a) { 292 + return; 293 + } 294 + 295 + e80186_tcu_set_out (tcu, idx, 0); 296 + e80186_tcu_set_out (tcu, idx, 1); 297 + 298 + if ((ctl & TCON_CONT) == 0) { 299 + cnt->control &= ~TCON_EN; 300 + } 301 + } 302 + 303 + cnt->count = 0; 304 + cnt->control |= TCON_MC; 305 + cnt->mc = 1; 306 + 307 + if (ctl & TCON_INT) { 308 + #if DEBUG_TCU >= 1 309 + fprintf (stderr, "TCU: TIMER %u INTERRUPT\n", idx); 310 + #endif 311 + e80186_tcu_set_int (tcu, idx, 0); 312 + e80186_tcu_set_int (tcu, idx, 1); 313 + } 314 + } 315 + 316 + void e80186_tcu_clock (e80186_tcu_t *tcu, unsigned cnt) 317 + { 318 + unsigned idx; 319 + 320 + while (cnt > 0) { 321 + idx = tcu->clock & 3; 322 + 323 + if (idx < 3) { 324 + e80186_tcu_clock_cntr (tcu, idx); 325 + } 326 + 327 + tcu->clock += 1; 328 + cnt -= 1; 329 + } 330 + }
+76
src/chipset/80186/tcu.h
··· 1 + /***************************************************************************** 2 + * pce * 3 + *****************************************************************************/ 4 + 5 + /***************************************************************************** 6 + * File name: src/chipset/80186/tcu.h * 7 + * Created: 2012-06-30 by Hampa Hug <hampa@hampa.ch> * 8 + * Copyright: (C) 2012 Hampa Hug <hampa@hampa.ch> * 9 + *****************************************************************************/ 10 + 11 + /***************************************************************************** 12 + * This program is free software. You can redistribute it and / or modify it * 13 + * under the terms of the GNU General Public License version 2 as published * 14 + * by the Free Software Foundation. * 15 + * * 16 + * This program is distributed in the hope that it will be useful, but * 17 + * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 + * Public License for more details. * 20 + *****************************************************************************/ 21 + 22 + 23 + #ifndef PCE_CHIPSET_80186_TCU_H 24 + #define PCE_CHIPSET_80186_TCU_H 1 25 + 26 + 27 + typedef struct { 28 + unsigned short control; 29 + unsigned short count; 30 + unsigned short max_count_a; 31 + unsigned short max_count_b; 32 + unsigned char current_input; 33 + unsigned char last_input; 34 + unsigned char mc; 35 + 36 + unsigned char intr_val; 37 + void *intr_ext; 38 + void (*intr) (void *ext, unsigned char val); 39 + 40 + unsigned char out_val; 41 + void *out_ext; 42 + void (*out) (void *ext, unsigned char val); 43 + } e80186_tcu_cntr_t; 44 + 45 + typedef struct { 46 + e80186_tcu_cntr_t cntr[3]; 47 + unsigned clock; 48 + } e80186_tcu_t; 49 + 50 + 51 + void e80186_tcu_init (e80186_tcu_t *tcu); 52 + void e80186_tcu_free (e80186_tcu_t *tcu); 53 + 54 + void e80186_tcu_set_int_fct (e80186_tcu_t *tcu, unsigned idx, void *ext, void *fct); 55 + void e80186_tcu_set_out_fct (e80186_tcu_t *tcu, unsigned idx, void *ext, void *fct); 56 + 57 + unsigned short e80186_tcu_get_control (const e80186_tcu_t *tcu, unsigned idx); 58 + void e80186_tcu_set_control (e80186_tcu_t *tcu, unsigned idx, unsigned short val); 59 + 60 + unsigned short e80186_tcu_get_count (const e80186_tcu_t *tcu, unsigned idx); 61 + void e80186_tcu_set_count (e80186_tcu_t *tcu, unsigned idx, unsigned short val); 62 + 63 + unsigned short e80186_tcu_get_max_count_a (const e80186_tcu_t *tcu, unsigned idx); 64 + void e80186_tcu_set_max_count_a (e80186_tcu_t *tcu, unsigned idx, unsigned short val); 65 + 66 + unsigned short e80186_tcu_get_max_count_b (const e80186_tcu_t *tcu, unsigned idx); 67 + void e80186_tcu_set_max_count_b (e80186_tcu_t *tcu, unsigned idx, unsigned short val); 68 + 69 + void e80186_tcu_set_input (e80186_tcu_t *tcu, unsigned idx, unsigned char val); 70 + 71 + void e80186_tcu_reset (e80186_tcu_t *tcu); 72 + 73 + void e80186_tcu_clock (e80186_tcu_t *tcu, unsigned cnt); 74 + 75 + 76 + #endif