Previous 15994 Revisions Next

r5192 Thursday 9th July, 2009 at 15:47:09 UTC by Curt Coder
[V1050] Fixed floppy access and Z80<->M6502 video interface.
[I8255] Rewrote the I8255 device from scratch to properly support handshaking. This will be submitted to mamedev, so it can be handled the same way as 6821new was.
[src/mess]mess.mak
[src/mess/drivers]v1050.c
[src/mess/includes]v1050.h
[src/mess/machine]i8255a.c* i8255a.h*
[src/mess/video]v1050.c

src/mess/video/v1050.c
r5191r5192
77   TODO:
88
99   - row update
10   - vsync interrupt
10   - vsync interrupt to Z80
1111
1212*/
1313
src/mess/includes/v1050.h
r5191r5192
44#define SCREEN_TAG            "screen"
55
66#define Z80_TAG               "u80"
7#define RTC_PPI8255_TAG         "u36"
7#define I8255_RTC_TAG         "u36"
88#define UPB8214_TAG            "u38"
9#define KB_MSM8251_TAG         "u85"
9#define I8251_KB_TAG         "u85"
1010#define RTC58321_TAG         "u26"
11#define SIO_MSM8251_TAG         "u8"
12#define FDC_PPI8255_TAG         "u10"
11#define I8251_SIO_TAG         "u8"
12#define I8255_MISC_TAG         "u10"
1313#define MB8877_TAG            "u13"
1414#define FDC9216_TAG            "u25"
15#define CRT_Z80_PPI8255_TAG      "u79"
15#define I8255_DISP_TAG         "u79"
1616#define M6502_TAG            "u76"
17#define CRT_M6502_PPI8255_TAG   "u101"
17#define I8255_M6502_TAG         "u101"
1818#define HD6845_TAG            "u75"
1919#define I8049_TAG            "z5"
2020#define CENTRONICS_TAG         "centronics"
r5191r5192
2727{
2828   /* memory state */
2929   UINT8 bank;
30   UINT8 int_mask;
3031
3132   /* floppy state */
3233   int f_int_enb;
r5191r5192
3536   UINT8 *video_ram;
3637   UINT8 *attr_ram;
3738   UINT8 attr;
39   int ppi8255_z80_pc;
40   int ppi8255_m6502_pc;
3841
3942   /* devices */
4043   const device_config *upb8214;
44   const device_config *i8255a_crt_z80;
45   const device_config *i8255a_crt_m6502;
4146   const device_config *mb8877;
4247   const device_config *mc6845;
4348   const device_config *centronics;
src/mess/machine/i8255a.c
r0r5192
1/**********************************************************************
2
3    Intel 8255A Programmable Peripheral Interface emulation
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************/
9
10#include "driver.h"
11#include "i8255a.h"
12
13/***************************************************************************
14    PARAMETERS
15***************************************************************************/
16
17#define LOG 0
18
19enum
20{
21   PORT_A = 0,
22   PORT_B,
23   PORT_C,
24   CONTROL
25};
26
27enum
28{
29   GROUP_A = 0,
30   GROUP_B
31};
32
33enum
34{
35   MODE_0 = 0,
36   MODE_1,
37   MODE_2
38};
39
40enum
41{
42   MODE_OUTPUT = 0,
43   MODE_INPUT,
44};
45
46#define I8255A_CONTROL_PORT_C_LOWER_INPUT   0x01
47#define I8255A_CONTROL_PORT_B_INPUT         0x02
48#define I8255A_CONTROL_GROUP_B_MODE_1      0x04
49#define I8255A_CONTROL_PORT_C_UPPER_INPUT   0x08
50#define I8255A_CONTROL_PORT_A_INPUT         0x10
51#define I8255A_CONTROL_GROUP_A_MODE_MASK   0x60
52#define I8255A_CONTROL_MODE_SET            0x80
53
54/***************************************************************************
55    TYPE DEFINITIONS
56***************************************************************************/
57
58typedef struct _i8255a_t i8255a_t;
59struct _i8255a_t
60{
61   devcb_resolved_read8      in_port_func[3];
62   devcb_resolved_write8      out_port_func[3];
63
64   UINT8 control;            /* mode control word */
65   UINT8 output[3];         /* output latch */
66   UINT8 input[3];            /* input latch */
67
68   int ibf[2];               /* input buffer full flag */
69   int obf[2];               /* output buffer full flag, negative logic */
70   int inte[2];            /* interrupt enable */
71   int inte1;               /* interrupt enable */
72   int inte2;               /* interrupt enable */
73   int intr[2];            /* interrupt */
74};
75
76/***************************************************************************
77    INLINE FUNCTIONS
78***************************************************************************/
79
80INLINE i8255a_t *get_safe_token(const device_config *device)
81{
82   assert(device != NULL);
83   assert(device->token != NULL);
84
85   return (i8255a_t *)device->token;
86}
87
88INLINE const i8255a_interface *get_interface(const device_config *device)
89{
90   assert(device != NULL);
91   assert((device->type == I8255A));
92   return (const i8255a_interface *) device->static_config;
93}
94
95INLINE int group_mode(i8255a_t *i8255a, int group)
96{
97   int mode = 0;
98
99   switch (group)
100   {
101   case GROUP_A:
102      switch ((i8255a->control & I8255A_CONTROL_GROUP_A_MODE_MASK) >> 5)
103      {
104      case 0: mode = MODE_0; break;
105      case 1: mode = MODE_1; break;
106      case 2: case 3: mode = MODE_2; break;
107      }
108      break;
109
110   case GROUP_B:
111      mode = i8255a->control & I8255A_CONTROL_GROUP_B_MODE_1 ? MODE_1 : MODE_0;
112      break;
113   }
114
115   return mode;
116}
117
118INLINE int port_mode(i8255a_t *i8255a, int port)
119{
120   int mode = 0;
121
122   switch (port)
123   {
124   case PORT_A: mode = i8255a->control & I8255A_CONTROL_PORT_A_INPUT ? MODE_INPUT : MODE_OUTPUT; break;
125   case PORT_B: mode = i8255a->control & I8255A_CONTROL_PORT_B_INPUT ? MODE_INPUT : MODE_OUTPUT; break;
126   }
127
128   return mode;
129}
130
131INLINE int port_c_lower_mode(i8255a_t *i8255a)
132{
133   return i8255a->control & I8255A_CONTROL_PORT_C_LOWER_INPUT ? MODE_INPUT : MODE_OUTPUT;
134}
135
136INLINE int port_c_upper_mode(i8255a_t *i8255a)
137{
138   return i8255a->control & I8255A_CONTROL_PORT_C_UPPER_INPUT ? MODE_INPUT : MODE_OUTPUT;
139}
140
141/***************************************************************************
142    IMPLEMENTATION
143***************************************************************************/
144
145static void output_pc(i8255a_t *i8255a)
146{
147   UINT8 data = 0;
148   UINT8 mask = 0;
149
150   /* PC upper */
151   switch (group_mode(i8255a, GROUP_A))
152   {
153   case MODE_0:
154      if (port_c_upper_mode(i8255a) == MODE_OUTPUT)
155      {
156         mask |= 0xf0;
157      }
158      break;
159
160   case MODE_1:
161      data |= i8255a->intr[PORT_A] ? 0x08 : 0x00;
162     
163      if (port_mode(i8255a, PORT_A) == MODE_OUTPUT)
164      {
165         data |= i8255a->obf[PORT_A] ? 0x80 : 0x00;
166         mask |= 0x30;
167      }
168      else
169      {
170         data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00;
171         mask |= 0xc0;
172      }
173      break;
174
175   case MODE_2:
176      data |= i8255a->intr[PORT_A] ? 0x08 : 0x00;
177      data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00;
178      data |= i8255a->obf[PORT_A] ? 0x80 : 0x00;
179      break;
180   }
181
182   /* PC lower */
183   switch (group_mode(i8255a, GROUP_B))
184   {
185   case MODE_0:
186      if (port_c_lower_mode(i8255a) == MODE_OUTPUT)
187      {
188         mask |= 0x0f;
189      }
190      break;
191
192   case MODE_1:
193      data |= i8255a->intr[PORT_B] ? 0x01 : 0x00;
194
195      if (port_mode(i8255a, PORT_B) == MODE_OUTPUT)
196      {
197         data |= i8255a->obf[PORT_B] ? 0x02 : 0x00;
198      }
199      else
200      {
201         data |= i8255a->ibf[PORT_B] ? 0x02 : 0x00;
202      }
203   }
204
205   data |= i8255a->output[PORT_C] & mask;
206
207   devcb_call_write8(&i8255a->out_port_func[PORT_C], 0, data);
208}
209
210static void check_interrupt(i8255a_t *i8255a, int port)
211{
212   switch (group_mode(i8255a, port))
213   {
214   case MODE_1:
215      switch (port_mode(i8255a, port))
216      {
217      case MODE_INPUT:
218         if (i8255a->inte[port] && i8255a->ibf[port])
219         {
220            if (LOG) logerror("8255A Port %c INTR: 1\n", 'A' + port);
221
222            i8255a->intr[port] = 1;
223         }
224         break;
225
226      case MODE_OUTPUT:
227         if (i8255a->inte[port] && i8255a->obf[port])
228         {
229            if (LOG) logerror("8255A Port %c INTR: 1\n", 'A' + port);
230
231            i8255a->intr[port] = 1;
232         }
233         break;
234      }
235      break;
236
237   case MODE_2:
238      if ((i8255a->inte1 && i8255a->obf[port]) || (i8255a->inte2 && i8255a->ibf[port]))
239      {
240         if (LOG) logerror("8255A Port %c INTR: 1\n", 'A' + port);
241
242         i8255a->intr[port] = 1;
243      }
244      break;
245   }
246
247   output_pc(i8255a);
248}
249
250static void set_ibf(i8255a_t *i8255a, int port, int state)
251{
252   if (LOG) logerror("8255A Port %c IBF: %u\n", 'A' + port, state);
253
254   i8255a->ibf[port] = state;
255
256   check_interrupt(i8255a, port);
257}
258
259static void set_obf(i8255a_t *i8255a, int port, int state)
260{
261   if (LOG) logerror("8255A Port %c OBF: %u\n", 'A' + port, state);
262
263   i8255a->obf[port] = state;
264   
265   check_interrupt(i8255a, port);
266}
267
268static void set_inte(i8255a_t *i8255a, int port, int state)
269{
270   if (LOG) logerror("8255A Port %c INTE: %u\n", 'A' + port, state);
271
272   i8255a->inte[port] = state;
273   
274   check_interrupt(i8255a, port);
275}
276
277static void set_inte1(i8255a_t *i8255a, int state)
278{
279   if (LOG) logerror("8255A Port A INTE1: %u\n", state);
280
281   i8255a->inte1 = state;
282   
283   check_interrupt(i8255a, PORT_A);
284}
285
286static void set_inte2(i8255a_t *i8255a, int state)
287{
288   if (LOG) logerror("8255A Port A INTE2: %u\n", state);
289
290   i8255a->inte2 = state;
291   
292   check_interrupt(i8255a, PORT_A);
293}
294
295static void set_intr(i8255a_t *i8255a, int port, int state)
296{
297   if (LOG) logerror("8255A Port %c INTR: %u\n", 'A' + port, state);
298
299   i8255a->intr[port] = state;
300
301   output_pc(i8255a);
302}
303
304static UINT8 read_mode0(i8255a_t *i8255a, int port)
305{
306   UINT8 data = 0;
307
308   if (port_mode(i8255a, port) == MODE_OUTPUT)
309   {
310      /* read data from output latch */
311      data = i8255a->output[port];
312   }
313   else
314   {
315      /* read data from port */
316      data = devcb_call_read8(&i8255a->in_port_func[port], 0);
317   }
318
319   return data;
320}
321
322static UINT8 read_mode1(i8255a_t *i8255a, int port)
323{
324   UINT8 data = 0;
325
326   if (port_mode(i8255a, port) == MODE_OUTPUT)
327   {
328      /* read data from output latch */
329      data = i8255a->output[port];
330   }
331   else
332   {
333      /* read data from input latch */
334      data = i8255a->input[port];
335
336      /* clear input buffer full flag */
337      set_ibf(i8255a, port, 0);
338
339      /* clear interrupt */
340      set_intr(i8255a, port, 0);
341   }
342
343   return data;
344}
345
346static UINT8 read_mode2(i8255a_t *i8255a)
347{
348   UINT8 data = 0;
349
350   /* read data from input latch */
351   data = i8255a->input[PORT_A];
352
353   /* clear input buffer full flag */
354   set_ibf(i8255a, PORT_A, 0);
355
356   return data;
357}
358
359static UINT8 read_pc(i8255a_t *i8255a)
360{
361   UINT8 data = 0;
362   UINT8 mask = 0;
363
364   /* PC upper */
365   switch (group_mode(i8255a, GROUP_A))
366   {
367   case MODE_0:
368      if (port_c_upper_mode(i8255a) == MODE_OUTPUT)
369      {
370         /* read data from output latch */
371         data |= i8255a->output[PORT_C] & 0xf0;
372      }
373      else
374      {
375         /* read data from port */
376         mask |= 0xf0;
377      }
378      break;
379
380   case MODE_1:
381      data |= i8255a->intr[PORT_A] ? 0x08 : 0x00;
382     
383      if (port_mode(i8255a, PORT_A) == MODE_OUTPUT)
384      {
385         data |= i8255a->obf[PORT_A] ? 0x80 : 0x00;
386         data |= i8255a->inte[PORT_A] ? 0x40 : 0x00;
387         mask |= 0x30;
388      }
389      else
390      {
391         data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00;
392         data |= i8255a->inte[PORT_A] ? 0x10 : 0x00;
393         mask |= 0xc0;
394      }
395      break;
396
397   case MODE_2:
398      data |= i8255a->intr[PORT_A] ? 0x08 : 0x00;
399      data |= i8255a->inte2 ? 0x10 : 0x00;
400      data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00;
401      data |= i8255a->inte1 ? 0x40 : 0x00;
402      data |= i8255a->obf[PORT_A] ? 0x80 : 0x00;
403      break;
404   }
405
406   /* PC lower */
407   switch (group_mode(i8255a, GROUP_B))
408   {
409   case MODE_0:
410      if (port_c_lower_mode(i8255a) == MODE_OUTPUT)
411      {
412         /* read data from output latch */
413         data |= i8255a->output[PORT_C] & 0x0f;
414      }
415      else
416      {
417         /* read data from port */
418         mask |= 0x0f;
419      }
420      break;
421
422   case MODE_1:
423      data |= i8255a->inte[PORT_B] ? 0x04 : 0x00;
424      data |= i8255a->intr[PORT_B] ? 0x01 : 0x00;
425
426      if (port_mode(i8255a, PORT_B) == MODE_OUTPUT)
427      {
428         data |= i8255a->obf[PORT_B] ? 0x02 : 0x00;
429      }
430      else
431      {
432         data |= i8255a->ibf[PORT_B] ? 0x02 : 0x00;
433      }
434   }
435
436   if (mask)
437   {
438      /* read data from port */
439      data |= devcb_call_read8(&i8255a->in_port_func[PORT_C], 0) & mask;
440   }
441   
442   return data;
443}
444
445READ8_DEVICE_HANDLER( i8255a_r )
446{
447   i8255a_t *i8255a = get_safe_token(device);
448
449   UINT8 data = 0;
450
451   switch (offset & 0x03)
452   {
453   case PORT_A:
454      switch (group_mode(i8255a, GROUP_A))
455      {
456      case MODE_0: data = read_mode0(i8255a, PORT_A); break;
457      case MODE_1: data = read_mode1(i8255a, PORT_A); break;
458      case MODE_2: data = read_mode2(i8255a); break;
459      }
460      if (LOG) logerror("8255A '%s' Port A Read: %02x\n", device->tag, data);
461      break;
462
463   case PORT_B:
464      switch (group_mode(i8255a, GROUP_B))
465      {
466      case MODE_0: data = read_mode0(i8255a, PORT_B); break;
467      case MODE_1: data = read_mode1(i8255a, PORT_B); break;
468      }
469      if (LOG) logerror("8255A '%s' Port B Read: %02x\n", device->tag, data);
470      break;
471
472   case PORT_C:
473      data = read_pc(i8255a);
474      //if (LOG) logerror("8255A '%s' Port C Read: %02x\n", device->tag, data);
475      break;
476
477   case CONTROL:
478      data = i8255a->control;
479      if (LOG) logerror("8255A '%s' Mode Control Word Read: %02x\n", device->tag, data);
480      break;
481   }
482
483   return data;
484}
485
486static void write_mode0(i8255a_t *i8255a, int port, UINT8 data)
487{
488   if (port_mode(i8255a, port) == MODE_OUTPUT)
489   {
490      /* latch output data */
491      i8255a->output[port] = data;
492
493      /* write data to port */
494      devcb_call_write8(&i8255a->out_port_func[port], 0, data);
495   }
496}
497
498static void write_mode1(i8255a_t *i8255a, int port, UINT8 data)
499{
500   if (port_mode(i8255a, port) == MODE_OUTPUT)
501   {
502      /* latch output data */
503      i8255a->output[port] = data;
504
505      /* write data to port */
506      devcb_call_write8(&i8255a->out_port_func[port], 0, data);
507
508      /* set output buffer full flag */
509      set_obf(i8255a, port, 0);
510
511      /* clear interrupt */
512      set_intr(i8255a, port, 0);
513   }
514}
515
516static void write_mode2(i8255a_t *i8255a, UINT8 data)
517{
518   /* latch output data */
519   i8255a->output[PORT_A] = data;
520
521   /* write data to port */
522   devcb_call_write8(&i8255a->out_port_func[PORT_A], 0, data);
523
524   /* set output buffer full flag */
525   set_obf(i8255a, PORT_A, 0);
526
527   /* clear interrupt */
528   set_intr(i8255a, PORT_A, 0);
529}
530
531static void write_pc(i8255a_t *i8255a, UINT8 data)
532{
533   int changed = 0;
534
535   if (group_mode(i8255a, GROUP_A) == MODE_0)
536   {
537      /* PC upper */
538      if (port_c_upper_mode(i8255a) == MODE_OUTPUT)
539      {
540         i8255a->output[PORT_C] = (data & 0xf0) | (i8255a->output[PORT_C] & 0x0f);
541         changed = 1;
542      }
543
544      /* PC lower */
545      if (port_c_lower_mode(i8255a) == MODE_OUTPUT)
546      {
547         i8255a->output[PORT_C] = (i8255a->output[PORT_C] & 0xf0) | (data & 0x0f);
548         changed = 1;
549      }
550   }
551
552   if (changed)
553   {
554      output_pc(i8255a);
555   }
556}
557
558static void set_mode(const device_config *device, UINT8 data)
559{
560   i8255a_t *i8255a = get_safe_token(device);
561
562   i8255a->control = data;
563
564   /* group A */
565   i8255a->output[PORT_A] = 0;
566   i8255a->input[PORT_A] = 0;
567   i8255a->ibf[PORT_A] = 0;
568   i8255a->obf[PORT_A] = 1;
569   i8255a->inte[PORT_A] = 0;
570   i8255a->inte1 = 0;
571   i8255a->inte2 = 0;
572
573   if (LOG) logerror("8255A '%s' Group A Mode: %u\n", device->tag, group_mode(i8255a, GROUP_A));
574   if (LOG) logerror("8255A '%s' Port A Mode: %s\n", device->tag, (port_mode(i8255a, PORT_A) == MODE_OUTPUT) ? "output" : "input");
575   if (LOG) logerror("8255A '%s' Port C Upper Mode: %s\n", device->tag, (port_c_upper_mode(i8255a) == MODE_OUTPUT) ? "output" : "input");
576   if (LOG) logerror("8255A '%s' Group B Mode: %u\n", device->tag, group_mode(i8255a, GROUP_B));
577   if (LOG) logerror("8255A '%s' Port B Mode: %s\n", device->tag, (port_mode(i8255a, PORT_B) == MODE_OUTPUT) ? "output" : "input");
578   if (LOG) logerror("8255A '%s' Port C Lower Mode: %s\n", device->tag, (port_c_lower_mode(i8255a) == MODE_OUTPUT) ? "output" : "input");
579
580   /* group B */
581   i8255a->output[PORT_B] = 0;
582   i8255a->input[PORT_B] = 0;
583   i8255a->ibf[PORT_B] = 0;
584   i8255a->obf[PORT_B] = 1;
585   i8255a->inte[PORT_B] = 0;
586
587   i8255a->output[PORT_C] = 0;
588   i8255a->input[PORT_C] = 0;
589
590   output_pc(i8255a);
591}
592
593static void set_pc_bit(const device_config *device, int bit, int state)
594{
595   i8255a_t *i8255a = get_safe_token(device);
596
597   /* set output latch bit */
598   i8255a->output[PORT_C] &= ~(1 << bit);
599   i8255a->output[PORT_C] |= state << bit;
600
601   switch (group_mode(i8255a, GROUP_A))
602   {
603   case MODE_1:
604      if (port_mode(i8255a, PORT_A) == MODE_OUTPUT)
605      {
606         switch (bit)
607         {
608         case 3: set_intr(i8255a, PORT_A, state); break;
609         case 6: set_inte(i8255a, PORT_A, state); break;
610         case 7: set_obf(i8255a, PORT_A, state); break;
611         }
612      }
613      else
614      {
615         switch (bit)
616         {
617         case 3: set_intr(i8255a, PORT_A, state); break;
618         case 4: set_inte(i8255a, PORT_A, state); break;
619         case 5: set_ibf(i8255a, PORT_A, state); break;
620         }
621      }
622      break;
623
624   case MODE_2:
625      switch (bit)
626      {
627      case 3: set_intr(i8255a, PORT_A, state); break;
628      case 4: set_inte2(i8255a, state); break;
629      case 5: set_ibf(i8255a, PORT_A, state); break;
630      case 6: set_inte1(i8255a, state); break;
631      case 7: set_obf(i8255a, PORT_A, state); break;
632      }
633      break;
634   }
635
636   if (group_mode(i8255a, GROUP_B) == MODE_1)
637   {
638      switch (bit)
639      {
640      case 0: set_intr(i8255a, PORT_B, state); break;
641      case 1:
642         if (port_mode(i8255a, PORT_B) == MODE_OUTPUT)
643            set_obf(i8255a, PORT_B, state);
644         else
645            set_ibf(i8255a, PORT_B, state);
646         break;
647      case 2: set_inte(i8255a, PORT_B, state); break;
648      }
649   }
650
651   output_pc(i8255a);
652}
653
654WRITE8_DEVICE_HANDLER( i8255a_w )
655{
656   i8255a_t *i8255a = get_safe_token(device);
657
658   switch (offset & 0x03)
659   {
660   case PORT_A:
661      if (LOG) logerror("8255A '%s' Port A Write: %02x\n", device->tag, data);
662
663      switch (group_mode(i8255a, GROUP_A))
664      {
665      case MODE_0: write_mode0(i8255a, PORT_A, data); break;
666      case MODE_1: write_mode1(i8255a, PORT_A, data); break;
667      case MODE_2: write_mode2(i8255a, data); break;
668      }
669      break;
670
671   case PORT_B:
672      if (LOG) logerror("8255A '%s' Port B Write: %02x\n", device->tag, data);
673
674      switch (group_mode(i8255a, GROUP_B))
675      {
676      case MODE_0: write_mode0(i8255a, PORT_B, data); break;
677      case MODE_1: write_mode1(i8255a, PORT_B, data); break;
678      }
679      break;
680
681   case PORT_C:
682      if (LOG) logerror("8255A '%s' Port C Write: %02x\n", device->tag, data);
683
684      write_pc(i8255a, data);
685      break;
686
687   case CONTROL:
688      if (data & I8255A_CONTROL_MODE_SET)
689      {
690         if (LOG) logerror("8255A '%s' Mode Control Word: %02x\n", device->tag, data);
691
692         set_mode(device, data);
693      }
694      else
695      {
696         int bit = (data >> 1) & 0x07;
697         int state = BIT(data, 0);
698
699         if (LOG) logerror("8255A '%s' %s Bit %u\n", device->tag, state ? "Set" : "Reset", bit);
700   
701         set_pc_bit(device, bit, state);
702      }
703      break;
704   }
705}
706
707READ8_DEVICE_HANDLER( i8255a_pa_r )
708{
709   i8255a_t *i8255a = get_safe_token(device);
710
711   return i8255a->output[PORT_A];
712}
713
714READ8_DEVICE_HANDLER( i8255a_pb_r )
715{
716   i8255a_t *i8255a = get_safe_token(device);
717
718   return i8255a->output[PORT_B];
719}
720
721WRITE_LINE_DEVICE_HANDLER( i8255a_pc2_w )
722{
723   i8255a_t *i8255a = get_safe_token(device);
724
725   if (group_mode(i8255a, GROUP_B) == 1)
726   {
727      if (port_mode(i8255a, PORT_B) == MODE_OUTPUT)
728      {
729         /* port B acknowledge */
730         if (!i8255a->obf[PORT_B] && !state)
731         {
732            if (LOG) logerror("8255A '%s' Port B Acknowledge\n", device->tag);
733
734            /* clear output buffer flag */
735            set_obf(i8255a, PORT_B, 1);
736         }
737      }
738      else
739      {
740         /* port B strobe */
741         if (!i8255a->ibf[PORT_B] && !state)
742         {
743            if (LOG) logerror("8255A '%s' Port B Strobe\n", device->tag);
744
745            /* read port into latch */
746            i8255a->input[PORT_B] = devcb_call_read8(&i8255a->in_port_func[PORT_B], 0);
747
748            /* set input buffer flag */
749            set_ibf(i8255a, PORT_B, 1);
750         }
751      }
752   }
753}
754
755WRITE_LINE_DEVICE_HANDLER( i8255a_pc4_w )
756{
757   i8255a_t *i8255a = get_safe_token(device);
758
759   if ((group_mode(i8255a, GROUP_A) == 2) || ((group_mode(i8255a, GROUP_A) == 1) && (port_mode(i8255a, PORT_A) == MODE_INPUT)))
760   {
761      /* port A strobe */
762      if (!i8255a->ibf[PORT_A] && !state)
763      {
764         if (LOG) logerror("8255A '%s' Port A Strobe\n", device->tag);
765
766         /* read port into latch */
767         i8255a->input[PORT_A] = devcb_call_read8(&i8255a->in_port_func[PORT_A], 0);
768
769         /* set input buffer flag */
770         set_ibf(i8255a, PORT_A, 1);
771      }
772   }
773}
774
775WRITE_LINE_DEVICE_HANDLER( i8255a_pc6_w )
776{
777   i8255a_t *i8255a = get_safe_token(device);
778
779   if ((group_mode(i8255a, GROUP_A) == 2) || ((group_mode(i8255a, GROUP_A) == 1) && (port_mode(i8255a, PORT_A) == MODE_OUTPUT)))
780   {
781      /* port A acknowledge */
782      if (!i8255a->obf[PORT_A] && !state)
783      {
784         if (LOG) logerror("8255A '%s' Port A Acknowledge\n", device->tag);
785
786         /* clear output buffer flag */
787         set_obf(i8255a, PORT_A, 1);
788      }
789   }
790}
791
792/*-------------------------------------------------
793    DEVICE_START( i8255a )
794-------------------------------------------------*/
795
796static DEVICE_START( i8255a )
797{
798   i8255a_t *i8255a = get_safe_token(device);
799   const i8255a_interface *intf = get_interface(device);
800
801   /* resolve callbacks */
802   devcb_resolve_read8(&i8255a->in_port_func[PORT_A], &intf->in_pa_func, device);
803   devcb_resolve_read8(&i8255a->in_port_func[PORT_B], &intf->in_pb_func, device);
804   devcb_resolve_read8(&i8255a->in_port_func[PORT_C], &intf->in_pc_func, device);
805   devcb_resolve_write8(&i8255a->out_port_func[PORT_A], &intf->out_pa_func, device);
806   devcb_resolve_write8(&i8255a->out_port_func[PORT_B], &intf->out_pb_func, device);
807   devcb_resolve_write8(&i8255a->out_port_func[PORT_C], &intf->out_pc_func, device);
808
809   /* register for state saving */
810   state_save_register_device_item(device, 0, i8255a->control);
811   state_save_register_device_item_array(device, 0, i8255a->output);
812   state_save_register_device_item_array(device, 0, i8255a->input);
813   state_save_register_device_item_array(device, 0, i8255a->ibf);
814   state_save_register_device_item_array(device, 0, i8255a->obf);
815   state_save_register_device_item_array(device, 0, i8255a->inte);
816   state_save_register_device_item(device, 0, i8255a->inte1);
817   state_save_register_device_item(device, 0, i8255a->inte2);
818   state_save_register_device_item_array(device, 0, i8255a->intr);
819}
820
821/*-------------------------------------------------
822    DEVICE_RESET( i8255a )
823-------------------------------------------------*/
824
825static DEVICE_RESET( i8255a )
826{
827   i8255a_w(device, CONTROL, 0x9b);
828}
829
830/*-------------------------------------------------
831    DEVICE_GET_INFO( i8255a )
832-------------------------------------------------*/
833
834DEVICE_GET_INFO( i8255a )
835{
836   switch (state)
837   {
838      /* --- the following bits of info are returned as 64-bit signed integers --- */
839      case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(i8255a_t);               break;
840      case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = 0;                        break;
841      case DEVINFO_INT_CLASS:                     info->i = DEVICE_CLASS_PERIPHERAL;         break;
842
843      /* --- the following bits of info are returned as pointers to data or functions --- */
844      case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(i8255a);   break;
845      case DEVINFO_FCT_STOP:                     /* Nothing */                        break;
846      case DEVINFO_FCT_RESET:                     info->reset = DEVICE_RESET_NAME(i8255a);   break;
847
848      /* --- the following bits of info are returned as NULL-terminated strings --- */
849      case DEVINFO_STR_NAME:                     strcpy(info->s, "Intel 8255A");            break;
850      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "Intel 8085");            break;
851      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                  break;
852      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);               break;
853      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright MESS Team");      break;
854   }
855}
src/mess/machine/i8255a.h
r0r5192
1/**********************************************************************
2
3    Intel 8255A Programmable Peripheral Interface emulation
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************
9                     _____   _____
10               PA3    1 |*    \_/     | 40  PA4
11               PA2    2 |          | 39  PA5
12               PA1    3 |          | 38  PA6
13               PA0    4 |          | 37  PA7
14               _RD    5 |          | 36  WR
15               _CS    6 |          | 35  RESET
16               GND    7 |          | 34  D0
17               A1    8 |          | 33  D1
18               A0    9 |          | 32  D2
19               PC7   10 |    8255A    | 31  D3
20               PC6   11 |          | 30  D4
21               PC5   12 |          | 29  D5
22               PC4   13 |          | 28  D6
23               PC0   14 |          | 27  D7
24               PC1   15 |          | 26  Vcc
25               PC2   16 |          | 25  PB7
26               PC3   17 |          | 24  PB6
27               PB0   18 |          | 23  PB5
28               PB1   19 |          | 22  PB4
29               PB2  20 |_____________| 21  PB3
30
31**********************************************************************/
32
33#ifndef __I8255A__
34#define __I8255A__
35
36#include "devcb.h"
37
38/***************************************************************************
39    MACROS / CONSTANTS
40***************************************************************************/
41
42#define I8255A      DEVICE_GET_INFO_NAME(i8255a)
43
44#define MDRV_I8255A_ADD(_tag, _intrf) \
45   MDRV_DEVICE_ADD(_tag, I8255A, 0) \
46   MDRV_DEVICE_CONFIG(_intrf)
47
48#define I8255A_INTERFACE(name) \
49   const i8255a_interface (name)=
50
51/***************************************************************************
52    TYPE DEFINITIONS
53***************************************************************************/
54
55typedef struct _i8255a_interface i8255a_interface;
56struct _i8255a_interface
57{
58   devcb_read8         in_pa_func;
59   devcb_read8         in_pb_func;
60   devcb_read8         in_pc_func;
61   
62   devcb_write8      out_pa_func;
63   devcb_write8      out_pb_func;
64   devcb_write8      out_pc_func;
65};
66
67/***************************************************************************
68    PROTOTYPES
69***************************************************************************/
70
71/* device interface */
72DEVICE_GET_INFO( i8255a );
73
74/* register access */
75READ8_DEVICE_HANDLER( i8255a_r );
76WRITE8_DEVICE_HANDLER( i8255a_w );
77
78/* port access */
79READ8_DEVICE_HANDLER( i8255a_pa_r );
80READ8_DEVICE_HANDLER( i8255a_pb_r );
81
82/* handshaking signals */
83WRITE_LINE_DEVICE_HANDLER( i8255a_pc2_w );
84WRITE_LINE_DEVICE_HANDLER( i8255a_pc4_w );
85WRITE_LINE_DEVICE_HANDLER( i8255a_pc6_w );
86
87#endif
src/mess/mess.mak
r5191r5192
14031403$(MESSOBJ)/visual.a:         \
14041404   $(MESS_DRIVERS)/v1050.o      \
14051405   $(MESS_VIDEO)/v1050.o      \
1406   $(MESS_MACHINE)/i8255a.o   \
14061407
14071408$(MESSOBJ)/votrax.a:         \
14081409   $(MESS_DRIVERS)/votrpss.o   \
src/mess/drivers/v1050.c
r5191r5192
1313   - video
1414   - µPB8214 chip
1515   - RTC58321 chip
16   - floppy
1716   - keyboard
18   - centronics
1917   - winchester
2018
2119*/
r5191r5192
2725#include "cpu/mcs48/mcs48.h"
2826#include "devices/basicdsk.h"
2927#include "machine/ctronics.h"
30#include "machine/8255ppi.h"
28#include "machine/i8255a.h"
3129#include "machine/msm8251.h"
3230#include "machine/wd17xx.h"
3331#include "video/mc6845.h"
r5191r5192
10199
102100static ADDRESS_MAP_START( v1050_io, ADDRESS_SPACE_IO, 8 )
103101   ADDRESS_MAP_UNMAP_HIGH
104//   AM_RANGE(0x84, 0x87) AM_DEVREADWRITE(CRT_Z80_PPI8255_TAG, ppi8255_r, ppi8255_w)
105//   AM_RANGE(0x88, 0x88) AM_DEVREADWRITE(KB_MSM8251_TAG, msm8251_data_r, msm8251_data_w)
106//   AM_RANGE(0x89, 0x89) AM_DEVREADWRITE(KB_MSM8251_TAG, msm8251_status_r, msm8251_control_w)
107//   AM_RANGE(0x8c, 0x8c) AM_DEVREADWRITE(SIO_MSM8251_TAG, msm8251_data_r, msm8251_data_w)
108//   AM_RANGE(0x8d, 0x8d) AM_DEVREADWRITE(SIO_MSM8251_TAG, msm8251_status_r, msm8251_control_w)
109//   AM_RANGE(0x90, 0x93) AM_DEVREADWRITE(FDC_PPI8255_TAG, ppi8255_r, ppi8255_w)
102   ADDRESS_MAP_GLOBAL_MASK(0xff)
103   AM_RANGE(0x84, 0x87) AM_DEVREADWRITE(I8255_DISP_TAG, i8255a_r, i8255a_w)
104//   AM_RANGE(0x88, 0x88) AM_DEVREADWRITE(I8251_KB_TAG, msm8251_data_r, msm8251_data_w)
105//   AM_RANGE(0x89, 0x89) AM_DEVREADWRITE(I8251_KB_TAG, msm8251_status_r, msm8251_control_w)
106//   AM_RANGE(0x8c, 0x8c) AM_DEVREADWRITE(I8251_SIO_TAG, msm8251_data_r, msm8251_data_w)
107//   AM_RANGE(0x8d, 0x8d) AM_DEVREADWRITE(I8251_SIO_TAG, msm8251_status_r, msm8251_control_w)
108   AM_RANGE(0x90, 0x93) AM_DEVREADWRITE(I8255_MISC_TAG, i8255a_r, i8255a_w)
110109   AM_RANGE(0x94, 0x97) AM_DEVREADWRITE(MB8877_TAG, wd17xx_r, wd17xx_w)
111//   AM_RANGE(0x9c, 0x9f) AM_DEVREADWRITE(RTC_PPI8255_TAG, ppi8255_r, ppi8255_w)
110   AM_RANGE(0x9c, 0x9f) AM_DEVREADWRITE(I8255_RTC_TAG, i8255a_r, i8255a_w)
112111//   AM_RANGE(0xa0, 0xa0) AM_READWRITE(vint_clr_r, vint_clr_w)
113112//   AM_RANGE(0xb0, 0xb0) AM_READWRITE(dint_clr_r, dint_clr_w)
114113//   AM_RANGE(0xc0, 0xc0) AM_DEVREADWRITE(UPB8214_TAG, pic8214_r, pic8214_w)
r5191r5192
121120   AM_RANGE(0x2000, 0x7fff) AM_RAM AM_READWRITE(v1050_videoram_r, v1050_videoram_w) AM_BASE_MEMBER(v1050_state, video_ram)
122121   AM_RANGE(0x8000, 0x8000) AM_DEVWRITE(HD6845_TAG, mc6845_address_w)
123122   AM_RANGE(0x8001, 0x8001) AM_DEVREADWRITE(HD6845_TAG, mc6845_register_r, mc6845_register_w)
124//   AM_RANGE(0x9000, 0x9003) AM_DEVREADWRITE(CRT_M6502_PPI8255_TAG, ppi8255_r, ppi8255_w)
123   AM_RANGE(0x9000, 0x9003) AM_DEVREADWRITE(I8255_M6502_TAG, i8255a_r, i8255a_w)
125124   AM_RANGE(0xa000, 0xa000) AM_READWRITE(v1050_attr_r, v1050_attr_w)
126125//   AM_RANGE(0xb000, 0xb000) AM_WRITE(z80int_w)
127126   AM_RANGE(0xc000, 0xc000) AM_WRITE(dvint_clr_w)
r5191r5192
258257   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
259258INPUT_PORTS_END
260259
260/* Display 8255A Interface */
261
262static WRITE8_DEVICE_HANDLER( crt_z80_ppi8255_c_w )
263{
264   v1050_state *state = device->machine->driver_data;
265
266   i8255a_pc2_w(state->i8255a_crt_m6502, BIT(data, 6));
267   i8255a_pc4_w(state->i8255a_crt_m6502, BIT(data, 7));
268}
269
270static I8255A_INTERFACE( disp_8255_intf )
271{
272   DEVCB_DEVICE_HANDLER(I8255_M6502_TAG, i8255a_pb_r),   // Port A read
273   DEVCB_NULL,                        // Port B read
274   DEVCB_NULL,                        // Port C read
275   DEVCB_NULL,                        // Port A write
276   DEVCB_NULL,                        // Port B write
277   DEVCB_HANDLER(crt_z80_ppi8255_c_w)      // Port C write
278};
279
280static WRITE8_DEVICE_HANDLER( crt_m6502_ppi8255_c_w )
281{
282   v1050_state *state = device->machine->driver_data;
283
284   i8255a_pc2_w(state->i8255a_crt_z80, BIT(data, 7));
285   i8255a_pc4_w(state->i8255a_crt_z80, BIT(data, 6));
286}
287
288static I8255A_INTERFACE( m6502_8255_intf )
289{
290   DEVCB_DEVICE_HANDLER(I8255_DISP_TAG, i8255a_pb_r),   // Port A read
291   DEVCB_NULL,                        // Port B read
292   DEVCB_NULL,                        // Port C read
293   DEVCB_NULL,                        // Port A write
294   DEVCB_NULL,                        // Port B write
295   DEVCB_HANDLER(crt_m6502_ppi8255_c_w)   // Port C write
296};
297
261298/* Miscellanous 8255A Interface */
262299
263static WRITE8_DEVICE_HANDLER( misc_ppi8255_a_w )
300static WRITE8_DEVICE_HANDLER( misc_8255_a_w )
264301{
265302   /*
266303
r5191r5192
284321   /* floppy drive select */
285322   if (BIT(data, 0)) wd17xx_set_drive(state->mb8877, 0);
286323   if (BIT(data, 1)) wd17xx_set_drive(state->mb8877, 1);
287   if (BIT(data, 2)) wd17xx_set_drive(state->mb8877, 2);
288   if (BIT(data, 3)) wd17xx_set_drive(state->mb8877, 3);
324//   if (BIT(data, 2)) wd17xx_set_drive(state->mb8877, 2);
325//   if (BIT(data, 3)) wd17xx_set_drive(state->mb8877, 3);
289326
290327   /* floppy side select */
291328   wd17xx_set_side(state->mb8877, BIT(data, 4));
r5191r5192
300337   wd17xx_set_density(state->mb8877, BIT(data, 7) ? DEN_FM_LO : DEN_FM_HI);
301338}
302339
303static READ8_DEVICE_HANDLER( misc_ppi8255_c_r )
340static READ8_DEVICE_HANDLER( misc_8255_c_r )
304341{
305342   /*
306343
r5191r5192
327364   return data;
328365}
329366
330static WRITE8_DEVICE_HANDLER( misc_ppi8255_c_w )
367static WRITE8_DEVICE_HANDLER( misc_8255_c_w )
331368{
332369   /*
333370
r5191r5192
353390   state->f_int_enb = BIT(data, 1);
354391}
355392
356static const ppi8255_interface misc_ppi8255_intf =
393static I8255A_INTERFACE( misc_8255_intf )
357394{
358395   DEVCB_NULL,                     // Port A read
359396   DEVCB_NULL,                     // Port B read
360   DEVCB_HANDLER(misc_ppi8255_c_r),   // Port C read
361   DEVCB_HANDLER(misc_ppi8255_a_w),   // Port A write
397   DEVCB_HANDLER(misc_8255_c_r),      // Port C read
398   DEVCB_HANDLER(misc_8255_a_w),      // Port A write
362399   DEVCB_DEVICE_HANDLER(CENTRONICS_TAG, centronics_data_w),// Port B write
363   DEVCB_HANDLER(misc_ppi8255_c_w)      // Port C write
400   DEVCB_HANDLER(misc_8255_c_w)      // Port C write
364401};
365402
403/* Real Time Clock 8255A Interface */
404
405static WRITE8_DEVICE_HANDLER( rtc_8255_b_w )
406{
407   /*
408
409        bit      signal      description
410
411      PB0               RS-232
412        PB1               Winchester
413        PB2               keyboard
414        PB3               floppy disk interrupt
415        PB4               vertical interrupt
416        PB5               display interrupt
417        PB6               expansion B
418        PB7               expansion A
419   
420   */
421
422   v1050_state *state = device->machine->driver_data;
423
424   state->int_mask = data;
425}
426
427static READ8_DEVICE_HANDLER( rtc_8255_c_r )
428{
429   /*
430
431        bit      signal      description
432
433      PC0     
434        PC1     
435        PC2     
436        PC3               clock busy
437        PC4               clock address write
438        PC5               clock data write
439        PC6               clock data read
440        PC7               clock device select
441   
442   */
443
444   return 0xff;
445}
446
447static WRITE8_DEVICE_HANDLER( rtc_8255_c_w )
448{
449   /*
450
451        bit      signal      description
452
453      PC0     
454        PC1     
455        PC2     
456        PC3               clock busy
457        PC4               clock address write
458        PC5               clock data write
459        PC6               clock data read
460        PC7               clock device select
461   
462   */
463}
464
465static I8255A_INTERFACE( rtc_8255_intf )
466{
467   DEVCB_NULL,                     // Port A read (RTC data)
468   DEVCB_NULL,                     // Port B read
469   DEVCB_HANDLER(rtc_8255_c_r),      // Port C read
470   DEVCB_NULL,                     // Port A write (RTC data)
471   DEVCB_HANDLER(rtc_8255_b_w),      // Port B write
472   DEVCB_HANDLER(rtc_8255_c_w)         // Port C write
473};
474
366475/* MB8877 Interface */
367476
368477static WD17XX_CALLBACK( v1050_mb8877_callback )
r5191r5192
403512
404513   /* find devices */
405514   state->upb8214 = devtag_get_device(machine, UPB8214_TAG);
515   state->i8255a_crt_z80 = devtag_get_device(machine, I8255_DISP_TAG);
516   state->i8255a_crt_m6502 = devtag_get_device(machine, I8255_M6502_TAG);
406517   state->mb8877 = devtag_get_device(machine, MB8877_TAG);
407518   state->centronics = devtag_get_device(machine, CENTRONICS_TAG);
408519
r5191r5192
452563   MDRV_IMPORT_FROM(v1050_video)
453564
454565   /* devices */
455   MDRV_PPI8255_ADD(FDC_PPI8255_TAG, misc_ppi8255_intf)
566   MDRV_I8255A_ADD(I8255_DISP_TAG, disp_8255_intf)
567   MDRV_I8255A_ADD(I8255_MISC_TAG, misc_8255_intf)
568   MDRV_I8255A_ADD(I8255_RTC_TAG, rtc_8255_intf)
456569   MDRV_WD1793_ADD(MB8877_TAG, v1050_wd17xx_intf )
457570
571   MDRV_I8255A_ADD(I8255_M6502_TAG, m6502_8255_intf)
572
458573   /* printer */
459574   MDRV_CENTRONICS_ADD(CENTRONICS_TAG, standard_centronics)
460575MACHINE_DRIVER_END
r5191r5192
463578
464579ROM_START( v1050 )
465580   ROM_REGION( 0x10000, Z80_TAG, 0 )
466   ROM_LOAD( "244-032.u86", 0x0000, 0x2000, CRC(46f847a7) SHA1(374db7a38a9e9230834ce015006e2f1996b9609a) )
581   ROM_LOAD( "e244-032 rev 1.2.u86", 0x0000, 0x2000, CRC(46f847a7) SHA1(374db7a38a9e9230834ce015006e2f1996b9609a) )
467582
468583   ROM_REGION( 0x10000, M6502_TAG, 0 )
469   ROM_LOAD( "244-033.u77", 0xe000, 0x2000, CRC(c0502b66) SHA1(bc0015f5b14f98110e652eef9f7c57c614683be5) )
584   ROM_LOAD( "e244-033 rev 1.1.u77", 0xe000, 0x2000, CRC(c0502b66) SHA1(bc0015f5b14f98110e652eef9f7c57c614683be5) )
470585
471586   ROM_REGION( 0x800, I8049_TAG, 0 )
472587   ROM_LOAD( "20-08049-410.z5", 0x0000, 0x0800, NO_DUMP )
r5191r5192
478593static DEVICE_IMAGE_LOAD( v1050_floppy )
479594{
480595   if (image_has_been_created(image))
596   {
481597      return INIT_FAIL;
598   }
482599
600   if (DEVICE_IMAGE_LOAD_NAME(basicdsk_floppy)(image) == INIT_PASS)
601   {
602      switch (image_length(image))
603      {
604      case 80*1*10*512: /* 400KB DSDD */
605         basicdsk_set_geometry(image, 80, 1, 10, 512, 1, 0, FALSE);
606         break;
607
608      default:
609         return INIT_FAIL;
610      }
611
612      return INIT_PASS;
613   }
614
483615   return INIT_FAIL;
484616}
485617

Previous 15994 Revisions Next


© 1998-2018 The MESS Team