1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/IoDevice/I8255.c,v $
3 **
4 ** $Revision: 1.9 $
5 **
6 ** $Date: 2008-03-30 18:38:40 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2006 Daniel Vik
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 ******************************************************************************
27 */
28 #include "I8255.h"
29 #include "SaveState.h"
30 #include <stdlib.h>
31 
32 struct I8255
33 {
34     I8255Read peekA;
35     I8255Read readA;
36     I8255Write writeA;
37     I8255Read peekB;
38     I8255Read readB;
39     I8255Write writeB;
40     I8255Read peekCLo;
41     I8255Read readCLo;
42     I8255Write writeCLo;
43     I8255Read peekCHi;
44     I8255Read readCHi;
45     I8255Write writeCHi;
46     void* ref;
47 
48     UInt8 reg[4];
49 };
50 
readDummy(void * ref)51 static UInt8 readDummy(void* ref)
52 {
53     return 0xff;
54 }
55 
writeDummy(void * ref,UInt8 value)56 static void writeDummy(void* ref, UInt8 value)
57 {
58 }
59 
i8255Create(I8255Read peekA,I8255Read readA,I8255Write writeA,I8255Read peekB,I8255Read readB,I8255Write writeB,I8255Read peekCLo,I8255Read readCLo,I8255Write writeCLo,I8255Read peekCHi,I8255Read readCHi,I8255Write writeCHi,void * ref)60 I8255* i8255Create(I8255Read peekA,   I8255Read readA,   I8255Write writeA,
61                    I8255Read peekB,   I8255Read readB,   I8255Write writeB,
62                    I8255Read peekCLo, I8255Read readCLo, I8255Write writeCLo,
63                    I8255Read peekCHi, I8255Read readCHi, I8255Write writeCHi,
64                    void* ref)
65 {
66     I8255* i8255 = calloc(1, sizeof(I8255));
67 
68     i8255->peekA    = peekA    ? peekA    : readDummy;
69     i8255->readA    = readA    ? readA    : readDummy;
70     i8255->writeA   = writeA   ? writeA   : writeDummy;
71     i8255->peekB    = peekB    ? peekB    : readDummy;
72     i8255->readB    = readB    ? readB    : readDummy;
73     i8255->writeB   = writeB   ? writeB   : writeDummy;
74     i8255->peekCLo  = peekCLo  ? peekCLo  : readDummy;
75     i8255->readCLo  = readCLo  ? readCLo  : readDummy;
76     i8255->writeCLo = writeCLo ? writeCLo : writeDummy;
77     i8255->peekCHi  = peekCHi  ? peekCHi  : readDummy;
78     i8255->readCHi  = readCHi  ? readCHi  : readDummy;
79     i8255->writeCHi = writeCHi ? writeCHi : writeDummy;
80     i8255->ref      = ref;
81 
82     return i8255;
83 }
84 
i8255Reset(I8255 * i8255)85 void i8255Reset(I8255* i8255)
86 {
87     i8255->reg[3] = 0x9b;
88 
89     i8255Write(i8255, 0, 0);
90     i8255Write(i8255, 1, 0);
91     i8255Write(i8255, 2, 0);
92 }
93 
i8255Destroy(I8255 * i8255)94 void i8255Destroy(I8255* i8255)
95 {
96     free(i8255);
97 }
98 
i8255LoadState(I8255 * i8255)99 void i8255LoadState(I8255* i8255)
100 {
101     SaveState* state = saveStateOpenForRead("i8255");
102 
103     i8255->reg[0] = (UInt8)saveStateGet(state, "reg00", 0);
104     i8255->reg[1] = (UInt8)saveStateGet(state, "reg01", 0);
105     i8255->reg[2] = (UInt8)saveStateGet(state, "reg02", 0);
106     i8255->reg[3] = (UInt8)saveStateGet(state, "reg03", 0);
107 
108     saveStateClose(state);
109 }
110 
i8255SaveState(I8255 * i8255)111 void i8255SaveState(I8255* i8255)
112 {
113     SaveState* state = saveStateOpenForWrite("i8255");
114 
115     saveStateSet(state, "reg00", i8255->reg[0]);
116     saveStateSet(state, "reg01", i8255->reg[1]);
117     saveStateSet(state, "reg02", i8255->reg[2]);
118     saveStateSet(state, "reg03", i8255->reg[3]);
119 
120     saveStateClose(state);
121 }
122 
i8255Peek(I8255 * i8255,UInt16 port)123 UInt8 i8255Peek(I8255* i8255, UInt16 port)
124 {
125     UInt8 value;
126 
127     port &= 0x03;
128 
129     switch (port) {
130     case 0:
131         switch (i8255->reg[3] & 0x60) {
132         case 0x00: // MODE 0
133             if (i8255->reg[3] & 0x10) {
134                 return i8255->peekA(i8255->ref);
135             }
136             return i8255->reg[0];
137 
138         case 0x20: // MODE 1
139             return 0xff;
140 
141         default: // MODE 2
142             return 0xff;
143         }
144         break;
145 
146     case 1:
147         switch (i8255->reg[3] & 0x04) {
148         case 0x00: // MODE 0
149             if (i8255->reg[3] & 0x02) {
150                 return i8255->peekA(i8255->ref);
151             }
152             return i8255->reg[1];
153 
154         default: // MODE 1
155             return 0xff;
156         }
157         break;
158 
159     case 2:
160         value = i8255->reg[2];
161 
162         if (i8255->reg[3] & 0x01) {
163             value = (value & 0xf0) | (i8255->peekCLo(i8255->ref) & 0x0f);
164         }
165         if (i8255->reg[3] & 0x08) {
166             value = (value & 0x0f) | (i8255->peekCHi(i8255->ref) << 4);
167         }
168         return value;
169 
170     case 3:
171         return i8255->reg[3];
172     }
173 
174     return 0xff;
175 }
176 
i8255Read(I8255 * i8255,UInt16 port)177 UInt8 i8255Read(I8255* i8255, UInt16 port)
178 {
179     UInt8 value;
180 
181     port &= 0x03;
182 
183     switch (port) {
184     case 0:
185         switch (i8255->reg[3] & 0x60) {
186         case 0x00: // MODE 0
187             if (i8255->reg[3] & 0x10) {
188                 return i8255->readA(i8255->ref);
189             }
190             return i8255->reg[0];
191 
192         case 0x20: // MODE 1
193             return 0xff;
194 
195         default: // MODE 2
196             return 0xff;
197         }
198         break;
199 
200     case 1:
201         switch (i8255->reg[3] & 0x04) {
202         case 0x00: // MODE 0
203             if (i8255->reg[3] & 0x02) {
204                 return i8255->readB(i8255->ref);
205             }
206             return i8255->reg[1];
207 
208         default: // MODE 1
209             return 0xff;
210         }
211         break;
212 
213     case 2:
214         // FIXME: Check mode
215 
216         value = i8255->reg[2];
217 
218         if (i8255->reg[3] & 0x01) {
219             value = (value & 0xf0) | (i8255->readCLo(i8255->ref) & 0x0f);
220         }
221         if (i8255->reg[3] & 0x08) {
222             value = (value & 0x0f) | (i8255->readCHi(i8255->ref) << 4);
223         }
224         return value;
225 
226     case 3:
227         return i8255->reg[3];
228     }
229 
230     return 0xff;
231 }
232 
i8255Write(I8255 * i8255,UInt16 port,UInt8 value)233 void i8255Write(I8255* i8255, UInt16 port, UInt8 value)
234 {
235     port &= 0x03;
236 
237     switch (port) {
238     case 0:
239         switch (i8255->reg[3] & 0x60) {
240         case 0x00: // MODE 0
241             break;
242         case 0x20: // MODE 1
243             break;
244         default: // MODE 2
245             break;
246         }
247 
248         i8255->reg[0] = value;
249 
250         if (!(i8255->reg[3] & 0x10)) {
251             i8255->writeA(i8255->ref, value);
252         }
253         return;
254 
255     case 1:
256         switch (i8255->reg[3] & 0x04) {
257         case 0x00: // MODE 0
258             break;
259         default: // MODE 1
260             break;
261         }
262 
263         i8255->reg[1] = value;
264 
265         if (!(i8255->reg[3] & 0x02)) {
266             i8255->writeB(i8255->ref, value);
267         }
268         return;
269 
270     case 2:
271         i8255->reg[2] = value;
272 
273         // FIXME: Check mode
274 
275         if (!(i8255->reg[3] & 0x01)) {
276             i8255->writeCLo(i8255->ref, value & 0x0f);
277         }
278         if (!(i8255->reg[3] & 0x08)) {
279             i8255->writeCHi(i8255->ref, value >> 4);
280         }
281         return;
282 
283     case 3:
284         if (value & 0x80) {
285             i8255->reg[3] = value;
286             i8255Write(i8255, 0, i8255->reg[0]);
287             i8255Write(i8255, 1, i8255->reg[1]);
288             i8255Write(i8255, 2, i8255->reg[2]);
289         }
290         else {
291             UInt8 mask = 1 << ((value >> 1) & 0x07);
292             if (value & 0x01) {
293                 i8255Write(i8255, 2, i8255->reg[2] | mask);
294             }
295             else {
296                 i8255Write(i8255, 2, i8255->reg[2] & ~mask);
297             }
298         }
299         return;
300     }
301 }
302 
303 
304 #if 0
305 
306 /*****************************************************************************
307 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/IoDevice/I8255.c,v $
308 **
309 ** $Revision: 1.9 $
310 **
311 ** $Date: 2008-03-30 18:38:40 $
312 **
313 ** More info: http://www.bluemsx.com
314 **
315 ** Copyright (C) 2003-2006 Daniel Vik
316 **
317 ** This program is free software; you can redistribute it and/or modify
318 ** it under the terms of the GNU General Public License as published by
319 ** the Free Software Foundation; either version 2 of the License, or
320 ** (at your option) any later version.
321 **
322 ** This program is distributed in the hope that it will be useful,
323 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
324 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
325 ** GNU General Public License for more details.
326 **
327 ** You should have received a copy of the GNU General Public License
328 ** along with this program; if not, write to the Free Software
329 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
330 **
331 ******************************************************************************
332 */
333 #include "I8255.h"
334 #include "SaveState.h"
335 #include <stdlib.h>
336 
337 struct I8255
338 {
339     I8255Read peekA;
340     I8255Read readA;
341     I8255Write writeA;
342     I8255Read peekB;
343     I8255Read readB;
344     I8255Write writeB;
345     I8255Read peekCLo;
346     I8255Read readCLo;
347     I8255Write writeCLo;
348     I8255Read peekCHi;
349     I8255Read readCHi;
350     I8255Write writeCHi;
351     void* ref;
352 
353     UInt8 reg[4];
354 
355     int   useInputLatch;
356 
357     UInt8 latchA;
358     UInt8 latchB;
359     UInt8 latchC;
360 };
361 
362 static UInt8 readLatchA(I8255* i8255)
363 {
364     return i8255->latchA;
365 }
366 
367 static UInt8 readLatchB(I8255* i8255)
368 {
369     return i8255->latchB;
370 }
371 
372 static UInt8 readLatchCLo(I8255* i8255)
373 {
374     return i8255->latchC & 0xff;
375 }
376 
377 static UInt8 readLatchCHi(I8255* i8255)
378 {
379     return i8255->latchC >> 4;
380 }
381 
382 static void writeDummy(void* ref, UInt8 value)
383 {
384 }
385 
386 I8255* i8255Create(I8255Read peekA,   I8255Read readA,   I8255Write writeA,
387                    I8255Read peekB,   I8255Read readB,   I8255Write writeB,
388                    I8255Read peekCLo, I8255Read readCLo, I8255Write writeCLo,
389                    I8255Read peekCHi, I8255Read readCHi, I8255Write writeCHi,
390                    void* ref, int useInputLatch)
391 {
392     I8255* i8255 = calloc(1, sizeof(I8255));
393 
394     i8255->peekA    = peekA    ? peekA    : readLatchA;
395     i8255->readA    = readA    ? readA    : readLatchA;
396     i8255->writeA   = writeA   ? writeA   : writeDummy;
397     i8255->peekB    = peekB    ? peekB    : readLatchB;
398     i8255->readB    = readB    ? readB    : readLatchB;
399     i8255->writeB   = writeB   ? writeB   : writeDummy;
400     i8255->peekCLo  = peekCLo  ? peekCLo  : readLatchCLo;
401     i8255->readCLo  = readCLo  ? readCLo  : readLatchCLo;
402     i8255->writeCLo = writeCLo ? writeCLo : writeDummy;
403     i8255->peekCHi  = peekCHi  ? peekCHi  : readLatchCHi;
404     i8255->readCHi  = readCHi  ? readCHi  : readLatchCHi;
405     i8255->writeCHi = writeCHi ? writeCHi : writeDummy;
406     i8255->ref      = ref;
407 
408     i8255->useInputLatch = useInputLatch;
409 
410     return i8255;
411 }
412 
413 void i8255Reset(I8255* i8255)
414 {
415     i8255->reg[3] = 0x9b;
416 
417     i8255->latchA = 0xff;
418     i8255->latchB = 0xff;
419     i8255->latchC = 0xff;
420 
421     i8255Write(i8255, 0, 0);
422     i8255Write(i8255, 1, 0);
423     i8255Write(i8255, 2, 0);
424 }
425 
426 void i8255Destroy(I8255* i8255)
427 {
428     free(i8255);
429 }
430 
431 void i8255LoadState(I8255* i8255)
432 {
433     SaveState* state = saveStateOpenForRead("i8255");
434 
435     i8255->reg[0] = (UInt8)saveStateGet(state, "reg00", 0);
436     i8255->reg[1] = (UInt8)saveStateGet(state, "reg01", 0);
437     i8255->reg[2] = (UInt8)saveStateGet(state, "reg02", 0);
438     i8255->reg[3] = (UInt8)saveStateGet(state, "reg03", 0);
439 
440     saveStateClose(state);
441 }
442 
443 void i8255SaveState(I8255* i8255)
444 {
445     SaveState* state = saveStateOpenForWrite("i8255");
446 
447     saveStateSet(state, "reg00", i8255->reg[0]);
448     saveStateSet(state, "reg01", i8255->reg[1]);
449     saveStateSet(state, "reg02", i8255->reg[2]);
450     saveStateSet(state, "reg03", i8255->reg[3]);
451 
452     saveStateClose(state);
453 }
454 
455 #define INTR_B 0x01
456 #define IBF_B  0x02
457 #define OBF_B  0x02
458 #define STB_B  0x04
459 #define ACK_B  0x04
460 #define INTR_A 0x08
461 #define STB_A  0x10
462 #define IBF_A  0x20
463 #define ACK_A  0x40
464 #define OBF_A  0x80
465 
466 
467 void i8255WriteLatchA(I8255* i8255, UInt8 value)
468 {
469     if (i8255->reg[3] & 0x01) {
470         return;
471     }
472 
473     switch (i8255->reg[3] & 0x60) {
474     case 0x00: // MODE 0
475         i8255->latchA = value;
476         break;
477     default: // MODE 1 and MODE 2
478         if (!(i8255->reg[2] & IBF_A)) {
479             if (i8255->latchA != value) {
480                 i8255->reg[2] |= IBF_A;
481                 i8255->reg[2] |= STB_A;
482                 i8255->latchA = value;
483                 if (i8255->reg[3] & 0x10) {
484                     i8255->reg[2] |= INTR_A;
485                     i8255->writeCLo(i8255->ref, i8255->reg[2] & 0x0f);
486                     i8255->writeCHi(i8255->ref, i8255->reg[2] >> 4);
487                 }
488                 }
489         }
490         break;
491     }
492 }
493 
494 void i8255WriteLatchB(I8255* i8255, UInt8 value)
495 {
496     if (i8255->reg[3] & 0x08) {
497         return;
498     }
499     switch (i8255->reg[3] & 0x04) {
500     case 0x00: // MODE 0
501         i8255->latchB = value;
502         break;
503     default: // MODE 1
504         if (!(i8255->reg[2] & IBF_B)) {
505             if (i8255->latchB != value) {
506                 i8255->reg[2] |= IBF_B;
507                 i8255->reg[2] |= STB_B;
508                 i8255->latchB = value;
509                 if (i8255->reg[3] & 0x04) {
510                     i8255->reg[2] |= INTR_B;
511                     i8255->writeCLo(i8255->ref, i8255->reg[2] & 0x0f);
512                 }
513             }
514         }
515         break;
516     }
517 }
518 
519 void i8255WriteLatchC(I8255* i8255, UInt8 value)
520 {
521     i8255->latchC = value;
522 }
523 
524 UInt8 i8255Peek(I8255* i8255, UInt16 port)
525 {
526     UInt8 value;
527 
528     port &= 0x03;
529 
530     switch (port) {
531     case 0:
532         switch (i8255->reg[3] & 0x60) {
533         case 0x00: // MODE 0
534             if (i8255->reg[3] & 0x10) {
535                 if (i8255->useInputLatch) {
536                     return i8255->latchA;
537                 }
538                 return i8255->peekA(i8255->ref);
539             }
540             return i8255->reg[0];
541 
542         case 0x20: // MODE 1
543             if (i8255->useInputLatch) {
544                 return i8255->latchA;
545             }
546             return 0xff;
547 
548         default: // MODE 2
549             if (i8255->useInputLatch) {
550                 return i8255->latchA;
551             }
552             return 0xff;
553         }
554         break;
555 
556     case 1:
557         switch (i8255->reg[3] & 0x04) {
558         case 0x00: // MODE 0
559             if (i8255->reg[3] & 0x02) {
560                 if (i8255->useInputLatch) {
561                     return i8255->latchB;
562                 }
563                 return i8255->peekA(i8255->ref);
564             }
565             return i8255->reg[1];
566 
567         default: // MODE 1
568             if (i8255->useInputLatch) {
569                 return i8255->latchB;
570             }
571             return 0xff;
572         }
573         break;
574 
575     case 2:
576         value = i8255->reg[2];
577 
578         if (i8255->reg[3] & 0x01) {
579             if (i8255->useInputLatch) {
580                 value = (value & 0xf0) | (i8255->latchC & 0x0f);
581             }
582             else {
583                 value = (value & 0xf0) | (i8255->peekCLo(i8255->ref) & 0x0f);
584             }
585         }
586         if (i8255->reg[3] & 0x08) {
587             if (i8255->useInputLatch) {
588                 value = (value & 0xf0) | (i8255->latchC & 0xf0);
589             }
590             else {
591                 value = (value & 0x0f) | (i8255->peekCHi(i8255->ref) << 4);
592             }
593         }
594         return value;
595 
596     case 3:
597         return i8255->reg[3];
598     }
599 
600     return 0xff;
601 }
602 
603 UInt8 i8255Read(I8255* i8255, UInt16 port)
604 {
605     UInt8 value;
606 
607     port &= 0x03;
608 
609     switch (port) {
610     case 0:
611         switch (i8255->reg[3] & 0x60) {
612         case 0x00: // MODE 0
613             if (i8255->reg[3] & 0x10) {
614                 if (i8255->useInputLatch) {
615                     return i8255->latchA;
616                 }
617                 return i8255->readA(i8255->ref);
618             }
619             return i8255->reg[0];
620 
621         case 0x20: // MODE 1
622             if (i8255->useInputLatch) {
623                 return i8255->latchA;
624             }
625             i8255->reg[2] &= ~IBF_A;
626             return 0xff;
627 
628         default: // MODE 2
629             if (i8255->useInputLatch) {
630                 return i8255->latchA;
631             }
632             i8255->reg[2] &= ~IBF_A;
633             return 0xff;
634         }
635         break;
636 
637     case 1:
638         switch (i8255->reg[3] & 0x04) {
639         case 0x00: // MODE 0
640             if (i8255->reg[3] & 0x02) {
641                 if (i8255->useInputLatch) {
642                     return i8255->latchB;
643                 }
644                 return i8255->readB(i8255->ref);
645             }
646             return i8255->reg[1];
647 
648         default: // MODE 1
649             if (i8255->useInputLatch) {
650                 return i8255->latchB;
651             }
652             i8255->reg[2] &= ~IBF_B;
653             return 0xff;
654         }
655         break;
656 
657     case 2:
658         value = i8255->reg[2];
659 
660         if (i8255->reg[3] & 0x60) {
661             value &= ~0x60;
662             if (i8255->reg[3] & 0x10) {
663                 if (i8255->reg[3] & 0x01) {
664                     value |= 20;
665                 }
666                 else {
667                     value |= 40;
668                 }
669             }
670         }
671 
672         if (i8255->reg[3] & 0x04) {
673             value &= ~0x04;
674             if (i8255->reg[3] & 0x04) {
675                 value |= 0x04;
676             }
677         }
678 
679         if (i8255->reg[3] & 0x01) {
680             if (i8255->useInputLatch) {
681                 value = (value & 0xf0) | (i8255->latchC & 0x0f);
682             }
683             else {
684                 value = (value & 0xf0) | (i8255->readCLo(i8255->ref) & 0x0f);
685             }
686         }
687         if (i8255->reg[3] & 0x08) {
688             if (i8255->useInputLatch) {
689                 value = (value & 0xf0) | (i8255->latchC & 0xf0);
690             }
691             else {
692                 value = (value & 0x0f) | (i8255->readCHi(i8255->ref) << 4);
693             }
694         }
695 
696         return value;
697 
698     case 3:
699         return i8255->reg[3];
700     }
701 
702     return 0xff;
703 }
704 
705 void i8255Write(I8255* i8255, UInt16 port, UInt8 value)
706 {
707     port &= 0x03;
708 
709     switch (port) {
710     case 0:
711         switch (i8255->reg[3] & 0x60) {
712         case 0x00: // MODE 0
713             break;
714         case 0x20: // MODE 1
715             break;
716         default: // MODE 2
717             break;
718         }
719 
720         i8255->reg[0] = value;
721 
722         if (!(i8255->reg[3] & 0x10)) {
723             i8255->writeA(i8255->ref, value);
724         }
725         return;
726 
727     case 1:
728         switch (i8255->reg[3] & 0x04) {
729         case 0x00: // MODE 0
730             break;
731         default: // MODE 1
732             break;
733         }
734 
735         i8255->reg[1] = value;
736 
737         if (!(i8255->reg[3] & 0x02)) {
738             i8255->writeB(i8255->ref, value);
739         }
740         return;
741 
742     case 2:
743         {
744             UInt8 mask = 0xff;
745 
746             if (i8255->reg[3] & 0x04) {
747                 mask &= 0xf8;
748             }
749             if (i8255->reg[3] & 0x60) {
750                 mask &= 0x07;
751             }
752 
753             if (!(i8255->reg[3] & 0x01) && (mask & 0x0f)) {
754                 i8255->writeCLo(i8255->ref, value & mask & 0x0f);
755             }
756             if (!(i8255->reg[3] & 0x08) && (mask & 0xf0)) {
757                 i8255->writeCHi(i8255->ref, value >> 4);
758             }
759 
760             i8255->reg[2] = (i8255->reg[2] & ~mask) | (value & mask);
761         }
762         return;
763 
764     case 3:
765         if (value & 0x80) {
766             if (value != i8255->reg[3]) {
767                 // Mode change
768 
769                 if (value & 0x60) {
770                     i8255->reg[2] = (i8255->reg[2] & 0xf8) | 0x00;
771                 }
772 
773                 if (value & 0x04) {
774                     i8255->reg[2] = (i8255->reg[2] & 0x07) | 0x00;
775                 }
776             }
777 
778             i8255->reg[3] = value;
779             i8255Write(i8255, 0, i8255->reg[0]);
780             i8255Write(i8255, 1, i8255->reg[1]);
781             i8255Write(i8255, 2, i8255->reg[2]);
782         }
783         else {
784             UInt8 mask = 1 << ((value >> 1) & 0x07);
785             if (value & 0x01) {
786                 i8255Write(i8255, 2, i8255->reg[2] | mask);
787             }
788             else {
789                 i8255Write(i8255, 2, i8255->reg[2] & ~mask);
790             }
791         }
792         return;
793     }
794 }
795 #endif