ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/sony.cpp
Revision: 1.6
Committed: 2000-04-10T18:52:30Z (24 years, 1 month ago) by cebix
Branch: MAIN
CVS Tags: snapshot-13072000
Changes since 1.5: +1 -1 lines
Log Message:
- updated copyright info: 1999->2000

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