OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [sim/] [disk.c] - Blame information for rev 25

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 hellwig
/*
2
 * disk.c -- disk simulation
3
 */
4
 
5
 
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <string.h>
9
#include <setjmp.h>
10
 
11
#include "common.h"
12
#include "console.h"
13
#include "error.h"
14
#include "except.h"
15
#include "cpu.h"
16
#include "timer.h"
17
#include "disk.h"
18
 
19
 
20
static Bool debug = false;
21
 
22
static FILE *diskImage;
23
static long totalSectors;
24
 
25
static Word diskCtrl;
26
static Word diskCnt;
27
static Word diskSct;
28
static Word diskCap;
29
 
30
static Byte diskBuffer[8 * SECTOR_SIZE];
31
 
32
static long lastSct;
33
 
34
 
35
static Word readWord(Byte *p) {
36
  Word data;
37
 
38
  data = ((Word) *(p + 0)) << 24 |
39
         ((Word) *(p + 1)) << 16 |
40
         ((Word) *(p + 2)) <<  8 |
41
         ((Word) *(p + 3)) <<  0;
42
  return data;
43
}
44
 
45
 
46
static void writeWord(Byte *p, Word data) {
47
  *(p + 0) = (Byte) (data >> 24);
48
  *(p + 1) = (Byte) (data >> 16);
49
  *(p + 2) = (Byte) (data >>  8);
50
  *(p + 3) = (Byte) (data >>  0);
51
}
52
 
53
 
54
static void diskCallback(int n) {
55
  int numScts;
56
 
57
  if (debug) {
58
    cPrintf("\n**** DISK CALLBACK, n = %d ****\n", n);
59
  }
60
  if (n == 0) {
61
    /* startup time expired */
62
    diskCap = totalSectors;
63
    diskCtrl |= DISK_READY;
64
    return;
65
  }
66
  /* disk read or write */
67
  numScts = ((diskCnt - 1) & 0x07) + 1;
68
  if (diskCap != 0 &&
69
      diskSct < diskCap &&
70
      diskSct + numScts <= diskCap) {
71
    /* do the transfer */
72
    if (fseek(diskImage, diskSct * SECTOR_SIZE, SEEK_SET) != 0) {
73
      error("cannot position to sector in disk image");
74
    }
75
    if (diskCtrl & DISK_WRT) {
76
      /* buffer --> disk */
77
      if (fwrite(diskBuffer, SECTOR_SIZE, numScts, diskImage) != numScts) {
78
        error("cannot write to disk image");
79
      }
80
    } else {
81
      /* disk --> buffer */
82
      if (fread(diskBuffer, SECTOR_SIZE, numScts, diskImage) != numScts) {
83
        error("cannot read from disk image");
84
      }
85
    }
86
    lastSct = (long) diskSct + (long) numScts - 1;
87
  } else {
88
    /* sectors requested exceed disk capacity */
89
    /* or we have no disk at all */
90
    diskCtrl |= DISK_ERR;
91
  }
92
  diskCtrl &= ~DISK_STRT;
93
  diskCtrl |= DISK_DONE;
94
  if (diskCtrl & DISK_IEN) {
95
    /* raise disk interrupt */
96
    cpuSetInterrupt(IRQ_DISK);
97
  }
98
}
99
 
100
 
101
Word diskRead(Word addr) {
102
  Word data;
103
 
104
  if (debug) {
105
    cPrintf("\n**** DISK READ from 0x%08X", addr);
106
  }
107
  if (addr == DISK_CTRL) {
108
    data = diskCtrl;
109
  } else
110
  if (addr == DISK_CNT) {
111
    data = diskCnt;
112
  } else
113
  if (addr == DISK_SCT) {
114
    data = diskSct;
115
  } else
116
  if (addr == DISK_CAP) {
117
    data = diskCap;
118
  } else
119
  if (addr & 0x80000) {
120
    /* buffer access */
121
    data = readWord(diskBuffer + (addr & 0x0FFC));
122
  } else {
123
    /* illegal register */
124
    throwException(EXC_BUS_TIMEOUT);
125
  }
126
  if (debug) {
127
    cPrintf(", data = 0x%08X ****\n", data);
128
  }
129
  return data;
130
}
131
 
132
 
