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

# Content
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 }