ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/sony.cpp
Revision: 1.8
Committed: 2000-07-22T16:07:18Z (23 years, 9 months ago) by cebix
Branch: MAIN
Changes since 1.7: +3 -3 lines
Log Message:
- new FOURCC() macro in macos_util.h

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * sony.cpp - Replacement .Sony driver (floppy drives)
3     *
4 cebix 1.6 * Basilisk II (C) 1997-2000 Christian Bauer
5 cebix 1.1 *
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 cebix 1.4 #define DEBUG 0
43 cebix 1.1 #include "debug.h"
44    
45 cebix 1.7
46     // Check for inserted disks by polling?
47 cebix 1.1 #ifdef AMIGA
48 cebix 1.7 #define DISK_INSERT_CHECK 1
49 cebix 1.1 #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 cebix 1.2 // Flag: Control(accRun) has been called, interrupt routine is now active
129     static bool acc_run_called = false;
130 cebix 1.1
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 cebix 1.2 * 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 cebix 1.1 * 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 cebix 1.2 acc_run_called = false;
267 cebix 1.1
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 cebix 1.2 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 cebix 1.1 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 cebix 1.8 case 0x5343: { // Format and write to disk ('SC'), used by DiskCopy
453 cebix 1.1 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 cebix 1.5 Mac2Mac_memcpy(pb + csParam, info->status, 22);
500 cebix 1.1 return noErr;
501    
502     case 10: // Get disk type
503     WriteMacInt32(pb + csParam, ReadMacInt32(info->status + dsMFMDrive) & 0xffffff00 | 0xfe);
504     return noErr;
505    
506 cebix 1.8 case 0x4456: // Duplicator version supported ('DV')
507 cebix 1.1 WriteMacInt16(pb + csParam, 0x0410);
508     return noErr;
509    
510 cebix 1.8 case 0x5343: // Get address header format byte ('SC')
511 cebix 1.1 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 cebix 1.2 }
518     }
519    
520    
521     /*
522 cebix 1.7 * Driver interrupt routine (1Hz) - check for volumes to be mounted
523 cebix 1.2 */
524    
525     void SonyInterrupt(void)
526     {
527     if (!acc_run_called)
528     return;
529    
530 cebix 1.7 mount_mountable_volumes();
531 cebix 1.1 }