ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/sony.cpp
Revision: 1.1
Committed: 1999-10-03T14:16:25Z (25 years, 1 month ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * sony.cpp - Replacement .Sony driver (floppy drives)
3     *
4     * Basilisk II (C) 1997-1999 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     #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     // Flag: accRun called for the first time, run PatchAfterStartup()
127     static bool periodic_first_time = false;
128    
129    
130     /*
131     * Get pointer to drive info, NULL = invalid drive number
132     */
133    
134     static DriveInfo *get_drive_info(int num)
135     {
136     DriveInfo *info = first_drive_info;
137     while (info != NULL) {
138     if (info->num == num)
139     return info;
140     info = info->next;
141     }
142     return NULL;
143     }
144    
145    
146     /*
147     * Initialization
148     */
149    
150     void SonyInit(void)
151     {
152     first_drive_info = NULL;
153    
154     // No drives specified in prefs? Then add defaults
155     if (PrefsFindString("floppy", 0) == NULL)
156     SysAddFloppyPrefs();
157    
158     // Add drives specified in preferences
159     int32 index = 0;
160     const char *str;
161     while ((str = PrefsFindString("floppy", index++)) != NULL) {
162     bool read_only = false;
163     if (str[0] == '*') {
164     read_only = true;
165     str++;
166     }
167     void *fh = Sys_open(str, read_only);
168     if (fh) {
169     DriveInfo *info = new DriveInfo;
170     info->fh = fh;
171     info->read_only = SysIsReadOnly(fh);
172     DriveInfo *p = (DriveInfo *)&first_drive_info;
173     while (p->next != NULL)
174     p = p->next;
175     p->next = info;
176     }
177     }
178     }
179    
180    
181     /*
182     * Deinitialization
183     */
184    
185     void SonyExit(void)
186     {
187     DriveInfo *info = first_drive_info, *next;
188     while (info != NULL) {
189     Sys_close(info->fh);
190     next = info->next;
191     delete info;
192     info = next;
193     }
194     }
195    
196    
197     /*
198     * Disk was inserted, flag for mounting
199     */
200    
201     bool SonyMountVolume(void *fh)
202     {
203     DriveInfo *info;
204     for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
205     if (info) {
206     if (SysIsDiskInserted(info->fh)) {
207     info->read_only = SysIsReadOnly(info->fh);
208     WriteMacInt8(info->status + dsDiskInPlace, 1); // Inserted removable disk
209     WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
210     info->to_be_mounted = true;
211     }
212     return true;
213     } else
214     return false;
215     }
216    
217    
218     /*
219     * Driver Open() routine
220     */
221    
222     int16 SonyOpen(uint32 pb, uint32 dce)
223     {
224     D(bug("SonyOpen\n"));
225    
226     // Set up DCE
227     WriteMacInt32(dce + dCtlPosition, 0);
228     WriteMacInt16(dce + dCtlQHdr + qFlags, ReadMacInt16(dce + dCtlQHdr + qFlags) & 0xff00 | 3); // Version number, must be >=3 or System 8 will replace us
229     periodic_first_time = true;
230    
231     // Install driver again with refnum -2 (HD20)
232     uint32 utab = ReadMacInt32(0x11c);
233     WriteMacInt32(utab + 4, ReadMacInt32(utab + 16));
234    
235     // Set up fake SonyVars
236     WriteMacInt32(0x134, 0xdeadbeef);
237    
238     // Clear DskErr
239     WriteMacInt16(0x142, 0);
240    
241     // Install drives
242     for (DriveInfo *info = first_drive_info; info; info = info->next) {
243    
244     info->num = FindFreeDriveNumber(1);
245     info->to_be_mounted = false;
246     info->tag_buffer = 0;
247    
248     if (info->fh) {
249    
250     // Allocate drive status record
251     M68kRegisters r;
252     r.d[0] = SIZEOF_DrvSts;
253     Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
254     if (r.a[0] == 0)
255     continue;
256     info->status = r.a[0];
257     D(bug(" DrvSts at %08lx\n", info->status));
258    
259     // Set up drive status
260     WriteMacInt16(info->status + dsQType, sony);
261     WriteMacInt8(info->status + dsInstalled, 1);
262     WriteMacInt8(info->status + dsSides, 0xff);
263     WriteMacInt8(info->status + dsTwoSideFmt, 0xff);
264     WriteMacInt8(info->status + dsNewIntf, 0xff);
265     WriteMacInt8(info->status + dsMFMDrive, 0xff);
266     WriteMacInt8(info->status + dsMFMDisk, 0xff);
267     WriteMacInt8(info->status + dsTwoMegFmt, 0xff);
268    
269     // Disk in drive?
270     if (SysIsDiskInserted(info->fh)) {
271     WriteMacInt8(info->status + dsDiskInPlace, 1); // Inserted removable disk
272     WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
273     info->to_be_mounted = true;
274     }
275    
276     // Add drive to drive queue
277     D(bug(" adding drive %d\n", info->num));
278     r.d[0] = (info->num << 16) | (SonyRefNum & 0xffff);
279     r.a[0] = info->status + dsQLink;
280     Execute68kTrap(0xa04e, &r); // AddDrive()
281     }
282     }
283     return noErr;
284     }
285    
286    
287     /*
288     * Driver Prime() routine
289     */
290    
291     int16 SonyPrime(uint32 pb, uint32 dce)
292     {
293     WriteMacInt32(pb + ioActCount, 0);
294    
295     // Drive valid and disk inserted?
296     DriveInfo *info;
297     if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
298     return nsDrvErr;
299     if (!ReadMacInt8(info->status + dsDiskInPlace))
300     return offLinErr;
301     WriteMacInt8(info->status + dsDiskInPlace, 2); // Disk accessed
302    
303     // Get parameters
304     void *buffer = Mac2HostAddr(ReadMacInt32(pb + ioBuffer));
305     size_t length = ReadMacInt32(pb + ioReqCount);
306     loff_t position = ReadMacInt32(dce + dCtlPosition);
307     if ((length & 0x1ff) || (position & 0x1ff))
308     return paramErr;
309    
310     size_t actual = 0;
311     if ((ReadMacInt16(pb + ioTrap) & 0xff) == aRdCmd) {
312    
313     // Read
314     actual = Sys_read(info->fh, buffer, position, length);
315     if (actual != length)
316     return readErr;
317    
318     // Clear TagBuf
319     WriteMacInt32(0x2fc, 0);
320     WriteMacInt32(0x300, 0);
321     WriteMacInt32(0x304, 0);
322    
323     } else {
324    
325     // Write
326     if (info->read_only)
327     return wPrErr;
328     actual = Sys_write(info->fh, buffer, position, length);
329     if (actual != length)
330     return writErr;
331     }
332    
333     // Update ParamBlock and DCE
334     WriteMacInt32(pb + ioActCount, actual);
335     WriteMacInt32(dce + dCtlPosition, ReadMacInt32(dce + dCtlPosition) + actual);
336     return noErr;
337     }
338    
339    
340     /*
341     * Driver Control() routine
342     */
343    
344     int16 SonyControl(uint32 pb, uint32 dce)
345     {
346     uint16 code = ReadMacInt16(pb + csCode);
347     D(bug("SonyControl %d\n", code));
348    
349     // General codes
350     switch (code) {
351     case 1: // KillIO
352     return -1;
353    
354     case 9: // Track cache
355     return noErr;
356    
357     case 65: { // Periodic action ("insert" disks on startup and check for disk changes)
358     DriveInfo *info = first_drive_info;
359     while (info != NULL) {
360    
361     // Disk in drive?
362     if (!ReadMacInt8(info->status + dsDiskInPlace)) {
363    
364     #if DISK_INSERT_CHECK
365     // No, check if disk was inserted
366     if (SysIsDiskInserted(info->fh))
367     SonyMountVolume(info->fh);
368     #endif
369     }
370    
371     // Mount disk if flagged
372     if (info->to_be_mounted) {
373     D(bug(" mounting drive %d\n", info->num));
374     M68kRegisters r;
375     r.d[0] = info->num;
376     r.a[0] = 7; // diskEvent
377     Execute68kTrap(0xa02f, &r); // PostEvent()
378     info->to_be_mounted = false;
379     }
380    
381     info = info->next;
382     }
383     if (periodic_first_time) {
384     periodic_first_time = false;
385     PatchAfterStartup(); // Install patches after system startup
386     }
387     return noErr;
388     }
389     }
390    
391     // Drive valid?
392     DriveInfo *info;
393     if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
394     return nsDrvErr;
395    
396     // Drive-specific codes
397     switch (code) {
398     case 5: // Verify disk
399     if (ReadMacInt8(info->status + dsDiskInPlace) > 0)
400     return noErr;
401     else
402     return verErr;
403    
404     case 6: // Format disk
405     if (info->read_only)
406     return wPrErr;
407     else if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
408     if (SysFormat(info->fh))
409     return noErr;
410     else
411     return writErr;
412     } else
413     return offLinErr;
414    
415     case 7: // Eject
416     if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
417     SysEject(info->fh);
418     WriteMacInt8(info->status + dsDiskInPlace, 0);
419     }
420     return noErr;
421    
422     case 8: // Set tag buffer
423     info->tag_buffer = ReadMacInt32(pb + csParam);
424     return noErr;
425    
426     case 21: // Get drive icon
427     WriteMacInt32(pb + csParam, SonyDriveIconAddr);
428     return noErr;
429    
430     case 22: // Get disk icon
431     WriteMacInt32(pb + csParam, SonyDiskIconAddr);
432     return noErr;
433    
434     case 23: // Get drive info
435     if (info->num == 1)
436     WriteMacInt32(pb + csParam, 0x0004); // Internal drive
437     else
438     WriteMacInt32(pb + csParam, 0x0104); // External drive
439     return noErr;
440    
441     case 'SC': { // Format and write to disk
442     if (!ReadMacInt8(info->status + dsDiskInPlace))
443     return offLinErr;
444     if (info->read_only)
445     return wPrErr;
446    
447     void *data = Mac2HostAddr(ReadMacInt32(pb + csParam + 2));
448     size_t actual = Sys_write(info->fh, data, 0, 2880*512);
449     if (actual != 2880*512)
450     return writErr;
451     else
452     return noErr;
453     }
454    
455     default:
456     printf("WARNING: Unknown SonyControl(%d)\n", code);
457     return controlErr;
458     }
459     }
460    
461    
462     /*
463     * Driver Status() routine
464     */
465    
466     int16 SonyStatus(uint32 pb, uint32 dce)
467     {
468     uint16 code = ReadMacInt16(pb + csCode);
469     D(bug("SonyStatus %d\n", code));
470    
471     // Drive valid?
472     DriveInfo *info;
473     if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
474     return nsDrvErr;
475    
476     switch (code) {
477     case 6: // Return format list
478     if (ReadMacInt16(pb + csParam) > 0) {
479     uint32 adr = ReadMacInt32(pb + csParam + 2);
480     WriteMacInt16(pb + csParam, 1); // 1 format
481     WriteMacInt32(adr, 2880); // 2880 sectors
482     WriteMacInt32(adr + 4, 0xd2120050); // 2 heads, 18 secs/track, 80 tracks
483     return noErr;
484     } else
485     return paramErr;
486    
487     case 8: // Get drive status
488     memcpy(Mac2HostAddr(pb + csParam), Mac2HostAddr(info->status), 22);
489     return noErr;
490    
491     case 10: // Get disk type
492     WriteMacInt32(pb + csParam, ReadMacInt32(info->status + dsMFMDrive) & 0xffffff00 | 0xfe);
493     return noErr;
494    
495     case 'DV': // Duplicator version supported
496     WriteMacInt16(pb + csParam, 0x0410);
497     return noErr;
498    
499     case 'SC': // Get address header format byte
500     WriteMacInt8(pb + csParam, 0x22); // 512 bytes/sector
501     return noErr;
502    
503     default:
504     printf("WARNING: Unknown SonyStatus(%d)\n", code);
505     return statusErr;
506     }
507     }