ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/sony.cpp
Revision: 1.11
Committed: 2001-07-01T14:38:02Z (22 years, 10 months ago) by cebix
Branch: MAIN
Changes since 1.10: +39 -51 lines
Log Message:
- sony.cpp/disk.cpp/cdrom.cpp use vector<> of drive_info objects instead of
  linked list
- color depth switching updates slot ROM
- video_x.cpp always supports 1-bit window modes
- timer_create()/clock_gettime() are pulled from librt if present

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