File: patch.floppy-athiel

package info (click to toggle)
bochs 2.3-2etch1
  • links: PTS
  • area: main
  • in suites: etch
  • size: 14,116 kB
  • ctags: 16,927
  • sloc: cpp: 130,524; ansic: 18,822; sh: 7,922; makefile: 3,836; yacc: 1,056; asm: 463; perl: 381; lex: 280; csh: 3
file content (306 lines) | stat: -rw-r--r-- 10,783 bytes parent folder | download | duplicates (5)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
----------------------------------------------------------------------
Patch name: patch.floppy-athiel
Author: Alex Thiel (uploaded by cbothamy)
Date: 8 Nov 2002
Status: Proposed 

Detailed description:
This patch  introduces the implicit termination of data transfer via 
end-of-track and data overrun/underrun conditions, as well as non-DMA mode.

The code cleanup is present in CVS now (Volker Ruppert, Dec 1st 2002).

We still have no test case for the non-DMA mode and the overrun/underrun (timeout)
code fails if cpu speedups are enabled. The timeout code expects at least one DMA
cycle within 15 usec (Volker Ruppert, Mar 12th 2005). 

Patch was created with:
  cvs diff -u
Apply patch to what version:
  cvs checked out on 11 Mar 2005
Instructions:
  To patch, go to main bochs directory.
  Type "patch -p0 < THIS_PATCH_FILE".
----------------------------------------------------------------------
Index: iodev/floppy.cc
===================================================================
RCS file: /cvsroot/bochs/bochs/iodev/floppy.cc,v
retrieving revision 1.77
diff -u -r1.77 floppy.cc
--- iodev/floppy.cc	2005-03-11 21:12:52 +0100
+++ iodev/floppy.cc	2005-03-12 15:23:40 +0200
@@ -73,11 +73,18 @@
 #define FD_MS_ACTB 0x02
 #define FD_MS_ACTA 0x01
 
+/* for status registers */
+#define FD_ST_EOT      0x80
+#define FD_ST_OVERRUN  0x10
+
 #define FROM_FLOPPY 10
 #define TO_FLOPPY   11
 
 #define FLOPPY_DMA_CHAN 2
 
+#define FD_TIMEOUT  15  // for FIFO overrun/underrun
+#define FD_IRQ_DELAY   2  // delay so the system can detect a INT change
+
 typedef struct {
   unsigned id;
   Bit8u trk;
@@ -391,6 +398,20 @@
       break;
 
     case 0x3F5: /* diskette controller data */
+
+      /* data transfer in non-DMA mode */
+      if (BX_FD_THIS s.main_status_reg & FD_MS_NDMA) {
+        BX_FD_THIS dma_write(&value); // write: from controller to cpu
+
+       /* This simulates the FIFO latency, see comment in timer() below. */
+        BX_FD_THIS lower_interrupt();
+        BX_FD_THIS s.main_status_reg &= ~FD_MS_MRQ;
+        // overrides the timer set in dma_write()
+        bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index, 
+                                    FD_IRQ_DELAY, 0); 
+        return(value);
+      }
+
       if (BX_FD_THIS s.result_size == 0) {
         BX_ERROR(("port 0x3f5: no results to read"));
         BX_FD_THIS s.main_status_reg = 0;
@@ -527,6 +548,20 @@
       break;
 
     case 0x3F5: /* diskette controller data */
+
+      /* data transfer in non-DMA mode */
+      if (BX_FD_THIS s.main_status_reg & FD_MS_NDMA) {
+        BX_FD_THIS dma_read((Bit8u *) &value); // read: from cpu to controller
+
+        /* This simulates the FIFO latency, see comment in timer() below. */
+        BX_FD_THIS lower_interrupt();
+        BX_FD_THIS s.main_status_reg &= ~FD_MS_MRQ;
+        // overrides the timer set in dma_read()
+        bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index,
+                                    FD_IRQ_DELAY, 0); 
+        break;
+      }
+
       BX_DEBUG(("command = %02x", (unsigned) value));
       if (BX_FD_THIS s.command_complete) {
         if (BX_FD_THIS s.pending_command!=0)
@@ -670,7 +705,7 @@
       head_load_time = BX_FD_THIS s.command[2] >> 1;
       BX_FD_THIS s.non_dma = BX_FD_THIS s.command[2] & 0x01;
       if (BX_FD_THIS s.non_dma)
-        BX_ERROR(("non DMA mode not implemented yet"));
+        BX_INFO(("non DMA mode selected"));
       enter_idle_phase();
       return;
       break;
@@ -839,10 +874,14 @@
       /* 4 header bytes per sector are required */
       BX_FD_THIS s.format_count <<= 2;
 
-      DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
-
-      /* data reg not ready, controller busy */
-      BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
+      if (BX_FD_THIS s.non_dma) {
+        BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_NDMA | FD_MS_BUSY;
+        BX_FD_THIS raise_interrupt();
+      } else {
+        /* data reg not ready, controller busy */
+        BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
+        DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
+      }
       BX_DEBUG(("format track"));
       return;
       break;
@@ -957,21 +996,25 @@
         floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
                     512, FROM_FLOPPY);
 
