DOSBox-X
|
00001 #include "compiler.h" 00002 00003 #if defined(SUPPORT_PC9861K) 00004 00005 #include "commng.h" 00006 #include "pccore.h" 00007 #include "iocore.h" 00008 #include "cbuscore.h" 00009 #include "pc9861k.h" 00010 00011 00012 _PC9861K pc9861k; 00013 COMMNG cm_pc9861ch1; 00014 COMMNG cm_pc9861ch2; 00015 00016 00017 const UINT32 pc9861k_speed[11] = {75, 150, 300, 600, 1200, 2400, 4800, 00018 9600, 19200, 38400, 76800}; 00019 00020 static const UINT8 ch1_irq[4] = {IRQ_INT0, IRQ_INT1, IRQ_INT2, IRQ_INT3}; 00021 static const UINT8 ch2_irq[4] = {IRQ_INT0, IRQ_INT41, IRQ_INT5, IRQ_INT6}; 00022 static const _PC9861CH pc9861def = 00023 {0x05, 0xff, 7, 1, 00024 0, 0, 2400, NEVENT_MAXCLOCK, 0, 0, 0}; 00025 00026 00027 // ---- 00028 00029 static void pc9861k_callback(COMMNG cm, PC9861CH m) { 00030 00031 BOOL interrupt; 00032 00033 interrupt = FALSE; 00034 if ((cm != NULL) && (cm->read(cm, &m->data))) { 00035 m->result |= 2; 00036 if (m->signal & 1) { 00037 interrupt = TRUE; 00038 } 00039 } 00040 else { 00041 m->result &= ~2; 00042 } 00043 if (m->signal & 4) { 00044 if (m->send) { 00045 m->send = 0; 00046 interrupt = TRUE; 00047 } 00048 } 00049 if (interrupt) { 00050 pic_setirq(m->irq); 00051 } 00052 } 00053 00054 void pc9861ch1cb(NEVENTITEM item) { 00055 00056 if (item->flag & NEVENT_SETEVENT) { 00057 nevent_set(NEVENT_PC9861CH1, pc9861k.ch1.clk, pc9861ch1cb, 00058 NEVENT_RELATIVE); 00059 } 00060 pc9861k_callback(cm_pc9861ch1, &pc9861k.ch1); 00061 } 00062 00063 void pc9861ch2cb(NEVENTITEM item) { 00064 00065 if (item->flag & NEVENT_SETEVENT) { 00066 nevent_set(NEVENT_PC9861CH2, pc9861k.ch2.clk, pc9861ch2cb, 00067 NEVENT_RELATIVE); 00068 } 00069 pc9861k_callback(cm_pc9861ch2, &pc9861k.ch2); 00070 } 00071 00072 static UINT32 pc9861k_getspeed(REG8 dip) { 00073 00074 UINT speed; 00075 00076 speed = (((~dip) >> 2) & 0x0f) + 1; 00077 if (dip & 0x02) { 00078 if (speed > 4) { 00079 speed -= 4; 00080 } 00081 else { 00082 speed = 0; 00083 } 00084 } 00085 if (speed > (NELEMENTS(pc9861k_speed) - 1)) { 00086 speed = NELEMENTS(pc9861k_speed) - 1; 00087 } 00088 return(pc9861k_speed[speed]); 00089 } 00090 00091 static void pc9861_makeclk(PC9861CH m, UINT32 mul2) { 00092 00093 m->clk = pccore.realclock * mul2 / ((m->speed) * 2); 00094 } 00095 00096 static void pc9861ch1_open(void) { 00097 00098 cm_pc9861ch1 = commng_create(COMCREATE_PC9861K1); 00099 00100 pc9861k.ch1.dip = np2cfg.pc9861sw[0]; 00101 pc9861k.ch1.speed = pc9861k_getspeed(pc9861k.ch1.dip); 00102 pc9861k.ch1.vect = ((np2cfg.pc9861sw[1] >> 1) & 1) | 00103 ((np2cfg.pc9861sw[1] << 1) & 2); 00104 pc9861k.ch1.irq = ch1_irq[pc9861k.ch1.vect]; 00105 pc9861_makeclk(&pc9861k.ch1, 10*2); 00106 nevent_set(NEVENT_PC9861CH1, pc9861k.ch1.clk, 00107 pc9861ch1cb, NEVENT_ABSOLUTE); 00108 } 00109 00110 static void pc9861ch2_open(void) { 00111 00112 cm_pc9861ch2 = commng_create(COMCREATE_PC9861K2); 00113 00114 pc9861k.ch2.dip = np2cfg.pc9861sw[2]; 00115 pc9861k.ch2.speed = pc9861k_getspeed(pc9861k.ch2.dip); 00116 pc9861k.ch2.vect = ((np2cfg.pc9861sw[1] >> 3) & 1) | 00117 ((np2cfg.pc9861sw[1] >> 1) & 2); 00118 pc9861k.ch2.irq = ch1_irq[pc9861k.ch2.vect]; 00119 pc9861_makeclk(&pc9861k.ch2, 10*2); 00120 nevent_set(NEVENT_PC9861CH2, pc9861k.ch2.clk, 00121 pc9861ch2cb, NEVENT_ABSOLUTE); 00122 } 00123 00124 00125 // ------------------------------------------------------------------------- 00126 00127 static void IOOUTCALL pc9861data_w8(COMMNG cm, PC9861CH m, 00128 UINT port, REG8 value) { 00129 00130 UINT32 mul2; 00131 00132 switch(port & 0x3) { 00133 case 0x01: 00134 cm->write(cm, (UINT8)value); 00135 if (m->signal & 4) { 00136 m->send = 0; 00137 pic_setirq(m->irq); 00138 } 00139 else { 00140 m->send = 1; 00141 } 00142 break; 00143 00144 case 0x03: 00145 if (!(value & 0xfd)) { 00146 m->dummyinst += 1; 00147 } 00148 else { 00149 if ((m->dummyinst >= 3) && (value == 0x40)) { 00150 m->pos = 0; 00151 } 00152 m->dummyinst = 0; 00153 } 00154 switch(m->pos) { 00155 case 0x00: // reset 00156 m->pos += 1; 00157 break; 00158 00159 case 0x01: // mode 00160 if (!(value & 0x03)) { 00161 mul2 = 10 * 2; 00162 } 00163 else { 00164 mul2 = ((value >> 1) & 6) + 10; 00165 if (value & 0x10) { 00166 mul2 += 2; 00167 } 00168 switch(value & 0xc0) { 00169 case 0x80: 00170 mul2 += 3; 00171 break; 00172 case 0xc0: 00173 mul2 += 4; 00174 break; 00175 default: 00176 mul2 += 2; 00177 break; 00178 } 00179 } 00180 pc9861_makeclk(m, mul2); 00181 m->pos += 1; 00182 break; 00183 00184 case 0x02: // cmd 00185 m->pos += 1; 00186 break; 00187 } 00188 break; 00189 } 00190 } 00191 00192 static REG8 IOINPCALL pc9861data_r8(COMMNG cm, PC9861CH m, UINT port) { 00193 00194 switch(port & 0x3) { 00195 case 0x01: 00196 return(m->data); 00197 00198 case 0x03: 00199 if (!(cm->getstat(cm) & 0x20)) { 00200 return((m->result) | 0x80); 00201 } 00202 return(m->result); 00203 } 00204 return(0xff); 00205 } 00206 00207 00208 static void IOOUTCALL pc9861k_ob0(UINT port, REG8 dat) { 00209 00210 if (cm_pc9861ch1 == NULL) { 00211 pc9861ch1_open(); 00212 } 00213 pc9861k.ch1.signal = dat; 00214 (void)port; 00215 } 00216 00217 static void IOOUTCALL pc9861k_ob2(UINT port, REG8 dat) { 00218 00219 if (cm_pc9861ch2 == NULL) { 00220 pc9861ch2_open(); 00221 } 00222 pc9861k.ch2.signal = dat; 00223 (void)port; 00224 } 00225 00226 static REG8 IOINPCALL pc9861k_ib0(UINT port) { 00227 00228 if (cm_pc9861ch1 == NULL) { 00229 pc9861ch1_open(); 00230 } 00231 (void)port; 00232 return(cm_pc9861ch1->getstat(cm_pc9861ch1) | pc9861k.ch1.vect); 00233 } 00234 00235 static REG8 IOINPCALL pc9861k_ib2(UINT port) { 00236 00237 if (cm_pc9861ch2 == NULL) { 00238 pc9861ch2_open(); 00239 } 00240 (void)port; 00241 return(cm_pc9861ch2->getstat(cm_pc9861ch2) | pc9861k.ch2.vect); 00242 } 00243 00244 00245 static void IOOUTCALL pc9861k_ob1(UINT port, REG8 dat) { 00246 00247 if (cm_pc9861ch1 == NULL) { 00248 pc9861ch1_open(); 00249 } 00250 pc9861data_w8(cm_pc9861ch1, &pc9861k.ch1, port, dat); 00251 } 00252 00253 static REG8 IOINPCALL pc9861k_ib1(UINT port) { 00254 00255 if (cm_pc9861ch2 == NULL) { 00256 pc9861ch1_open(); 00257 } 00258 return(pc9861data_r8(cm_pc9861ch1, &pc9861k.ch1, port)); 00259 } 00260 00261 00262 static void IOOUTCALL pc9861k_ob9(UINT port, REG8 dat) { 00263 00264 if (cm_pc9861ch2 == NULL) { 00265 pc9861ch2_open(); 00266 } 00267 pc9861data_w8(cm_pc9861ch2, &pc9861k.ch2, port, dat); 00268 } 00269 00270 static REG8 IOINPCALL pc9861k_ib9(UINT port) { 00271 00272 if (cm_pc9861ch2 == NULL) { 00273 pc9861ch2_open(); 00274 } 00275 return(pc9861data_r8(cm_pc9861ch2, &pc9861k.ch2, port)); 00276 } 00277 00278 00279 // ---- I/F 00280 00281 void pc9861k_initialize(void) { 00282 00283 cm_pc9861ch1 = NULL; 00284 cm_pc9861ch2 = NULL; 00285 } 00286 00287 void pc9861k_deinitialize(void) { 00288 00289 commng_destroy(cm_pc9861ch1); 00290 cm_pc9861ch1 = NULL; 00291 commng_destroy(cm_pc9861ch2); 00292 cm_pc9861ch2 = NULL; 00293 } 00294 00295 void pc9861k_reset(const NP2CFG *pConfig) { 00296 00297 commng_destroy(cm_pc9861ch1); 00298 cm_pc9861ch1 = NULL; 00299 commng_destroy(cm_pc9861ch2); 00300 cm_pc9861ch2 = NULL; 00301 00302 pc9861k.ch1 = pc9861def; 00303 pc9861k.ch2 = pc9861def; 00304 pc9861k.en = pConfig->pc9861enable & 1; 00305 } 00306 00307 void pc9861k_bind(void) { 00308 00309 pc9861k_deinitialize(); 00310 if (pc9861k.en) { 00311 iocore_attachout(0xb0, pc9861k_ob0); 00312 iocore_attachout(0xb2, pc9861k_ob2); 00313 iocore_attachinp(0xb0, pc9861k_ib0); 00314 iocore_attachinp(0xb2, pc9861k_ib2); 00315 00316 iocore_attachout(0xb1, pc9861k_ob1); 00317 iocore_attachout(0xb3, pc9861k_ob1); 00318 iocore_attachinp(0xb1, pc9861k_ib1); 00319 iocore_attachinp(0xb3, pc9861k_ib1); 00320 00321 iocore_attachout(0xb9, pc9861k_ob9); 00322 iocore_attachout(0xbb, pc9861k_ob9); 00323 iocore_attachinp(0xb9, pc9861k_ib9); 00324 iocore_attachinp(0xbb, pc9861k_ib9); 00325 } 00326 } 00327 00328 void pc9861k_midipanic(void) { 00329 00330 if (cm_pc9861ch1) { 00331 cm_pc9861ch1->msg(cm_pc9861ch1, COMMSG_MIDIRESET, 0); 00332 } 00333 if (cm_pc9861ch2) { 00334 cm_pc9861ch2->msg(cm_pc9861ch1, COMMSG_MIDIRESET, 0); 00335 } 00336 } 00337 00338 #endif 00339