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, 6 months 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

# 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 #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 // 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
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 * 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 * 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 acc_run_called = false;
268
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 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 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 Mac2Mac_memcpy(pb + csParam, info->status, 22);
501 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 }
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 }
537 }