ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/sony.cpp
Revision: 1.7
Committed: 2000-07-14T21:29:10Z (23 years, 10 months ago) by cebix
Branch: MAIN
Changes since 1.6: +5 -11 lines
Log Message:
- AmigaOS bug fixes by J.Lachmann (floppy, 2060scsi.device, "Add Volume" in
  prefs editor)
- imported some changes from the Windows source (1Hz interrupt, FPU fixes)

File Contents

# Content
1 /*
2 * sony.cpp - Replacement .Sony driver (floppy drives)
3 *
4 * Basilisk II (C) 1997-2000 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 * SEE ALSO
23 * Inside Macintosh: Devices, chapter 1 "Device Manager"
24 * Technote DV 05: "Drive Queue Elements"
25 * Technote DV 07: "Forcing Floppy Disk Size to be Either 400K or 800K"
26 * Technote DV 17: "Sony Driver: What Your Sony Drives For You"
27 * Technote DV 23: "Driver Education"
28 * Technote FL 24: "Don't Look at ioPosOffset for Devices"
29 */
30
31 #include <string.h>
32
33 #include "sysdeps.h"
34 #include "cpu_emulation.h"
35 #include "main.h"
36 #include "macos_util.h"
37 #include "rom_patches.h"
38 #include "sys.h"
39 #include "prefs.h"
40 #include "sony.h"
41
42 #define DEBUG 0
43 #include "debug.h"
44
45
46 // Check for inserted disks by polling?
47 #ifdef AMIGA
48 #define DISK_INSERT_CHECK 1
49 #else
50 #define DISK_INSERT_CHECK 0
51 #endif
52
53
54 // Floppy disk icon
55 const uint8 SonyDiskIcon[258] = {
56 0x7f, 0xff, 0xff, 0xf8, 0x81, 0x00, 0x01, 0x04, 0x81, 0x00, 0x71, 0x02, 0x81, 0x00, 0x89, 0x01,
57 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01,
58 0x81, 0x00, 0x71, 0x01, 0x81, 0x00, 0x01, 0x01, 0x80, 0xff, 0xfe, 0x01, 0x80, 0x00, 0x00, 0x01,
59 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01,
60 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x87, 0xff, 0xff, 0xe1, 0x88, 0x00, 0x00, 0x11,
61 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
62 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
63 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x7f, 0xff, 0xff, 0xfe,
64
65 0x7f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
68 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
70 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
71 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfe,
73
74 0, 0
75 };
76
77 // Floppy drive icon
78 const uint8 SonyDriveIcon[258] = {
79 0x7f, 0xff, 0xff, 0xf8, 0x81, 0x00, 0x01, 0x04, 0x81, 0x00, 0x71, 0x02, 0x81, 0x00, 0x89, 0x01,
80 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01,
81 0x81, 0x00, 0x71, 0x01, 0x81, 0x00, 0x01, 0x01, 0x80, 0xff, 0xfe, 0x01, 0x80, 0x00, 0x00, 0x01,
82 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01,
83 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x87, 0xff, 0xff, 0xe1, 0x88, 0x00, 0x00, 0x11,
84 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
85 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
86 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x7f, 0xff, 0xff, 0xfe,
87
88 0x7f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
89 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
90 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
91 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
92 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
95 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfe,
96
97 0, 0
98 };
99
100
101 // Struct for each drive
102 struct DriveInfo {
103 DriveInfo()
104 {
105 next = NULL;
106 num = 0;
107 fh = NULL;
108 read_only = false;
109 status = 0;
110 }
111
112 DriveInfo *next; // Pointer to next DriveInfo (must be first in struct!)
113 int num; // Drive number
114 void *fh; // Floppy driver file handle
115 bool to_be_mounted; // Flag: drive must be mounted in accRun
116 bool read_only; // Flag: force write protection
117 uint32 tag_buffer; // Mac address of tag buffer
118 uint32 status; // Mac address of drive status record
119 };
120
121 // Linked list of DriveInfos
122 static DriveInfo *first_drive_info;
123
124 // Icon addresses (Mac address space, set by PatchROM())
125 uint32 SonyDiskIconAddr;
126 uint32 SonyDriveIconAddr;
127
128 // Flag: Control(accRun) has been called, interrupt routine is now active
129 static bool acc_run_called = false;
130
131
132 /*
133 * Get pointer to drive info, NULL = invalid drive number
134 */
135
136 static DriveInfo *get_drive_info(int num)
137 {
138 DriveInfo *info = first_drive_info;
139 while (info != NULL) {
140 if (info->num == num)
141 return info;
142 info = info->next;
143 }
144 return NULL;
145 }
146
147
148 /*
149 * Initialization
150 */
151
152 void SonyInit(void)
153 {
154 first_drive_info = NULL;
155
156 // No drives specified in prefs? Then add defaults
157 if (PrefsFindString("floppy", 0) == NULL)
158 SysAddFloppyPrefs();
159
160 // Add drives specified in preferences
161 int32 index = 0;
162 const char *str;
163 while ((str = PrefsFindString("floppy", index++)) != NULL) {
164 bool read_only = false;
165 if (str[0] == '*') {
166 read_only = true;
167 str++;
168 }
169 void *fh = Sys_open(str, read_only);
170 if (fh) {
171 DriveInfo *info = new DriveInfo;
172 info->fh = fh;
173 info->read_only = SysIsReadOnly(fh);
174 DriveInfo *p = (DriveInfo *)&first_drive_info;
175 while (p->next != NULL)
176 p = p->next;
177 p->next = info;
178 }
179 }
180 }
181
182
183 /*
184 * Deinitialization
185 */
186
187 void SonyExit(void)
188 {
189 DriveInfo *info = first_drive_info, *next;
190 while (info != NULL) {
191 Sys_close(info->fh);
192 next = info->next;
193 delete info;
194 info = next;
195 }
196 }
197
198
199 /*
200 * Disk was inserted, flag for mounting
201 */
202
203 bool SonyMountVolume(void *fh)
204 {
205 DriveInfo *info;
206 for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
207 if (info) {
208 if (SysIsDiskInserted(info->fh)) {
209 info->read_only = SysIsReadOnly(info->fh);
210 WriteMacInt8(info->status + dsDiskInPlace, 1); // Inserted removable disk
211 WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
212 info->to_be_mounted = true;
213 }
214 return true;
215 } else
216 return false;
217 }
218
219
220 /*
221 * Mount volumes for which the to_be_mounted flag is set
222 * (called during interrupt time)
223 */
224
225 static void mount_mountable_volumes(void)
226 {
227 DriveInfo *info = first_drive_info;
228 while (info != NULL) {
229
230 #if DISK_INSERT_CHECK
231 // Disk in drive?
232 if (!ReadMacInt8(info->status + dsDiskInPlace)) {
233
234 // No, check if disk was inserted
235 if (SysIsDiskInserted(info->fh))
236 SonyMountVolume(info->fh);
237 }
238 #endif
239
240 // Mount disk if flagged
241 if (info->to_be_mounted) {
242 D(bug(" mounting drive %d\n", info->num));
243 M68kRegisters r;
244 r.d[0] = info->num;
245 r.a[0] = 7; // diskEvent
246 Execute68kTrap(0xa02f, &r); // PostEvent()
247 info->to_be_mounted = false;
248 }
249
250 info = info->next;
251 }
252 }
253
254
255 /*
256 * Driver Open() routine
257 */
258
259 int16 SonyOpen(uint32 pb, uint32 dce)
260 {
261 D(bug("SonyOpen\n"));
262
263 // Set up DCE
264 WriteMacInt32(dce + dCtlPosition, 0);
265 WriteMacInt16(dce + dCtlQHdr + qFlags, ReadMacInt16(dce + dCtlQHdr + qFlags) & 0xff00 | 3); // Version number, must be >=3 or System 8 will replace us
266 acc_run_called = false;
267
268 // Install driver again with refnum -2 (HD20)
269 uint32 utab = ReadMacInt32(0x11c);
270 WriteMacInt32(utab + 4, ReadMacInt32(utab + 16));
271
272 // Set up fake SonyVars
273 WriteMacInt32(0x134, 0xdeadbeef);
274
275 // Clear DskErr
276 WriteMacInt16(0x142, 0);
277
278 // Install drives
279 for (DriveInfo *info = first_drive_info; info; info = info->next) {
280
281 info->num = FindFreeDriveNumber(1);
282 info->to_be_mounted = false;
283 info->tag_buffer = 0;
284
285 if (info->fh) {
286
287 // Allocate drive status record
288 M68kRegisters r;
289 r.d[0] = SIZEOF_DrvSts;
290 Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
291 if (r.a[0] == 0)
292 continue;
293 info->status = r.a[0];
294 D(bug(" DrvSts at %08lx\n", info->status));
295
296 // Set up drive status
297 WriteMacInt16(info->status + dsQType, sony);
298 WriteMacInt8(info->status + dsInstalled, 1);
299 WriteMacInt8(info->status + dsSides, 0xff);
300 WriteMacInt8(info->status + dsTwoSideFmt, 0xff);
301 WriteMacInt8(info->status + dsNewIntf, 0xff);
302 WriteMacInt8(info->status + dsMFMDrive, 0xff);
303 WriteMacInt8(info->status + dsMFMDisk, 0xff);
304 WriteMacInt8(info->status + dsTwoMegFmt, 0xff);
305
306 // Disk in drive?
307 if (SysIsDiskInserted(info->fh)) {
308 WriteMacInt8(info->status + dsDiskInPlace, 1); // Inserted removable disk
309 WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
310 info->to_be_mounted = true;
311 }
312
313 // Add drive to drive queue
314 D(bug(" adding drive %d\n", info->num));
315 r.d[0] = (info->num << 16) | (SonyRefNum & 0xffff);
316 r.a[0] = info->status + dsQLink;
317 Execute68kTrap(0xa04e, &r); // AddDrive()
318 }
319 }
320 return noErr;
321 }
322
323
324 /*
325 * Driver Prime() routine
326 */
327
328 int16 SonyPrime(uint32 pb, uint32 dce)
329 {
330 WriteMacInt32(pb + ioActCount, 0);
331
332 // Drive valid and disk inserted?
333 DriveInfo *info;
334 if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
335 return nsDrvErr;
336 if (!ReadMacInt8(info->status + dsDiskInPlace))
337 return offLinErr;
338 WriteMacInt8(info->status + dsDiskInPlace, 2); // Disk accessed
339
340 // Get parameters
341 void *buffer = Mac2HostAddr(ReadMacInt32(pb + ioBuffer));
342 size_t length = ReadMacInt32(pb + ioReqCount);
343 loff_t position = ReadMacInt32(dce + dCtlPosition);
344 if ((length & 0x1ff) || (position & 0x1ff))
345 return paramErr;
346
347 size_t actual = 0;
348 if ((ReadMacInt16(pb + ioTrap) & 0xff) == aRdCmd) {
349
350 // Read
351 actual = Sys_read(info->fh, buffer, position, length);
352 if (actual != length)
353 return readErr;
354
355 // Clear TagBuf
356 WriteMacInt32(0x2fc, 0);
357 WriteMacInt32(0x300, 0);
358 WriteMacInt32(0x304, 0);
359
360 } else {
361
362 // Write
363 if (info->read_only)
364 return wPrErr;
365 actual = Sys_write(info->fh, buffer, position, length);
366 if (actual != length)
367 return writErr;
368 }
369
370 // Update ParamBlock and DCE
371 WriteMacInt32(pb + ioActCount, actual);
372 WriteMacInt32(dce + dCtlPosition, ReadMacInt32(dce + dCtlPosition) + actual);
373 return noErr;
374 }
375
376
377 /*
378 * Driver Control() routine
379 */
380
381 int16 SonyControl(uint32 pb, uint32 dce)
382 {
383 uint16 code = ReadMacInt16(pb + csCode);
384 D(bug("SonyControl %d\n", code));
385
386 // General codes
387 switch (code) {
388 case 1: // KillIO
389 return -1;
390
391 case 9: // Track cache
392 return noErr;
393
394 case 65: // Periodic action (accRun, "insert" disks on startup)
395 mount_mountable_volumes();
396 PatchAfterStartup(); // Install patches after system startup
397 WriteMacInt16(dce + dCtlFlags, ReadMacInt16(dce + dCtlFlags) & ~0x2000); // Disable periodic action
398 acc_run_called = true;
399 return noErr;
400 }
401
402 // Drive valid?
403 DriveInfo *info;
404 if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
405 return nsDrvErr;
406
407 // Drive-specific codes
408 switch (code) {
409 case 5: // Verify disk
410 if (ReadMacInt8(info->status + dsDiskInPlace) > 0)
411 return noErr;
412 else
413 return verErr;
414
415 case 6: // Format disk
416 if (info->read_only)
417 return wPrErr;
418 else if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
419 if (SysFormat(info->fh))
420 return noErr;
421 else
422 return writErr;
423 } else
424 return offLinErr;
425
426 case 7: // Eject
427 if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
428 SysEject(info->fh);
429 WriteMacInt8(info->status + dsDiskInPlace, 0);
430 }
431 return noErr;
432
433 case 8: // Set tag buffer
434 info->tag_buffer = ReadMacInt32(pb + csParam);
435 return noErr;
436
437 case 21: // Get drive icon
438 WriteMacInt32(pb + csParam, SonyDriveIconAddr);
439 return noErr;
440
441 case 22: // Get disk icon
442 WriteMacInt32(pb + csParam, SonyDiskIconAddr);
443 return noErr;
444
445 case 23: // Get drive info
446 if (info->num == 1)
447 WriteMacInt32(pb + csParam, 0x0004); // Internal drive
448 else
449 WriteMacInt32(pb + csParam, 0x0104); // External drive
450 return noErr;
451
452 case 'SC': { // Format and write to disk
453 if (!ReadMacInt8(info->status + dsDiskInPlace))
454 return offLinErr;
455 if (info->read_only)
456 return wPrErr;
457
458 void *data = Mac2HostAddr(ReadMacInt32(pb + csParam + 2));
459 size_t actual = Sys_write(info->fh, data, 0, 2880*512);
460 if (actual != 2880*512)
461 return writErr;
462 else
463 return noErr;
464 }
465
466 default:
467 printf("WARNING: Unknown SonyControl(%d)\n", code);
468 return controlErr;
469 }
470 }
471
472
473 /*
474 * Driver Status() routine
475 */
476
477 int16 SonyStatus(uint32 pb, uint32 dce)
478 {
479 uint16 code = ReadMacInt16(pb + csCode);
480 D(bug("SonyStatus %d\n", code));
481
482 // Drive valid?
483 DriveInfo *info;
484 if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
485 return nsDrvErr;
486
487 switch (code) {
488 case 6: // Return format list
489 if (ReadMacInt16(pb + csParam) > 0) {
490 uint32 adr = ReadMacInt32(pb + csParam + 2);
491 WriteMacInt16(pb + csParam, 1); // 1 format
492 WriteMacInt32(adr, 2880); // 2880 sectors
493 WriteMacInt32(adr + 4, 0xd2120050); // 2 heads, 18 secs/track, 80 tracks
494 return noErr;
495 } else
496 return paramErr;
497
498 case 8: // Get drive status
499 Mac2Mac_memcpy(pb + csParam, info->status, 22);
500 return noErr;
501
502 case 10: // Get disk type
503 WriteMacInt32(pb + csParam, ReadMacInt32(info->status + dsMFMDrive) & 0xffffff00 | 0xfe);
504 return noErr;
505
506 case 'DV': // Duplicator version supported
507 WriteMacInt16(pb + csParam, 0x0410);
508 return noErr;
509
510 case 'SC': // Get address header format byte
511 WriteMacInt8(pb + csParam, 0x22); // 512 bytes/sector
512 return noErr;
513
514 default:
515 printf("WARNING: Unknown SonyStatus(%d)\n", code);
516 return statusErr;
517 }
518 }
519
520
521 /*
522 * Driver interrupt routine (1Hz) - check for volumes to be mounted
523 */
524
525 void SonyInterrupt(void)
526 {
527 if (!acc_run_called)
528 return;
529
530 mount_mountable_volumes();
531 }