-        DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
-
-        /* data reg not ready, controller busy */
-        BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
-        return;
-        }
-      else if ((BX_FD_THIS s.command[0] & 0x7f) == 0x45) { // write
-
-        DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
-
-        /* data reg not ready, controller busy */
-        BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
-        return;
+        if (BX_FD_THIS s.non_dma) {
+          BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_NDMA | FD_MS_DIO | FD_MS_BUSY;
+          BX_FD_THIS raise_interrupt();
+        } else {
+          /* data reg not ready, controller busy */
+          BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
+          DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
+        }
+      } else if ((BX_FD_THIS s.command[0] & 0x7f) == 0x45) { // write
+
+        if (BX_FD_THIS s.non_dma) {
+          BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_NDMA | FD_MS_BUSY;
+          BX_FD_THIS raise_interrupt();
+        } else {
+          /* data reg not ready, controller busy */
+          BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
+          DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
         }
-      else
+      } else
         BX_PANIC(("floppy_command(): unknown read/write command"));
 
       return;
@@ -1138,6 +1181,31 @@
       enter_result_phase();
       break;
 
+    case 0x4d: // format track
+    case 0x46: // read normal data
+    case 0x66: 
+    case 0xc6:
+    case 0xe6:
+    case 0x45: // write normal data
+    case 0xc5: 
+      /* During non-DMA operation, the state of the FDC oscillates
+         between IRQ low/MRQ clear (set after data is transferred via 0x3f5)
+         and IRQ high/MRQ set. 
+         Whenever the timer is triggered in DMA mode, or in non-DMA mode with
+         MRQ set, we have a data overrun/underrun. */
+      if ((BX_FD_THIS s.main_status_reg & (FD_MS_MRQ | FD_MS_NDMA)) 
+          == FD_MS_NDMA) { // NDMA & !MRQ
+        BX_FD_THIS raise_interrupt();
+        BX_FD_THIS s.main_status_reg |= FD_MS_MRQ;
+        bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index, 
+                                    FD_TIMEOUT, 0 ); 
+      } else { // timeout
+        // FIXME: this code requires at least one DMA cycle within 15 usec
+        //BX_FD_THIS s.status_reg1 |= FD_ST_OVERRUN;
+        //enter_result_phase();
+      } 
+      break;
+
     case 0xfe: // (contrived) RESET
       theFloppyController->reset(BX_RESET_SOFTWARE);
       BX_FD_THIS s.pending_command = 0;
@@ -1163,9 +1231,11 @@
   // We need to return then next data byte from the floppy buffer
   // to be transfered via the DMA to memory. (read block from floppy)
 
-
   *data_byte = BX_FD_THIS s.floppy_buffer[BX_FD_THIS s.floppy_buffer_index++];
 
