summaryrefslogtreecommitdiffstats
path: root/io.c
blob: 6cdf17c0ff71881fc42a8f57f36989b76e8a32a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <stdio.h>
#include <dirent.h>

#include "z80.h"
#include "screen.h"

static uint8_t inports[256];
static uint8_t outports[256];

#define READ_MODE   0
#define WRITE_MODE  1


/*
 * Information about files.
 * Max 7 can be open at one time,  file #0 is never used.
 */
static struct {
    union {
        FILE *fp;
        DIR  *dp;
    } u;
    int	  mode;
} files[8];

/*
 * Set a port to a value which the z80 can read later.
 */
void
set_in_port(int port, uint8_t value)
{
    inports[port] = value;
}

/* Select code for ABC/4680 bus */
int abcbus_select = -1;

extern void disk_reset(void);
extern void disk_out(int, int, int);
extern int disk_in(int, int);
extern void printer_reset(void);
extern void printer_out(int, int, int);
extern int printer_in(int, int);

/*
 * This function is called from the z80 at an OUT instruction.
 * We check if any special port was accessed and
 * dispatch possible actions.
 */
void 
z80_out(int port, uint8_t value)
{
  if ( port == 1 )
    abcbus_select = value & 0x3f;

  if (port < 6) {
    switch (abcbus_select) {
    case 36:			/* HDx: */
    case 44:			/* MFx: */
    case 45:			/* MOx: */
    case 46:			/* SFx: */
      disk_out(abcbus_select, port, value);
      break;

    case 60:			/* PRx: */
      printer_out(abcbus_select, port, value);
      break;

    default:
      break;
    }
  } else if (port == 6 && value == 131) { /* beep */
    putchar(7);
    fflush(stdout);
  }
  outports[port] = value;
}


/*
 * This function is called from the z80 at an IN instruction.
 */
int 
z80_in(int port)
{
  if ( port == 7 ) {
    abcbus_select = -1;
    disk_reset();		/* Reset ALL devices */
    printer_reset();
  }

  if ( port == 0 || port == 1 ) {
    int v;

    switch (abcbus_select) {
    case 36:			/* HDx: */
    case 44:			/* MFx: */
    case 45:			/* MOx: */
    case 46:			/* SFx: */
      v = disk_in(abcbus_select, port);
      break;

    case 60:			/* PRx: */
      v = printer_in(abcbus_select, port);
      break;

    default:
      v = 0xff;
      break;
    }

    return v;
  }

  if ( port == 3 ) {
    setmode40(1);
  }

  if ( port == 4 ) {
    setmode40(0);
  }

  if (port == 56) {
    int v = inports[port];
    inports[port] &= ~0x80;
    return v;
  }
  
  return (int)inports[port];
}

void
io_init(void)
{
    int i;

    memset(inports, 0xff, sizeof inports);

    for (i = 0; i < 8; i++) {
        files[i].u.fp = NULL;
    }
}