133
void diskWrite(Word addr, Word data) {
134
  long delta;
135
 
136
  if (debug) {
137
    cPrintf("\n**** DISK WRITE to 0x%08X, data = 0x%08X ****\n",
138
            addr, data);
139
  }
140
  if (addr == DISK_CTRL) {
141
    if (data & DISK_WRT) {
142
      diskCtrl |= DISK_WRT;
143
    } else {
144
      diskCtrl &= ~DISK_WRT;
145
    }
146
    if (data & DISK_IEN) {
147
      diskCtrl |= DISK_IEN;
148
    } else {
149
      diskCtrl &= ~DISK_IEN;
150
    }
151
    if (data & DISK_STRT) {
152
      diskCtrl |= DISK_STRT;
153
      diskCtrl &= ~DISK_ERR;
154
      diskCtrl &= ~DISK_DONE;
155
      /* only start a disk operation if disk is present */
156
      if (diskCap != 0) {
157
        delta = labs((long) diskSct - lastSct);
158
        if (delta > diskCap) {
159
          delta = diskCap;
160
        }
161 25 hellwig
        timerStart(DISK_DELAY_USEC + (delta * DISK_SEEK_USEC) / diskCap,
162 8 hellwig
                   diskCallback, 1);
163
      }
164
    } else {
165
      diskCtrl &= ~DISK_STRT;
166
      if (data & DISK_ERR) {
167
        diskCtrl |= DISK_ERR;
168
      } else {
169
        diskCtrl &= ~DISK_ERR;
170
      }
171
      if (data & DISK_DONE) {
172
        diskCtrl |= DISK_DONE;
173
      } else {
174
        diskCtrl &= ~DISK_DONE;
175
      }
176
    }
177
    if ((diskCtrl & DISK_IEN) != 0 &&
178
        (diskCtrl & DISK_DONE) != 0) {
179
      /* raise disk interrupt */
180
      cpuSetInterrupt(IRQ_DISK);
181
    } else {
182
      /* lower disk interrupt */
183
      cpuResetInterrupt(IRQ_DISK);
184
    }
185
  } else
186
  if (addr == DISK_CNT) {
187
    diskCnt = data;
188
  } else
189
  if (addr == DISK_SCT) {
190
    diskSct = data;
191
  } else
192
  if (addr == DISK_CAP) {
193
    /* this register is read-only */
194
    throwException(EXC_BUS_TIMEOUT);
195
  } else
196
  if (addr & 0x80000) {
197
    /* buffer access */
198
    writeWord(diskBuffer + (addr & 0x0FFC), data);
199
  } else {
200
    /* illegal register */
201
    throwException(EXC_BUS_TIMEOUT);
202
  }
203
}
204
 
205
 
206
void diskReset(void) {
207
  cPrintf("Resetting Disk...\n");
208
  diskCtrl = 0;
209
  diskCnt = 0;
210
  diskSct = 0;
211
  diskCap = 0;
212
  lastSct = 0;
213
  if (totalSectors != 0) {
214
    cPrintf("Disk of size %ld sectors (%ld bytes) installed.\n",
215
            totalSectors, totalSectors * SECTOR_SIZE);
216 25 hellwig
    timerStart(DISK_START_USEC, diskCallback, 0);
217 8 hellwig
  }
218
}
219
 
220
 
221
void diskInit(char *diskImageName) {
222
  long numBytes;
223
 
224
  if (diskImageName == NULL) {
225
    /* do not install disk */
226
    diskImage = NULL;
227
    totalSectors = 0;
228
  } else {
229
    /* try to install disk */
230
    diskImage = fopen(diskImageName, "r+b");
231
    if (diskImage == NULL) {
232
      error("cannot open disk image '%s'", diskImageName);
233
    }
234
    fseek(diskImage, 0, SEEK_END);
235
    numBytes = ftell(diskImage);
236
    fseek(diskImage, 0, SEEK_SET);
237
    if (numBytes % SECTOR_SIZE != 0) {
238
      error("disk image '%s' does not contain an integral number of sectors",
239
            diskImageName);
240
    }
241
    totalSectors = numBytes / SECTOR_SIZE;
242
  }
243
  diskReset();
244
}
245
 
246
 
247
void diskExit(void) {
248
  if (diskImage == NULL) {
249
    /* disk not installed */
250
    return;
251
  }
252
  fclose(diskImage);
253
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.