+  // reschedule timeout
+  bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index, FD_TIMEOUT, 0 ); 
+
   if (BX_FD_THIS s.floppy_buffer_index >= 512) {
     Bit8u drive;
 
@@ -1174,7 +1244,6 @@
     BX_FD_THIS s.floppy_buffer_index = 0;
     if (DEV_dma_get_tc()) { // Terminal Count line, done
       BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive;
-      BX_FD_THIS s.status_reg1 = 0;
       BX_FD_THIS s.status_reg2 = 0;
 
       if (bx_dbg.floppy) {
@@ -1215,6 +1284,9 @@
   Bit8u drive;
   Bit32u logical_sector;
 
+  // reschedule timeout
+  bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index, FD_TIMEOUT, 0 ); 
+
   drive = BX_FD_THIS s.DOR & 0x03;
   if (BX_FD_THIS s.pending_command == 0x4d) { // format track in progress
     --BX_FD_THIS s.format_count;
@@ -1279,7 +1351,6 @@
     BX_FD_THIS s.floppy_buffer_index = 0;
     if (DEV_dma_get_tc()) { // Terminal Count line, done
       BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive;
-      BX_FD_THIS s.status_reg1 = 0;
       BX_FD_THIS s.status_reg2 = 0;
 
       if (bx_dbg.floppy) {
@@ -1322,6 +1393,14 @@
 
   drive = BX_FD_THIS s.DOR & 0x03;
 
+  if (BX_FD_THIS s.status_reg1 & FD_ST_EOT) {
+    /* increment past EOT: abnormal termination */
+    BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive;
+    DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
+    enter_result_phase();
+    return;
+  }
+
   // values after completion of data xfer
   // ??? calculation depends on base_count being multiple of 512
   BX_FD_THIS s.sector[drive] ++;
@@ -1344,6 +1423,12 @@
       BX_INFO(("increment_sector: clamping cylinder to max"));
       }
     }
+
+  /* check end-of-track condition */
+  if ((BX_FD_THIS s.multi_track == BX_FD_THIS s.head[drive]) &&
+      (BX_FD_THIS s.sector[drive] == BX_FD_THIS s.media[drive].sectors_per_track)) {
+    BX_FD_THIS s.status_reg1 |= FD_ST_EOT;
+  }
 }
 
   unsigned
@@ -1702,14 +1787,23 @@
     BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
     BX_FD_THIS s.result[1] = BX_FD_THIS s.cylinder[drive];
     break;
-  case 0x4a: // read ID
-  case 0x4d: // format track
   case 0x46: // read normal data
   case 0x66:
   case 0xc6:
   case 0xe6:
   case 0x45: // write normal data
   case 0xc5:
+    /* increment sector once more if we terminated normally at EOT */
+    if ((BX_FD_THIS s.status_reg0 & 0xc0) == 0x00 &&
+	 (BX_FD_THIS s.status_reg1 & FD_ST_EOT)) {
+      BX_FD_THIS s.status_reg1 &= ~FD_ST_EOT;  // clear EOT flag
+      increment_sector();
+      // reset the head bit
+      BX_FD_THIS s.status_reg0 &= 0xfb;
+      BX_FD_THIS s.status_reg0 |= (BX_FD_THIS s.head[drive] << 2);
+    }
+  case 0x4a: // read ID
+  case 0x4d: // format track
     BX_FD_THIS s.result_size = 7;
     BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;    
     BX_FD_THIS s.result[1] = BX_FD_THIS s.status_reg1;
@@ -1718,6 +1812,8 @@
     BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
     BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
     BX_FD_THIS s.result[6] = 2; /* sector size code */
+
+    bx_pc_system.deactivate_timer( BX_FD_THIS s.floppy_timer_index ); // clear pending timeout
     BX_FD_THIS raise_interrupt();
     break;
   }
@@ -1729,6 +1825,11 @@
   BX_FD_THIS s.main_status_reg &= 0x0f;      // leave drive status untouched
   BX_FD_THIS s.main_status_reg |= FD_MS_MRQ; // data register ready
 
+  /* do not touch ST0 and ST3 since these may be queried later via
+     commands 0x08 and 0x04, respectively. */
+  BX_FD_THIS s.status_reg1 = 0;
+  BX_FD_THIS s.status_reg2 = 0;
+
   BX_FD_THIS s.command_complete = 1; /* waiting for new command */
   BX_FD_THIS s.command_index = 0;
   BX_FD_THIS s.command_size = 0;