fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/arch/macplus/sony.c *
7 * Created: 2007-11-15 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2007-2023 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include "main.h"
24#include "sony.h"
25
26#include <string.h>
27
28#include <devices/memory.h>
29
30#include <drivers/block/block.h>
31#include <drivers/block/blkpsi.h>
32#include <drivers/psi/psi.h>
33
34#include <lib/log.h>
35
36
37#define MAC_HOOK_SONY 16
38#define MAC_HOOK_SONY_OPEN (MAC_HOOK_SONY + 0)
39#define MAC_HOOK_SONY_PRIME (MAC_HOOK_SONY + 1)
40#define MAC_HOOK_SONY_CTRL (MAC_HOOK_SONY + 2)
41#define MAC_HOOK_SONY_STATUS (MAC_HOOK_SONY + 3)
42#define MAC_HOOK_SONY_CLOSE (MAC_HOOK_SONY + 4)
43
44/* sony variable offsets */
45#define SONY_TRACK 0 /* current track */
46#define SONY_WPROT 2 /* FF = write protected, 00 = writeable */
47#define SONY_DISKINPLACE 3 /* 0 = no disk, 1 = inserted, 2 = accessed */
48#define SONY_INSTALLED 4 /* 0 = unknown, 1 = installed, ff = not installed */
49#define SONY_SIDES 5 /* 0 single sided, ff double sided */
50#define SONY_QLINK 6
51#define SONY_QTYPE 10
52#define SONY_QDRIVENO 12
53#define SONY_QREFNUM 14 /* driver reference number (0xfffb) */
54#define SONY_QFSID 16
55#define SONY_TWOSIDEFMT 18 /* ff double-sided, 0 single-sided */
56#define SONY_NEWIF 19 /* ff new 800K interface, 0 old 400K interface */
57#define SONY_DRIVEERRS 20 /* drive soft errors */
58
59/* parameter block offsets */
60#define qLink 0
61#define qType 4
62#define ioTrap 6
63#define ioCmdAddr 8
64#define ioCompletion 12
65#define ioResult 16
66#define ioNamePtr 18
67#define ioVRefNum 22
68#define ioRefNum 24
69#define ioVersNum 26
70#define ioPermssn 27
71#define ioMisc 28
72#define ioBuffer 32
73#define ioReqCount 36
74#define ioActCount 40
75#define ioPosMode 44
76#define ioPosOffset 46
77#define csCode 26
78#define csParam 28
79
80/* device control entry offsets */
81#define dCtlDriver 0
82#define dCtlFlags 4
83#define dCtlQHdr 6
84#define dCtlPosition 16
85#define dCtlStorage 20
86#define dCtlRefNum 24
87#define dCtlCurTicks 26
88
89/* positioning modes */
90#define fsAtMark 0
91#define fsFromStart 1
92#define fsFromMark 3
93#define rdVerify 64
94
95/* trap word flags */
96#define asyncTrpBit 0x0100
97#define noQueueBit 0x0200
98
99/* result codes */
100#define noErr 0
101#define controlErr -17
102#define statusErr -18
103#define readErr -19
104#define writeErr -20
105#define abortErr -27
106#define wPrErr -44
107#define paramErr -50
108#define nsDrvErr -56
109#define noDriveErr -64
110#define offLineErr -65
111#define verErr -84
112
113
114void mac_sony_init (mac_sony_t *sony, int enable)
115{
116 unsigned i;
117
118 sony->open = 0;
119 sony->patched = 0;
120 sony->enable = (enable != 0);
121
122 sony->mem = NULL;
123 sony->dsks = NULL;
124
125 sony->check_addr = 0;
126 sony->icon_addr[0] = 0;
127 sony->icon_addr[1] = 0;
128
129 sony->tag_buf = 0;
130
131 sony->format_hd_as_dd = 0;
132 sony->format_cnt = 0;
133
134 for (i = 0; i < SONY_DRIVES; i++) {
135 sony->delay_val[i] = 0;
136 sony->delay_cnt[i] = 0;
137 }
138}
139
140void mac_sony_free (mac_sony_t *sony)
141{
142}
143
144void mac_sony_set_mem (mac_sony_t *sony, memory_t *mem)
145{
146 sony->mem = mem;
147}
148
149void mac_sony_set_disks (mac_sony_t *sony, disks_t *dsks)
150{
151 sony->dsks = dsks;
152}
153
154static
155unsigned long mac_sony_get_vars (mac_sony_t *sony, unsigned drive)
156{
157 unsigned long ret;
158
159 ret = mem_get_uint32_be (sony->mem, 0x0134);
160
161 if ((drive >= 1) && (drive <= SONY_DRIVES)) {
162 ret += 8 + 66 * drive;
163 }
164
165 return (ret);
166}
167
168static
169unsigned long mac_sony_find_pcex (mac_sony_t *sony, unsigned long addr)
170{
171 unsigned long cnt;
172
173 if (mem_get_uint32_be (sony->mem, addr) != 0x50434558) {
174 return (0);
175 }
176
177 cnt = mem_get_uint32_be (sony->mem, addr + 8);
178
179 if (cnt < 4) {
180 return (0);
181 }
182
183 sony->check_addr = addr + mem_get_uint32_be (sony->mem, addr + 16);
184 sony->icon_addr[0] = addr + mem_get_uint32_be (sony->mem, addr + 20);
185 sony->icon_addr[1] = addr + mem_get_uint32_be (sony->mem, addr + 24);
186
187 addr += mem_get_uint32_be (sony->mem, addr + 12);
188
189 return (addr);
190}
191
192static
193unsigned long mac_sony_find (mac_sony_t *sony, unsigned long addr, unsigned long size)
194{
195 unsigned long sony_addr;
196
197 while (size > 0) {
198 addr += 1;
199 size -= 1;
200
201 if (mem_get_uint16_be (sony->mem, addr - 1) != 0x052e) {
202 continue;
203 }
204
205 if (mem_get_uint32_be (sony->mem, addr + 1) != 0x536f6e79) {
206 continue;
207 }
208
209 sony_addr = addr - 19;
210
211 if (mem_get_uint16_be (sony->mem, sony_addr) != 0x4f00) {
212 continue;
213 }
214
215 return (sony_addr);
216 }
217
218 return (0);
219}
220
221static
222void mac_sony_unpatch_rom (mac_sony_t *sony)
223{
224 unsigned i, j;
225 unsigned sofs;
226 unsigned long sadr;
227 unsigned char *buf;
228
229 if (sony->patched == 0) {
230 return;
231 }
232
233 if ((sony->sony_addr == 0) || (sony->pcex_addr == 0)) {
234 return;
235 }
236
237 buf = sony->patch_buf;
238
239 for (i = 0; i < 5; i++) {
240 sofs = mem_get_uint16_be (sony->mem, sony->sony_addr + 8 + 2 * i);
241 sadr = sony->sony_addr + sofs;
242
243 for (j = 0; j < 6; j++) {
244 mem_set_uint8_rw (sony->mem, sadr + j, *(buf++));
245 }
246 }
247
248 sony->patched = 0;
249}
250
251static
252void mac_sony_patch_rom (mac_sony_t *sony)
253{
254 unsigned i, j;
255 unsigned sofs, dofs;
256 unsigned long sadr, dadr;
257 unsigned char *buf;
258
259 if ((sony->sony_addr == 0) || (sony->pcex_addr == 0)) {
260 return;
261 }
262
263 buf = sony->patch_buf;
264
265 for (i = 0; i < 5; i++) {
266 sofs = mem_get_uint16_be (sony->mem, sony->sony_addr + 8 + 2 * i);
267 sadr = sony->sony_addr + sofs;
268
269 dofs = mem_get_uint16_be (sony->mem, sony->pcex_addr + 8 + 2 * i);
270 dadr = sony->pcex_addr + dofs;
271
272 for (j = 0; j < 6; j++) {
273 *(buf++) = mem_get_uint8 (sony->mem, sadr + j);
274 }
275
276 mem_set_uint8_rw (sony->mem, sadr + 0, 0x4e);
277 mem_set_uint8_rw (sony->mem, sadr + 1, 0xf9);
278 mem_set_uint8_rw (sony->mem, sadr + 2, (dadr >> 24) & 0xff);
279 mem_set_uint8_rw (sony->mem, sadr + 3, (dadr >> 16) & 0xff);
280 mem_set_uint8_rw (sony->mem, sadr + 4, (dadr >> 8) & 0xff);
281 mem_set_uint8_rw (sony->mem, sadr + 5, dadr & 0xff);
282
283#ifdef DEBUG_SONY
284 mac_log_deb ("sony: patch %u: %06lx -> %06lx\n", i, sadr, dadr);
285#endif
286 }
287}
288
289void mac_sony_patch (mac_sony_t *sony)
290{
291 if (sony->enable == 0) {
292 return;
293 }
294
295 if (sony->patched) {
296 return;
297 }
298
299 sony->patched = 1;
300
301 sony->pcex_addr = 0;
302 sony->sony_addr = 0;
303
304 sony->pcex_addr = mac_sony_find_pcex (sony, 0xf80000);
305
306 if (sony->pcex_addr == 0) {
307 pce_log_tag (MSG_ERR, "SONY:", "PCE ROM extension not found\n");
308 return;
309 }
310
311 pce_log_tag (MSG_INF, "SONY:", "PCE ROM extension at 0x%06lx\n", sony->pcex_addr);
312
313 sony->sony_addr = mac_sony_find (sony, 0x400000, 1024UL * 1024UL);
314
315 if (sony->sony_addr == 0) {
316 pce_log_tag (MSG_ERR, "SONY:", "sony driver not found\n");
317 return;
318 }
319
320 pce_log_tag (MSG_INF, "SONY:", "sony driver at 0x%06lx\n", sony->sony_addr);
321
322 mac_sony_patch_rom (sony);
323}
324
325void mac_sony_set_delay (mac_sony_t *sony, unsigned drive, unsigned delay)
326{
327 if (drive < SONY_DRIVES) {
328 sony->delay_val[drive] = delay;
329 sony->delay_cnt[drive] = delay;
330 }
331}
332
333void mac_sony_insert (mac_sony_t *sony, unsigned drive)
334{
335 unsigned long vars;
336 disk_t *dsk;
337
338 if (sony->open == 0) {
339 return;
340 }
341
342 if ((drive < 1) || (drive > SONY_DRIVES)) {
343 return;
344 }
345
346 dsk = dsks_get_disk (sony->dsks, drive);
347
348 if (dsk == NULL) {
349 return;
350 }
351
352 vars = mac_sony_get_vars (sony, drive);
353
354 if (mem_get_uint8 (sony->mem, vars + SONY_DISKINPLACE) == 0x00) {
355 pce_log_tag (MSG_INF, "SONY:", "insert drive %u\n", drive);
356
357 mem_set_uint8 (sony->mem, vars + SONY_DISKINPLACE, 0x01);
358
359 if (dsk_get_block_cnt (dsk) < 1600) {
360 mem_set_uint8 (sony->mem, vars + SONY_TWOSIDEFMT, 0x00);
361 mem_set_uint8 (sony->mem, vars + SONY_SIDES, 0x00);
362 mem_set_uint8 (sony->mem, vars + SONY_NEWIF, 0x00);
363 }
364 else {
365 mem_set_uint8 (sony->mem, vars + SONY_TWOSIDEFMT, 0xff);
366 mem_set_uint8 (sony->mem, vars + SONY_SIDES, 0xff);
367 mem_set_uint8 (sony->mem, vars + SONY_NEWIF, 0xff);
368 }
369
370 if (dsk_get_readonly (dsk)) {
371 mem_set_uint8 (sony->mem, vars + SONY_WPROT, 0xff);
372 }
373 else {
374 mem_set_uint8 (sony->mem, vars + SONY_WPROT, 0x00);
375 }
376 }
377}
378
379/*
380 * Check if disks need to be inserted.
381 */
382int mac_sony_check (mac_sony_t *sony)
383{
384 int check;
385 unsigned i;
386 unsigned long vars;
387 disk_t *dsk;
388
389 if (sony->open == 0) {
390 return (0);
391 }
392
393 check = 0;
394
395 for (i = 0; i < SONY_DRIVES; i++) {
396 if (sony->delay_cnt[i] > 0) {
397 sony->delay_cnt[i] -= 1;
398
399 if (sony->delay_cnt[i] == 0) {
400 mac_sony_insert (sony, i + 1);
401 }
402 }
403
404 dsk = dsks_get_disk (sony->dsks, i + 1);
405
406 if (dsk != NULL) {
407 vars = mac_sony_get_vars (sony, i + 1);
408
409 if (mem_get_uint8 (sony->mem, vars + SONY_DISKINPLACE) == 0x01) {
410 check = 1;
411 }
412 }
413 }
414
415 return (check);
416}
417
418
419static
420void mac_sony_open (mac_sony_t *sony)
421{
422#ifdef DEBUG_SONY
423 mac_log_deb ("sony: open\n");
424#endif
425
426 sony->open = 1;
427
428 if (mac_sony_check (sony)) {
429 sony->pc = sony->check_addr;
430 }
431}
432
433
434static
435unsigned long mac_sony_get_pblk (mac_sony_t *sony, unsigned ofs, unsigned size)
436{
437 if (size == 1) {
438 return (mem_get_uint8 (sony->mem, sony->a0 + ofs));
439 }
440 else if (size == 2) {
441 return (mem_get_uint16_be (sony->mem, sony->a0 + ofs));
442 }
443 else if (size == 4) {
444 return (mem_get_uint32_be (sony->mem, sony->a0 + ofs));
445 }
446
447 return (0);
448}
449
450static
451void mac_sony_set_pblk (mac_sony_t *sony, unsigned ofs, unsigned size, unsigned long val)
452{
453 if (size == 1) {
454 mem_set_uint8 (sony->mem, sony->a0 + ofs, val);
455 }
456 else if (size == 2) {
457 mem_set_uint16_be (sony->mem, sony->a0 + ofs, val);
458 }
459 else if (size == 4) {
460 mem_set_uint32_be (sony->mem, sony->a0 + ofs, val);
461 }
462}
463
464static
465unsigned long mac_sony_get_dctl (mac_sony_t *sony, unsigned ofs, unsigned size)
466{
467 if (size == 1) {
468 return (mem_get_uint8 (sony->mem, sony->a1 + ofs));
469 }
470 else if (size == 2) {
471 return (mem_get_uint16_be (sony->mem, sony->a1 + ofs));
472 }
473 else if (size == 4) {
474 return (mem_get_uint32_be (sony->mem, sony->a1 + ofs));
475 }
476
477 return (0);
478}
479
480static
481void mac_sony_set_dctl (mac_sony_t *sony, unsigned ofs, unsigned size, unsigned long val)
482{
483 if (size == 1) {
484 mem_set_uint8 (sony->mem, sony->a1 + ofs, val);
485 }
486 else if (size == 2) {
487 mem_set_uint16_be (sony->mem, sony->a1 + ofs, val);
488 }
489 else if (size == 4) {
490 mem_set_uint32_be (sony->mem, sony->a1 + ofs, val);
491 }
492}
493
494static
495void mac_sony_return (mac_sony_t *sony, unsigned res, int rts)
496{
497 unsigned trap;
498 unsigned long val;
499
500 sony->d0 = (res & 0x8000) ? (0xffff0000 | res) : 0;
501
502 trap = mac_sony_get_pblk (sony, ioTrap, 2);
503
504 mac_sony_set_pblk (sony, ioResult, 2, res);
505
506 if ((rts == 0) && ((trap & noQueueBit) == 0)) {
507 val = mem_get_uint32_be (sony->mem, 0x0134);
508 val = mem_get_uint32_be (sony->mem, val);
509
510 sony->a1 = val;
511 sony->pc = mem_get_uint32_be (sony->mem, 0x08fc);
512 }
513}
514
515
516static
517unsigned long mac_sony_get_offset (mac_sony_t *sony)
518{
519 unsigned posmode;
520 unsigned long ofs;
521
522 posmode = mac_sony_get_pblk (sony, ioPosMode, 2);
523
524 switch (posmode & 0x0f) {
525 case fsAtMark:
526 ofs = mac_sony_get_dctl (sony, dCtlPosition, 4);
527 break;
528
529 case fsFromStart:
530 ofs = mac_sony_get_pblk (sony, ioPosOffset, 4);
531 break;
532
533 case fsFromMark:
534 ofs = mac_sony_get_pblk (sony, ioPosOffset, 4);
535 ofs += mac_sony_get_dctl (sony, dCtlPosition, 4);
536 break;
537
538 default:
539 return (0);
540 }
541
542 return (ofs);
543}
544
545/*
546 * Get the disk type from a number of blocks
547 */
548static
549unsigned mac_sony_get_disk_type (unsigned long blk)
550{
551 if (blk < ((800 + 1440) / 2)) {
552 return (0);
553 }
554 else if (blk < ((1440 + 1600) / 2)) {
555 return (2);
556 }
557 else if (blk < ((1600 + 2880) / 2)) {
558 return (1);
559 }
560 else if (blk < (2 * 2880)) {
561 return (3);
562 }
563
564 return (255);
565}
566
567static
568int mac_sony_get_chs (unsigned long blk, unsigned long lba, unsigned *c, unsigned *h, unsigned *s)
569{
570 unsigned type;
571 unsigned i, hn, sn;
572
573 type = mac_sony_get_disk_type (blk);
574
575 if ((type == 0) || (type == 1)) {
576 hn = (type == 0) ? 1 : 2;
577 sn = 12;
578 *c = 0;
579
580 for (i = 0; i < 5; i++) {
581 if (lba < (16 * hn * sn)) {
582 *s = (lba % sn);
583 *h = (lba / sn) % hn;
584 *c += lba / (sn * hn);
585 return (0);
586 }
587
588 lba -= 16 * hn * sn;
589 *c += 16;
590 sn -= 1;
591 }
592
593 return (1);
594 }
595 else if (type == 2) {
596 *s = (lba % 9) + 1;
597 *h = (lba / 9) % 2;
598 *c = lba / 18;
599 }
600 else if (type == 3) {
601 *s = (lba % 18) + 1;
602 *h = (lba / 18) % 2;
603 *c = lba / 36;
604 }
605 else {
606 mac_log_deb ("sony: chs error (blk=%lu, lba=%lu)\n", blk, lba);
607 return (1);
608 }
609
610 return (0);
611}
612
613static
614int mac_sony_read_block (disk_t *dsk, void *buf, void *tag, unsigned long idx)
615{
616 unsigned c, h, s;
617 unsigned cnt;
618
619 if (dsk_get_type (dsk) != PCE_DISK_PSI) {
620 memset (tag, 0, 12);
621
622 if (dsk_read_lba (dsk, buf, idx, 1)) {
623 return (1);
624 }
625
626 return (0);
627 }
628
629 if (mac_sony_get_chs (dsk_get_block_cnt (dsk), idx, &c, &h, &s)) {
630 return (1);
631 }
632
633 dsk_psi_read_tags (dsk->ext, tag, 12, c, h, s, 0);
634
635 cnt = 512;
636
637 if (dsk_psi_read_chs (dsk->ext, buf, &cnt, c, h, s, 0) != PCE_BLK_PSI_OK) {
638 mac_log_deb ("sony: read error at %u/%u/%u\n", c, h, s);
639 return (1);
640 }
641
642 return (0);
643}
644
645static
646int mac_sony_write_block (disk_t *dsk, const void *buf, const void *tag, unsigned long idx)
647{
648 unsigned c, h, s;
649 unsigned type;
650 unsigned cnt;
651
652 if (dsk_get_type (dsk) != PCE_DISK_PSI) {
653 if (dsk_write_lba (dsk, buf, idx, 1)) {
654 return (1);
655 }
656
657 return (0);
658 }
659
660 if (mac_sony_get_chs (dsk_get_block_cnt (dsk), idx, &c, &h, &s)) {
661 return (1);
662 }
663
664 type = mac_sony_get_disk_type (dsk_get_block_cnt (dsk));
665
666 if ((type == 0) || (type == 1)) {
667 dsk_psi_write_tags (dsk->ext, tag, 12, c, h, s, 0);
668 }
669
670 cnt = 512;
671
672 if (dsk_psi_write_chs (dsk->ext, buf, &cnt, c, h, s, 0) != PCE_BLK_PSI_OK) {
673 mac_log_deb ("sony: write error at %u/%u/%u\n", c, h, s);
674 return (1);
675 }
676
677 return (0);
678}
679
680static
681void mac_sony_prime_read (mac_sony_t *sony, unsigned drive)
682{
683 unsigned long addr, vars;
684 unsigned long ofs, cnt;
685 unsigned long i, n;
686 unsigned j;
687 disk_t *dsk;
688 unsigned char buf[512];
689 unsigned char tag[12];
690 unsigned posmode;
691
692 ofs = mac_sony_get_offset (sony);
693 cnt = mac_sony_get_pblk (sony, ioReqCount, 4);
694 addr = mac_sony_get_pblk (sony, ioBuffer, 4) & 0x00ffffff;
695 posmode = mac_sony_get_pblk (sony, ioPosMode, 2);
696
697#ifdef DEBUG_SONY
698 mac_log_deb ("sony: prime: read (drive=%u, ofs=0x%08lx, cnt=0x%04lx, addr=0x%08lx)\n",
699 drive, ofs, cnt, addr
700 );
701#endif
702
703 dsk = dsks_get_disk (sony->dsks, drive);
704
705 if (dsk == NULL) {
706 mac_sony_return (sony, offLineErr, 0);
707 return;
708 }
709
710 if (posmode & 0x40) {
711 /* verify */
712 mac_sony_return (sony, noErr, 0);
713 return;
714 }
715
716 if ((ofs & 511) || (cnt & 511)) {
717 mac_log_deb ("sony: non-aligned read\n");
718 mac_sony_return (sony, paramErr, 0);
719 return;
720 }
721
722 n = cnt / 512;
723
724 for (i = 0; i < n; i++) {
725 if (mac_sony_read_block (dsk, buf, tag, (ofs / 512) + i)) {
726 mac_log_deb ("sony: read error at block %lu\n",
727 (ofs / 512) + i
728 );
729 mac_sony_return (sony, 0xffff, 0);
730 return;
731 }
732
733 for (j = 0; j < 512; j++) {
734 mem_set_uint8 (sony->mem, addr + 512 * i + j, buf[j]);
735 }
736
737 for (j = 0; j < 12; j++) {
738 mem_set_uint8 (sony->mem, 0x2fc + j, tag[j]);
739 }
740
741 if (sony->tag_buf != 0) {
742 for (j = 0; j < 12; j++) {
743 mem_set_uint8 (sony->mem, sony->tag_buf + 12 * i + j, tag[j]);
744 }
745 }
746 }
747
748 vars = mac_sony_get_vars (sony, drive);
749 mem_set_uint8 (sony->mem, vars + SONY_DISKINPLACE, 0x02);
750
751 mac_sony_set_pblk (sony, ioActCount, 4, cnt);
752
753 ofs = mac_sony_get_dctl (sony, dCtlPosition, 4);
754 mac_sony_set_dctl (sony, dCtlPosition, 4, ofs + cnt);
755
756 mac_sony_return (sony, noErr, 0);
757}
758
759static
760void mac_sony_prime_write (mac_sony_t *sony, unsigned drive)
761{
762 unsigned long addr;
763 unsigned long ofs, cnt;
764 unsigned relblk;
765 unsigned long i, n;
766 unsigned j;
767 disk_t *dsk;
768 unsigned char buf[512];
769 unsigned char tag[12];
770
771 ofs = mac_sony_get_offset (sony);
772 cnt = mac_sony_get_pblk (sony, ioReqCount, 4);
773 addr = mac_sony_get_pblk (sony, ioBuffer, 4) & 0x00ffffff;
774
775#ifdef DEBUG_SONY
776 mac_log_deb ("sony: prime: write (drive=%u, ofs=0x%08lx, cnt=0x%04lx, addr=0x%08lx)\n",
777 drive, ofs, cnt, addr
778 );
779#endif
780
781 dsk = dsks_get_disk (sony->dsks, drive);
782
783 if (dsk == NULL) {
784 mac_sony_return (sony, offLineErr, 0);
785 return;
786 }
787
788 if (dsk_get_readonly (dsk)) {
789 mac_sony_return (sony, wPrErr, 0);
790 return;
791 }
792
793 if ((cnt & 511) || (ofs & 511)) {
794 mac_log_deb ("sony: non-aligned write\n");
795 mac_sony_return (sony, paramErr, 0);
796 return;
797 }
798
799 memset (tag, 0, 12);
800
801 relblk = mem_get_uint16_be (sony->mem, 0x302);
802
803 n = cnt / 512;
804
805 for (i = 0; i < n; i++) {
806 for (j = 0; j < 512; j++) {
807 buf[j] = mem_get_uint8 (sony->mem, addr + 512 * i + j);
808 }
809
810 if (sony->tag_buf != 0) {
811 for (j = 0; j < 12; j++) {
812 tag[j] = mem_get_uint8 (sony->mem, sony->tag_buf + 12 * i + j);
813 mem_set_uint8 (sony->mem, 0x2fc + j, tag[j]);
814 }
815 }
816 else {
817 mem_set_uint16_be (sony->mem, 0x302, relblk + i);
818
819 for (j = 0; j < 12; j++) {
820 tag[j] = mem_get_uint8 (sony->mem, 0x2fc + j);
821 }
822 }
823
824 if (mac_sony_write_block (dsk, buf, tag, (ofs / 512) + i)) {
825 mac_log_deb ("sony: write error at block %lu\n",
826 (ofs / 512) + i
827 );
828 mac_sony_return (sony, 0xffff, 0);
829 return;
830 }
831 }
832
833 mac_sony_set_pblk (sony, ioActCount, 4, cnt);
834
835 ofs = mac_sony_get_dctl (sony, dCtlPosition, 4);
836 mac_sony_set_dctl (sony, dCtlPosition, 4, ofs + cnt);
837
838 mac_sony_return (sony, noErr, 0);
839}
840
841static
842void mac_sony_prime (mac_sony_t *sony)
843{
844 unsigned long vars;
845 unsigned trap, vref;
846
847 trap = mac_sony_get_pblk (sony, ioTrap, 2);
848 vref = mac_sony_get_pblk (sony, ioVRefNum, 2);
849
850 if ((vref < 1) || (vref > SONY_DRIVES)) {
851 mac_sony_return (sony, nsDrvErr, 0);
852 return;
853 }
854
855 vars = mac_sony_get_vars (sony, vref);
856
857 if (mem_get_uint8 (sony->mem, vars + SONY_DISKINPLACE) == 0) {
858 mac_sony_return (sony, offLineErr, 0);
859 return;
860 }
861
862 mem_set_uint8 (sony->mem, vars + SONY_DISKINPLACE, 0x02);
863
864 switch (trap & 0xff) {
865 case 2: /* read */
866 mac_sony_prime_read (sony, vref);
867 break;
868
869 case 3: /* write */
870 mac_sony_prime_write (sony, vref);
871 break;
872
873 default:
874 mac_log_deb ("sony: prime: unknown (trap=0x%04x)\n", trap);
875 mac_sony_return (sony, 0xffef, 0);
876 break;
877 }
878}
879
880
881static
882int mac_sony_format (disk_t *dsk, unsigned long blk)
883{
884 unsigned long i, n;
885 unsigned c, h, s, hn, sn;
886 unsigned type;
887 unsigned char buf[512];
888 psi_sct_t *sct;
889 disk_psi_t *psi;
890
891 if (dsk_get_type (dsk) != PCE_DISK_PSI) {
892 n = dsk_get_block_cnt (dsk);
893
894 if (n != blk) {
895 return (1);
896 }
897
898 memset (buf, 0x00, 512);
899
900 for (i = 0; i < n; i++) {
901 dsk_write_lba (dsk, buf, i, 1);
902 }
903
904 return (0);
905 }
906
907 psi = dsk->ext;
908
909 memset (buf, 0, 12);
910
911 type = mac_sony_get_disk_type (blk);
912
913 dsk_psi_erase_disk (psi);
914
915 if ((type == 0) || (type == 1)) {
916 dsk_psi_set_encoding (psi, PSI_ENC_GCR);
917
918 hn = (type == 0) ? 1 : 2;
919 sn = 13;
920
921 for (c = 0; c < 80; c++) {
922 if ((c & 15) == 0) {
923 sn -= 1;
924 }
925
926 for (h = 0; h < hn; h++) {
927 for (s = 0; s < sn; s++) {
928 dsk_psi_format_sector (psi, c, h, c, h, s, 512, 0);
929
930 sct = psi_img_get_sector (psi->img, c, h, s, 1);
931
932 if (sct != NULL) {
933 psi_sct_set_tags (sct, buf, 12);
934 }
935 }
936 }
937 }
938 }
939 else if ((type == 2) || (type == 3)) {
940 dsk_psi_set_encoding (psi, (type == 2) ? PSI_ENC_MFM_DD : PSI_ENC_MFM_HD);
941
942 sn = (type == 2) ? 9 : 18;
943
944 for (c = 0; c < 80; c++) {
945 for (h = 0; h < 2; h++) {
946 for (s = 0; s < sn; s++) {
947 dsk_psi_format_sector (psi, c, h, c, h, s + 1, 512, 0);
948 }
949 }
950 }
951 }
952 else {
953 return (1);
954 }
955
956 mac_log_deb ("sony: formatted disk (%lu blocks)\n", dsk_get_block_cnt (dsk));
957
958 return (0);
959}
960
961static
962void mac_sony_ctl_verify (mac_sony_t *sony)
963{
964 unsigned vref;
965 disk_t *dsk;
966
967 vref = mac_sony_get_pblk (sony, ioVRefNum, 2);
968
969#ifdef DEBUG_SONY
970 mac_log_deb ("sony: control: verify (drive=%u)\n", vref);
971#endif
972
973 if ((vref < 1) || (vref > SONY_DRIVES)) {
974 mac_sony_return (sony, nsDrvErr, 0);
975 return;
976 }
977
978 dsk = dsks_get_disk (sony->dsks, vref);
979
980 if (dsk == NULL) {
981 mac_sony_return (sony, noDriveErr, 0);
982 return;
983 }
984
985 mac_sony_return (sony, noErr, 0);
986}
987
988static
989void mac_sony_ctl_eject (mac_sony_t *sony)
990{
991 unsigned vref;
992 unsigned long vars;
993
994 vref = mac_sony_get_pblk (sony, ioVRefNum, 2);
995
996#ifdef DEBUG_SONY
997 mac_log_deb ("sony: control eject (drive=%u)\n", vref);
998#endif
999
1000 if ((vref < 1) || (vref > SONY_DRIVES)) {
1001 mac_sony_return (sony, nsDrvErr, 0);
1002 return;
1003 }
1004
1005 vars = mac_sony_get_vars (sony, vref);
1006
1007 mem_set_uint8 (sony->mem, vars + SONY_DISKINPLACE, 0x00);
1008 mem_set_uint8 (sony->mem, vars + SONY_WPROT, 0x00);
1009 mem_set_uint8 (sony->mem, vars + SONY_TWOSIDEFMT, 0x00);
1010
1011 mac_sony_return (sony, noErr, 0);
1012}
1013
1014static
1015void mac_sony_ctl_set_tag_buf (mac_sony_t *sony)
1016{
1017 unsigned long tagbuf;
1018
1019 tagbuf = mac_sony_get_pblk (sony, csParam, 4);
1020
1021#ifdef DEBUG_SONY
1022 mac_log_deb ("sony: control: set tag buffer (buf=0x%08lx)\n", tagbuf);
1023#endif
1024
1025 sony->tag_buf = tagbuf & 0x00ffffff;
1026
1027 mac_sony_return (sony, noErr, 0);
1028}
1029
1030static
1031void mac_sony_ctl_format (mac_sony_t *sony)
1032{
1033 unsigned vref, format;
1034 unsigned long blk;
1035 unsigned long vars;
1036 disk_t *dsk;
1037
1038 vref = mac_sony_get_pblk (sony, ioVRefNum, 2);
1039 format = mac_sony_get_pblk (sony, csParam, 2);
1040
1041#ifdef DEBUG_SONY
1042 mac_log_deb ("sony: control format (drive=%u, format=%u)\n", vref, format);
1043#endif
1044
1045 if ((vref < 1) || (vref > SONY_DRIVES)) {
1046 mac_sony_return (sony, nsDrvErr, 0);
1047 return;
1048 }
1049
1050 dsk = dsks_get_disk (sony->dsks, vref);
1051
1052 if (dsk == NULL) {
1053 mac_sony_return (sony, noDriveErr, 0);
1054 return;
1055 }
1056
1057 if (dsk->readonly) {
1058 mac_sony_return (sony, wPrErr, 0);
1059 return;
1060 }
1061
1062 if ((format > 0) && (format <= sony->format_cnt)) {
1063 blk = sony->format_list[2 * (format - 1)];
1064 }
1065 else {
1066 blk = dsk_get_block_cnt (dsk);
1067
1068 if (dsk_get_type (dsk) == PCE_DISK_PSI) {
1069 if (format == 1) {
1070 blk = 800;
1071 }
1072 else if (format == 2) {
1073 blk = 1600;
1074 }
1075
1076 if (blk == 0) {
1077 blk = 800;
1078 }
1079 }
1080 }
1081
1082 if (mac_sony_format (dsk, blk)) {
1083 mac_sony_return (sony, paramErr, 0);
1084 return;
1085 }
1086
1087 vars = mac_sony_get_vars (sony, vref);
1088 mem_set_uint16_be (sony->mem, vars + 18, blk);
1089 mem_set_uint16_be (sony->mem, vars + 20, blk >> 16);
1090
1091 mac_sony_return (sony, noErr, 0);
1092}
1093
1094static
1095void mac_sony_ctl_get_icon (mac_sony_t *sony, int which)
1096{
1097 unsigned vref;
1098 unsigned long addr, addr1, addr2;
1099 disk_t *dsk;
1100
1101 vref = mac_sony_get_pblk (sony, ioVRefNum, 2);
1102
1103#ifdef DEBUG_SONY
1104 mac_log_deb ("sony: control: get %s icon (drive=%u)\n",
1105 which ? "media" : "drive", vref
1106 );
1107#endif
1108
1109 if ((vref < 1) || (vref > SONY_DRIVES)) {
1110 mac_sony_return (sony, nsDrvErr, 0);
1111 return;
1112 }
1113
1114 addr1 = sony->icon_addr[0];
1115 addr2 = sony->icon_addr[1];
1116
1117 dsk = dsks_get_disk (sony->dsks, vref);
1118
1119 if (dsk == NULL) {
1120 addr = addr1;
1121 }
1122 else {
1123 switch (dsk_get_block_cnt (dsk)) {
1124 case 800:
1125 case 1600:
1126 case 1440:
1127 case 2880:
1128 addr = addr1;
1129 break;
1130
1131 default:
1132 addr = addr2;
1133 break;
1134 }
1135 }
1136
1137 mac_sony_set_pblk (sony, csParam, 4, addr);
1138
1139 mac_sony_return (sony, noErr, 0);
1140}
1141
1142static
1143void mac_sony_ctl_get_drive_info (mac_sony_t *sony)
1144{
1145 unsigned vref, val;
1146
1147 vref = mac_sony_get_pblk (sony, ioVRefNum, 2);
1148
1149#ifdef DEBUG_SONY
1150 mac_log_deb ("sony: control: get drive info (drive=%u)\n", vref);
1151#endif
1152
1153 if ((vref < 1) || (vref > SONY_DRIVES)) {
1154 mac_sony_return (sony, nsDrvErr, 0);
1155 return;
1156 }
1157
1158 val = vref - 1;
1159 val = ((val << 3) & 8) | ((val >> 1) & 1);
1160
1161 mac_sony_set_pblk (sony, csParam, 4, (val << 8) | 0x04);
1162
1163 mac_sony_return (sony, noErr, 0);
1164}
1165
1166static
1167void mac_sony_ctl_format_copy (mac_sony_t *sony)
1168{
1169 unsigned i;
1170 unsigned vref, format, type;
1171 unsigned long data, tags;
1172 unsigned long idx, blk;
1173 unsigned char buf[512];
1174 unsigned char tag[12];
1175 disk_t *dsk;
1176
1177 vref = mac_sony_get_pblk (sony, ioVRefNum, 2);
1178
1179 format = mac_sony_get_pblk (sony, csParam, 2);
1180 data = mac_sony_get_pblk (sony, csParam + 2, 4);
1181 tags = mac_sony_get_pblk (sony, csParam + 6, 4);
1182
1183#ifdef DEBUG_SONY
1184 mac_log_deb ("sony: control: format/copy (drive=%u, format=%u, data=0x%08lx, tags=0x%08lx)\n",
1185 vref, format, data, tags
1186 );
1187#endif
1188
1189 if ((vref < 1) || (vref > SONY_DRIVES)) {
1190 mac_sony_return (sony, nsDrvErr, 0);
1191 return;
1192 }
1193
1194 dsk = dsks_get_disk (sony->dsks, vref);
1195
1196 if (dsk == NULL) {
1197 mac_sony_return (sony, noDriveErr, 0);
1198 return;
1199 }
1200
1201 if (dsk->readonly) {
1202 mac_sony_return (sony, wPrErr, 0);
1203 return;
1204 }
1205
1206 if ((format > 0) && (format <= sony->format_cnt)) {
1207 blk = sony->format_list[2 * (format - 1)];
1208 }
1209 else {
1210 mac_sony_return (sony, paramErr, 0);
1211 return;
1212 }
1213
1214 type = mac_sony_get_disk_type (blk);
1215
1216 if (mac_sony_format (dsk, blk)) {
1217 mac_sony_return (sony, paramErr, 0);
1218 return;
1219 }
1220
1221 data &= 0x00ffffff;
1222 tags &= 0x00ffffff;
1223
1224 memset (tag, 0, 12);
1225
1226 for (idx = 0; idx < blk; idx++) {
1227 for (i = 0; i < 512; i++) {
1228 buf[i] = mem_get_uint8 (sony->mem, data + i);
1229 }
1230
1231 if ((type != 2) && (type != 3)) {
1232 for (i = 0; i < 12; i++) {
1233 tag[i] = mem_get_uint8 (sony->mem, tags + i);
1234 }
1235 }
1236
1237 if (mac_sony_write_block (dsk, buf, tag, idx)) {
1238 mac_sony_return (sony, 0xffff, 0);
1239 return;
1240 }
1241
1242 data += 512;
1243 tags += 12;
1244 }
1245
1246 mac_sony_return (sony, noErr, 0);
1247}
1248
1249static
1250void mac_sony_control (mac_sony_t *sony)
1251{
1252 unsigned cscode;
1253
1254 cscode = mac_sony_get_pblk (sony, csCode, 2);
1255
1256 switch (cscode) {
1257 case 1: /* kill io */
1258 mac_sony_return (sony, abortErr, 1);
1259 break;
1260
1261 case 5: /* verify disk */
1262 mac_sony_ctl_verify (sony);
1263 break;
1264
1265 case 7: /* eject disk */
1266 mac_sony_ctl_eject (sony);
1267 return;
1268
1269 case 8: /* set tag buffer */
1270 mac_sony_ctl_set_tag_buf (sony);
1271 break;
1272
1273 case 9: /* track cache control */
1274 mac_sony_return (sony, 0xffc8, 0);
1275 break;
1276
1277 case 6: /* format disk */
1278 mac_sony_ctl_format (sony);
1279 return;
1280
1281 case 21: /* get drive icon */
1282 mac_sony_ctl_get_icon (sony, 0);
1283 return;
1284
1285 case 22: /* get media icon */
1286 mac_sony_ctl_get_icon (sony, 1);
1287 return;
1288
1289 case 23: /* get drive info */
1290 mac_sony_ctl_get_drive_info (sony);
1291 return;
1292
1293 case 21315: /* FmtCopy */
1294 mac_sony_ctl_format_copy (sony);
1295 return;
1296
1297 default:
1298 mac_log_deb ("sony: control: unknown (opcode=0x%04x)\n", cscode);
1299 mac_sony_return (sony, controlErr, 0);
1300 return;
1301 }
1302}
1303
1304
1305static
1306void mac_sony_status_format_list (mac_sony_t *sony)
1307{
1308 unsigned i;
1309 unsigned long ptr;
1310 unsigned vref, cnt;
1311 unsigned long blk;
1312 unsigned long *list;
1313 disk_t *dsk;
1314
1315 vref = mac_sony_get_pblk (sony, ioVRefNum, 2);
1316 cnt = mac_sony_get_pblk (sony, csParam, 2);
1317 ptr = mac_sony_get_pblk (sony, csParam + 2, 4);
1318
1319#ifdef DEBUG_SONY
1320 mac_log_deb ("sony: status: get format list (drive=%u, maxfmt=%u)\n",
1321 vref, cnt
1322 );
1323#endif
1324
1325 if ((vref < 1) || (vref > SONY_DRIVES)) {
1326 mac_sony_return (sony, nsDrvErr, 0);
1327 return;
1328 }
1329
1330 dsk = dsks_get_disk (sony->dsks, vref);
1331
1332 if (dsk == NULL) {
1333 mac_sony_return (sony, noDriveErr, 0);
1334 return;
1335 }
1336
1337 blk = dsk_get_block_cnt (dsk);
1338
1339 list = sony->format_list;
1340
1341 if (dsk_get_type (dsk) == PCE_DISK_PSI) {
1342 sony->format_cnt = 4;
1343
1344 list[0] = 800;
1345 list[1] = 0x810a0050;
1346 list[2] = 1600;
1347 list[3] = 0x820a0050;
1348 list[4] = 1440;
1349 list[5] = 0x82090050;
1350 list[6] = 2880;
1351 list[7] = 0x92120050;
1352
1353 switch (mac_sony_get_disk_type (blk)) {
1354 case 0:
1355 list[1] |= 0x40000000;
1356 break;
1357
1358 case 1:
1359 list[3] |= 0x40000000;
1360 break;
1361
1362 case 2:
1363 list[5] |= 0x40000000;
1364 break;
1365
1366 case 3:
1367 default:
1368 if (sony->format_hd_as_dd) {
1369 list[7] |= 0x40000000;
1370 }
1371 else {
1372 sony->format_cnt = 1;
1373 list[0] = 2880;
1374 list[1] = 0xd2120050;
1375 }
1376 break;
1377 }
1378 }
1379 else {
1380 sony->format_cnt = 1;
1381 list[0] = blk;
1382 list[1] = 0;
1383 }
1384
1385 if (cnt > sony->format_cnt) {
1386 cnt = sony->format_cnt;
1387 }
1388
1389 for (i = 0; i < cnt; i++) {
1390 mem_set_uint32_be (sony->mem, ptr + 8 * i + 0, list[2 * i + 0]);
1391 mem_set_uint32_be (sony->mem, ptr + 8 * i + 4, list[2 * i + 1]);
1392 }
1393
1394 mac_sony_set_pblk (sony, csParam, 2, cnt);
1395
1396 mac_sony_return (sony, noErr, 0);
1397}
1398
1399static
1400void mac_sony_status_drive_status (mac_sony_t *sony)
1401{
1402 unsigned i;
1403 unsigned vref, val;
1404 unsigned long src;
1405 disk_t *dsk;
1406
1407 vref = mac_sony_get_pblk (sony, ioVRefNum, 2);
1408
1409#ifdef DEBUG_SONY
1410 mac_log_deb ("sony: status: get drive status (drive=%u)\n", vref);
1411#endif
1412
1413 if ((vref < 1) || (vref > SONY_DRIVES)) {
1414 mac_sony_return (sony, nsDrvErr, 0);
1415 return;
1416 }
1417
1418 dsk = dsks_get_disk (sony->dsks, vref);
1419
1420 if (dsk == NULL) {
1421 mac_sony_return (sony, noDriveErr, 0);
1422 return;
1423 }
1424
1425 src = mac_sony_get_vars (sony, vref);
1426
1427 for (i = 0; i < 11; i++) {
1428 val = mem_get_uint16_be (sony->mem, src + 2 * i);
1429 mac_sony_set_pblk (sony, csParam + 2 * i, 2, val);
1430 }
1431
1432 mac_sony_return (sony, noErr, 0);
1433}
1434
1435static
1436void mac_sony_status (mac_sony_t *sony)
1437{
1438 unsigned cscode;
1439
1440 cscode = mac_sony_get_pblk (sony, csCode, 2);
1441
1442 switch (cscode) {
1443 case 6: /* return format list */
1444 mac_sony_status_format_list (sony);
1445 break;
1446
1447 case 8: /* drive status */
1448 mac_sony_status_drive_status (sony);
1449 break;
1450
1451 default:
1452 mac_sony_return (sony, statusErr, 0);
1453 mac_log_deb ("sony: status: unknown (cs=0x%04x)\n", cscode);
1454 break;
1455 }
1456}
1457
1458int mac_sony_hook (mac_sony_t *sony, unsigned val)
1459{
1460 switch (val) {
1461 case MAC_HOOK_SONY_OPEN:
1462 mac_sony_open (sony);
1463 return (0);
1464
1465 case MAC_HOOK_SONY_PRIME:
1466 mac_sony_prime (sony);
1467 return (0);
1468
1469 case MAC_HOOK_SONY_CTRL:
1470 mac_sony_control (sony);
1471 return (0);
1472
1473 case MAC_HOOK_SONY_STATUS:
1474 mac_sony_status (sony);
1475 return (0);
1476
1477 case MAC_HOOK_SONY_CLOSE:
1478 return (0);
1479 }
1480
1481 return (1);
1482}
1483
1484void mac_sony_reset (mac_sony_t *sony)
1485{
1486 unsigned i;
1487
1488 mac_sony_unpatch_rom (sony);
1489
1490 sony->open = 0;
1491
1492 for (i = 0; i < SONY_DRIVES; i++) {
1493 sony->delay_cnt[i] = sony->delay_val[i];
1494 }
1495}