ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/sony.cpp
Revision: 1.10
Committed: 2001-02-10T20:03:55Z (23 years, 3 months ago) by cebix
Branch: MAIN
CVS Tags: snapshot-17022001, snapshot-29052001, release-0_9-1
Changes since 1.9: +63 -47 lines
Log Message:
floppy driver updates DskErr

File Contents

# Content
1 /*
2 * sony.cpp - Replacement .Sony driver (floppy drives)
3 *
4 * Basilisk II (C) 1997-2001 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 * Set error code in DskErr
257 */
258
259 static int16 set_dsk_err(int16 err)
260 {
261 WriteMacInt16(0x142, err);
262 return err;
263 }
264
265
266 /*
267 * Driver Open() routine
268 */
269
270 int16 SonyOpen(uint32 pb, uint32 dce)
271 {
272 D(bug("SonyOpen\n"));
273
274 // Set up DCE
275 WriteMacInt32(dce + dCtlPosition, 0);
276 WriteMacInt16(dce + dCtlQHdr + qFlags, ReadMacInt16(dce + dCtlQHdr + qFlags) & 0xff00 | 3); // Version number, must be >=3 or System 8 will replace us
277 acc_run_called = false;
278
279 // Install driver again with refnum -2 (HD20)
280 uint32 utab = ReadMacInt32(0x11c);
281 WriteMacInt32(utab + 4, ReadMacInt32(utab + 16));
282
283 // Set up fake SonyVars
284 WriteMacInt32(0x134, 0xdeadbeef);
285
286 // Clear DskErr
287 set_dsk_err(0);
288
289 // Install drives
290 for (DriveInfo *info = first_drive_info; info; info = info->next) {
291
292 info->num = FindFreeDriveNumber(1);
293 info->to_be_mounted = false;
294 info->tag_buffer = 0;
295
296 if (info->fh) {
297
298 // Allocate drive status record
299 M68kRegisters r;
300 r.d[0] = SIZEOF_DrvSts;
301 Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
302 if (r.a[0] == 0)
303 continue;
304 info->status = r.a[0];
305 D(bug(" DrvSts at %08lx\n", info->status));
306
307 // Set up drive status
308 WriteMacInt16(info->status + dsQType, sony);
309 WriteMacInt8(info->status + dsInstalled, 1);
310 WriteMacInt8(info->status + dsSides, 0xff);
311 WriteMacInt8(info->status + dsTwoSideFmt, 0xff);
312 WriteMacInt8(info->status + dsNewIntf, 0xff);
313 WriteMacInt8(info->status + dsMFMDrive, 0xff);
314 WriteMacInt8(info->status + dsMFMDisk, 0xff);
315 WriteMacInt8(info->status + dsTwoMegFmt, 0xff);
316
317 // Disk in drive?
318 if (SysIsDiskInserted(info->fh)) {
319 WriteMacInt8(info->status + dsDiskInPlace, 1); // Inserted removable disk
320 WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
321 info->to_be_mounted = true;
322 }
323
324 // Add drive to drive queue
325 D(bug(" adding drive %d\n", info->num));
326 r.d[0] = (info->num << 16) | (SonyRefNum & 0xffff);
327 r.a[0] = info->status + dsQLink;
328 Execute68kTrap(0xa04e, &r); // AddDrive()
329 }
330 }
331 return noErr;
332 }
333
334
335 /*
336 * Driver Prime() routine
337 */
338
339 int16 SonyPrime(uint32 pb, uint32 dce)
340 {
341 WriteMacInt32(pb + ioActCount, 0);
342
343 // Drive valid and disk inserted?
344 DriveInfo *info;
345 if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
346 return set_dsk_err(nsDrvErr);
347 if (!ReadMacInt8(info->status + dsDiskInPlace))
348 return set_dsk_err(offLinErr);
349 WriteMacInt8(info->status + dsDiskInPlace, 2); // Disk accessed
350
351 // Get parameters
352 void *buffer = Mac2HostAddr(ReadMacInt32(pb + ioBuffer));
353 size_t length = ReadMacInt32(pb + ioReqCount);
354 loff_t position = ReadMacInt32(dce + dCtlPosition);
355 if ((length & 0x1ff) || (position & 0x1ff))
356 return set_dsk_err(paramErr);
357
358 size_t actual = 0;
359 if ((ReadMacInt16(pb + ioTrap) & 0xff) == aRdCmd) {
360
361 // Read
362 actual = Sys_read(info->fh, buffer, position, length);
363 if (actual != length)
364 return set_dsk_err(readErr);
365
366 // Clear TagBuf
367 WriteMacInt32(0x2fc, 0);
368 WriteMacInt32(0x300, 0);
369 WriteMacInt32(0x304, 0);
370
371 } else {
372
373 // Write
374 if (info->read_only)
375 return set_dsk_err(wPrErr);
376 actual = Sys_write(info->fh, buffer, position, length);
377 if (actual != length)
378 return set_dsk_err(writErr);
379 }
380
381 // Update ParamBlock and DCE
382 WriteMacInt32(pb + ioActCount, actual);
383 WriteMacInt32(dce + dCtlPosition, ReadMacInt32(dce + dCtlPosition) + actual);
384 return set_dsk_err(noErr);
385 }
386
387
388 /*
389 * Driver Control() routine
390 */
391
392 int16 SonyControl(uint32 pb, uint32 dce)
393 {
394 uint16 code = ReadMacInt16(pb + csCode);
395 D(bug("SonyControl %d\n", code));
396
397 // General codes
398 switch (code) {
399 case 1: // KillIO
400 return set_dsk_err(-1);
401
402 case 9: // Track cache
403 return set_dsk_err(noErr);
404
405 case 65: // Periodic action (accRun, "insert" disks on startup)
406 mount_mountable_volumes();
407 PatchAfterStartup(); // Install patches after system startup
408 WriteMacInt16(dce + dCtlFlags, ReadMacInt16(dce + dCtlFlags) & ~0x2000); // Disable periodic action
409 acc_run_called = true;
410 return noErr;
411 }
412
413 // Drive valid?
414 DriveInfo *info;
415 if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
416 return set_dsk_err(nsDrvErr);
417
418 // Drive-specific codes
419 int16 err = noErr;
420 switch (code) {
421 case 5: // Verify disk
422 if (ReadMacInt8(info->status + dsDiskInPlace) <= 0)
423 err = verErr;
424 break;
425
426 case 6: // Format disk
427 if (info->read_only)
428 err = wPrErr;
429 else if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
430 if (!SysFormat(info->fh))
431 err = writErr;
432 } else
433 err = offLinErr;
434 break;
435
436 case 7: // Eject
437 if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
438 SysEject(info->fh);
439 WriteMacInt8(info->status + dsDiskInPlace, 0);
440 }
441 break;
442
443 case 8: // Set tag buffer
444 info->tag_buffer = ReadMacInt32(pb + csParam);
445 break;
446
447 case 21: // Get drive icon
448 WriteMacInt32(pb + csParam, SonyDriveIconAddr);
449 break;
450
451 case 22: // Get disk icon
452 WriteMacInt32(pb + csParam, SonyDiskIconAddr);
453 break;
454
455 case 23: // Get drive info
456 if (info->num == 1)
457 WriteMacInt32(pb + csParam, 0x0004); // Internal drive
458 else
459 WriteMacInt32(pb + csParam, 0x0104); // External drive
460 break;
461
462 case 0x5343: // Format and write to disk ('SC'), used by DiskCopy
463 if (!ReadMacInt8(info->status + dsDiskInPlace))
464 err = offLinErr;
465 else if (info->read_only)
466 err = wPrErr;
467 else {
468 void *data = Mac2HostAddr(ReadMacInt32(pb + csParam + 2));
469 size_t actual = Sys_write(info->fh, data, 0, 2880*512);
470 if (actual != 2880*512)
471 err = writErr;
472 }
473 break;
474
475 default:
476 printf("WARNING: Unknown SonyControl(%d)\n", code);
477 err = controlErr;
478 break;
479 }
480
481 return set_dsk_err(err);
482 }
483
484
485 /*
486 * Driver Status() routine
487 */
488
489 int16 SonyStatus(uint32 pb, uint32 dce)
490 {
491 uint16 code = ReadMacInt16(pb + csCode);
492 D(bug("SonyStatus %d\n", code));
493
494 // Drive valid?
495 DriveInfo *info;
496 if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
497 return set_dsk_err(nsDrvErr);
498
499 int16 err = noErr;
500 switch (code) {
501 case 6: // Return format list
502 if (ReadMacInt16(pb + csParam) > 0) {
503 uint32 adr = ReadMacInt32(pb + csParam + 2);
504 WriteMacInt16(pb + csParam, 1); // 1 format
505 WriteMacInt32(adr, 2880); // 2880 sectors
506 WriteMacInt32(adr + 4, 0xd2120050); // 2 heads, 18 secs/track, 80 tracks
507 } else
508 err = paramErr;
509 break;
510
511 case 8: // Get drive status
512 Mac2Mac_memcpy(pb + csParam, info->status, 22);
513 break;
514
515 case 10: // Get disk type
516 WriteMacInt32(pb + csParam, ReadMacInt32(info->status + dsMFMDrive) & 0xffffff00 | 0xfe);
517 break;
518
519 case 0x4456: // Duplicator version supported ('DV')
520 WriteMacInt16(pb + csParam, 0x0410);
521 break;
522
523 case 0x5343: // Get address header format byte ('SC')
524 WriteMacInt8(pb + csParam, 0x22); // 512 bytes/sector
525 break;
526
527 default:
528 printf("WARNING: Unknown SonyStatus(%d)\n", code);
529 err = statusErr;
530 break;
531 }
532
533 return set_dsk_err(err);
534 }
535
536
537 /*
538 * Driver interrupt routine (1Hz) - check for volumes to be mounted
539 */
540
541 void SonyInterrupt(void)
542 {
543 if (!acc_run_called)
544 return;
545
546 mount_mountable_volumes();
547 }