forked from tonioni/WinUAE
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gayle.cpp
2261 lines (2069 loc) · 55.5 KB
/
gayle.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* UAE - The Un*x Amiga Emulator
*
* Gayle (and motherboard resources) memory bank
*
* (c) 2006 - 2015 Toni Wilen
*/
#define GAYLE_LOG 0
#define MBRES_LOG 0
#define PCMCIA_LOG 0
#include "sysconfig.h"
#include "sysdeps.h"
#include "options.h"
#include "memory.h"
#include "custom.h"
#include "newcpu.h"
#include "filesys.h"
#include "gayle.h"
#include "savestate.h"
#include "uae.h"
#include "gui.h"
#include "threaddep/thread.h"
#include "a2091.h"
#include "ncr_scsi.h"
#include "ncr9x_scsi.h"
#include "blkdev.h"
#include "scsi.h"
#include "ide.h"
#include "idecontrollers.h"
#include "pci_hw.h"
#include "debug.h"
#include "autoconf.h"
#include "rommgr.h"
#include "devices.h"
#define PCMCIA_SRAM 1
#define PCMCIA_IDE 2
#define PCMCIA_NE2000 3
#define PCMCIA_ARCHOSHD 4
#define PCMCIA_SURFSQUIRREL 5
/*
600000 to 9FFFFF 4 MB Credit Card memory if CC present
A00000 to A1FFFF 128 KB Credit Card Attributes
A20000 to A3FFFF 128 KB Credit Card I/O
A40000 to A5FFFF 128 KB Credit Card Bits
A60000 to A7FFFF 128 KB PC I/O
D80000 to D8FFFF 64 KB SPARE chip select
D90000 to D9FFFF 64 KB ARCNET chip select
DA0000 to DA3FFF 16 KB IDE drive
DA4000 to DA4FFF 16 KB IDE reserved
DA8000 to DAFFFF 32 KB Credit Card and IDE configregisters
DB0000 to DBFFFF 64 KB Not used (reserved for external IDE)
* DC0000 to DCFFFF 64 KB Real Time Clock (RTC)
DD0000 to DDFFFF 64 KB A3000 DMA controller
DD0000 to DD1FFF A4000 DMAC
DD2000 to DDFFFF A4000 IDE
DE0000 to DEFFFF 64 KB Motherboard resources
*/
/* A4000T NCR */
#define NCR_OFFSET 0x40
#define NCR_ALT_OFFSET 0x80
#define NCR_MASK 0x3f
/* Gayle definitions from Linux drivers and preliminary Gayle datasheet */
/* PCMCIA stuff */
#define GAYLE_RAM 0x600000
#define GAYLE_RAMSIZE 0x400000
#define GAYLE_ATTRIBUTE 0xa00000
#define GAYLE_ATTRIBUTESIZE 0x020000
#define GAYLE_IO 0xa20000 /* 16bit and even 8bit registers */
#define GAYLE_IOSIZE 0x010000
#define GAYLE_IO_8BITODD 0xa30000 /* odd 8bit registers */
#define GAYLE_ADDRESS 0xda8000 /* gayle main registers base address */
#define GAYLE_RESET 0xa40000 /* write 0x00 to start reset, read 1 byte to stop reset */
/* Bases of the IDE interfaces */
#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */
#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */
/*
* These are at different offsets from the base
*/
#define GAYLE_IRQ_4000 0x3020 /* WORD register MSB = 1, Harddisk is source of interrupt */
#define GAYLE_CS_1200 0x8000
#define GAYLE_IRQ_1200 0x9000
#define GAYLE_INT_1200 0xA000
#define GAYLE_CFG_1200 0xB000
/* DA8000 */
#define GAYLE_CS_IDE 0x80 /* IDE int status */
#define GAYLE_CS_CCDET 0x40 /* credit card detect */
#define GAYLE_CS_BVD1 0x20 /* battery voltage detect 1 */
#define GAYLE_CS_SC 0x20 /* credit card status change */
#define GAYLE_CS_BVD2 0x10 /* battery voltage detect 2 */
#define GAYLE_CS_DA 0x10 /* digital audio */
#define GAYLE_CS_WR 0x08 /* write enable (1 == enabled) */
#define GAYLE_CS_BSY 0x04 /* credit card busy */
#define GAYLE_CS_IRQ 0x04 /* interrupt request */
#define GAYLE_CS_DAEN 0x02 /* enable digital audio */
#define GAYLE_CS_DIS 0x01 /* disable PCMCIA slot */
/* DA9000 */
#define GAYLE_IRQ_IDE 0x80
#define GAYLE_IRQ_CCDET 0x40 /* credit card detect */
#define GAYLE_IRQ_BVD1 0x20 /* battery voltage detect 1 */
#define GAYLE_IRQ_SC 0x20 /* credit card status change */
#define GAYLE_IRQ_BVD2 0x10 /* battery voltage detect 2 */
#define GAYLE_IRQ_DA 0x10 /* digital audio */
#define GAYLE_IRQ_WR 0x08 /* write enable (1 == enabled) */
#define GAYLE_IRQ_BSY 0x04 /* credit card busy */
#define GAYLE_IRQ_IRQ 0x04 /* interrupt request */
#define GAYLE_IRQ_RESET 0x02 /* reset machine after CCDET change */
#define GAYLE_IRQ_BERR 0x01 /* generate bus error after CCDET change */
/* DAA000 */
#define GAYLE_INT_IDE 0x80 /* IDE interrupt enable */
#define GAYLE_INT_CCDET 0x40 /* credit card detect change enable */
#define GAYLE_INT_BVD1 0x20 /* battery voltage detect 1 change enable */
#define GAYLE_INT_SC 0x20 /* credit card status change enable */
#define GAYLE_INT_BVD2 0x10 /* battery voltage detect 2 change enable */
#define GAYLE_INT_DA 0x10 /* digital audio change enable */
#define GAYLE_INT_WR 0x08 /* write enable change enabled */
#define GAYLE_INT_BSY 0x04 /* credit card busy */
#define GAYLE_INT_IRQ 0x04 /* credit card interrupt request */
#define GAYLE_INT_BVD_LEV 0x02 /* BVD int level, 0=lev2,1=lev6 */
#define GAYLE_INT_BSY_LEV 0x01 /* BSY int level, 0=lev2,1=lev6 */
/* 0xDAB000 GAYLE_CONFIG */
#define GAYLE_CFG_0V 0x00
#define GAYLE_CFG_5V 0x01
#define GAYLE_CFG_12V 0x02
#define GAYLE_CFG_100NS 0x08
#define GAYLE_CFG_150NS 0x04
#define GAYLE_CFG_250NS 0x00
#define GAYLE_CFG_720NS 0x0c
#define TOTAL_IDE 3
#define GAYLE_IDE_ID 0
#define PCMCIA_IDE_ID 2
static struct ide_hdf *idedrive[TOTAL_IDE * 2];
static struct ide_hdf *archoshd[2];
struct hd_hardfiledata *pcmcia_disk;
static int pcmcia_card;
static int pcmcia_readonly;
static int pcmcia_type;
static uae_u8 pcmcia_configuration[20];
static int pcmcia_configured;
static int pcmcia_delayed_insert, pcmcia_delayed_insert_count;
static int external_card_int;
static int gayle_id_cnt;
static uae_u8 gayle_irq, gayle_int, gayle_cs, gayle_cs_mask, gayle_cfg;
static int ide_splitter;
static struct ide_thread_state gayle_its, pcmcia_its;
static bool ne2000_pcmcia_irq;
static int dataflyer_state;
static int dataflyer_disable_irq;
static uae_u8 dataflyer_byte;
static void gayle_reset(int hardreset);
static void gayle_map_pcmcia(void);
static void pcmcia_reset (void)
{
memset (pcmcia_configuration, 0, sizeof pcmcia_configuration);
pcmcia_configured = -1;
if (PCMCIA_LOG > 0)
write_log (_T("PCMCIA reset\n"));
}
static uae_u8 checkpcmciane2000irq(void)
{
if (ne2000_pcmcia_irq)
return GAYLE_IRQ_BSY;
return 0;
}
static uae_u8 checkpcmciaideirq (void)
{
if (!idedrive[PCMCIA_IDE_ID * 2] || pcmcia_type != PCMCIA_IDE || pcmcia_configured < 0)
return 0;
if (!idedrive[PCMCIA_IDE_ID * 2]->regs0 || (idedrive[PCMCIA_IDE_ID * 2]->regs0->ide_devcon & 2))
return 0;
if (idedrive[PCMCIA_IDE_ID * 2]->irq)
return GAYLE_IRQ_BSY;
return 0;
}
static uae_u8 checkgayleideirq (void)
{
int i;
bool irq = false;
if (dataflyer_disable_irq) {
gayle_irq &= ~GAYLE_IRQ_IDE;
return 0;
}
for (i = 0; i < 2; i++) {
if (idedrive[i]) {
if (!(idedrive[i]->regs.ide_devcon & 2) && (idedrive[i]->irq || (idedrive[i + 2] && idedrive[i + 2]->irq)))
irq = true;
/* IDE killer feature. Do not eat interrupt to make booting faster. */
if (idedrive[i]->irq && !ide_isdrive (idedrive[i]))
idedrive[i]->irq = 0;
if (idedrive[i + 2] && idedrive[i + 2]->irq && !ide_isdrive (idedrive[i + 2]))
idedrive[i + 2]->irq = 0;
}
}
return irq ? GAYLE_IRQ_IDE : 0;
}
bool isideint(void)
{
return checkgayleideirq() != 0;
}
static void rethink_gayle (void)
{
int lev2 = 0;
int lev6 = 0;
uae_u8 mask;
if (currprefs.cs_ide == IDE_A4000) {
gayle_irq |= checkgayleideirq ();
if ((gayle_irq & GAYLE_IRQ_IDE))
safe_interrupt_set(IRQ_SOURCE_GAYLE, 0, false);
return;
}
if (currprefs.cs_ide != IDE_A600A1200 && !currprefs.cs_pcmcia)
return;
gayle_irq |= checkgayleideirq();
gayle_irq |= checkpcmciaideirq();
gayle_irq |= checkpcmciane2000irq();
gayle_irq |= external_card_int;
mask = gayle_int & gayle_irq;
if (mask & (GAYLE_IRQ_IDE | GAYLE_IRQ_WR))
lev2 = 1;
if (mask & GAYLE_IRQ_CCDET)
lev6 = 1;
if (mask & (GAYLE_IRQ_BVD1 | GAYLE_IRQ_BVD2)) {
if (gayle_int & GAYLE_INT_BVD_LEV)
lev6 = 1;
else
lev2 = 1;
}
if (mask & GAYLE_IRQ_BSY) {
if (gayle_int & GAYLE_INT_BSY_LEV)
lev6 = 1;
else
lev2 = 1;
}
if (lev2)
safe_interrupt_set(IRQ_SOURCE_GAYLE, 0, false);
if (lev6)
safe_interrupt_set(IRQ_SOURCE_GAYLE, 0, true);
}
void pcmcia_interrupt_set(int level)
{
if (level) {
if (!external_card_int)
write_log("PCMCIA IRQ ACTIVE\n");
external_card_int |= GAYLE_INT_IRQ;
} else {
if (external_card_int)
write_log("PCMCIA IRQ INACTIVE\n");
external_card_int &= ~GAYLE_INT_IRQ;
}
rethink_gayle();
}
static void gayle_cs_change (uae_u8 mask, int onoff)
{
int changed = 0;
if ((gayle_cs & mask) && !onoff) {
gayle_cs &= ~mask;
changed = 1;
} else if (!(gayle_cs & mask) && onoff) {
gayle_cs |= mask;
changed = 1;
}
if (changed) {
gayle_irq |= mask;
devices_rethink_all(rethink_gayle);
if ((mask & GAYLE_CS_CCDET) && (gayle_irq & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR)) != (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR)) {
if (gayle_irq & GAYLE_IRQ_RESET)
uae_reset (0, 0);
if (gayle_irq & GAYLE_IRQ_BERR)
Exception (2);
}
}
}
static void card_trigger (int insert)
{
external_card_int = 0;
if (insert) {
if (pcmcia_card) {
gayle_cs_change (GAYLE_CS_CCDET, 1);
gayle_cfg = GAYLE_CFG_100NS;
if (!pcmcia_readonly)
gayle_cs_change (GAYLE_CS_WR, 1);
}
} else {
gayle_cfg = 0;
gayle_cs_change (GAYLE_CS_CCDET, 0);
gayle_cs_change (GAYLE_CS_BVD2, 0);
gayle_cs_change (GAYLE_CS_BVD1, 0);
gayle_cs_change (GAYLE_CS_WR, 0);
gayle_cs_change (GAYLE_CS_BSY, 0);
}
devices_rethink_all(rethink_gayle);
}
static void write_gayle_cfg (uae_u8 val)
{
gayle_cfg = val;
}
static uae_u8 read_gayle_cfg (void)
{
return gayle_cfg & 0x0f;
}
static void write_gayle_irq (uae_u8 val)
{
gayle_irq = (gayle_irq & val) | (val & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
if ((gayle_irq & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR)) == (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR))
pcmcia_reset ();
}
static uae_u8 read_gayle_irq (void)
{
return gayle_irq;
}
static void write_gayle_int (uae_u8 val)
{
gayle_int = val;
}
static uae_u8 read_gayle_int (void)
{
return gayle_int;
}
static void write_gayle_cs (uae_u8 val)
{
int ov = gayle_cs;
gayle_cs_mask = val & ~3;
gayle_cs &= ~3;
gayle_cs |= val & 3;
if ((ov & 1) != (gayle_cs & 1)) {
gayle_map_pcmcia ();
/* PCMCIA disable -> enable */
card_trigger (!(gayle_cs & GAYLE_CS_DIS) ? 1 : 0);
if (PCMCIA_LOG)
write_log (_T("PCMCIA slot: %s PC=%08X\n"), !(gayle_cs & 1) ? _T("enabled") : _T("disabled"), M68K_GETPC);
}
}
static uae_u8 read_gayle_cs (void)
{
uae_u8 v;
v = gayle_cs_mask | gayle_cs;
v |= checkgayleideirq ();
v |= checkpcmciaideirq ();
return v;
}
static int get_gayle_ide_reg (uaecptr addr, struct ide_hdf **ide)
{
int ide2;
addr &= 0xffff;
*ide = NULL;
if (addr >= GAYLE_IRQ_4000 && addr <= GAYLE_IRQ_4000 + 1 && currprefs.cs_ide == IDE_A4000)
return -1;
addr &= ~0x2020;
addr >>= 2;
ide2 = 0;
if (addr & IDE_SECONDARY) {
if (ide_splitter) {
ide2 = 2;
addr &= ~IDE_SECONDARY;
}
}
*ide = idedrive[ide2 + idedrive[ide2]->ide_drv];
return addr;
}
static uae_u32 gayle_read2 (uaecptr addr)
{
struct ide_hdf *ide = NULL;
int ide_reg;
addr &= 0xffff;
if ((GAYLE_LOG > 3 && (addr != 0x2000 && addr != 0x2001 && addr != 0x3020 && addr != 0x3021 && addr != GAYLE_IRQ_1200)) || GAYLE_LOG > 5)
write_log (_T("IDE_READ %08X PC=%X\n"), addr, M68K_GETPC);
if (currprefs.cs_ide <= 0) {
if (addr == 0x201c) // AR1200 IDE detection hack
return 0x7f;
return 0xff;
}
if (addr >= GAYLE_IRQ_4000 && addr <= GAYLE_IRQ_4000 + 1 && currprefs.cs_ide == IDE_A4000) {
uae_u8 v = gayle_irq;
gayle_irq = 0;
return v;
}
if (addr >= 0x4000) {
if (addr == GAYLE_IRQ_1200) {
if (currprefs.cs_ide == IDE_A600A1200)
return read_gayle_irq ();
return 0;
} else if (addr == GAYLE_INT_1200) {
if (currprefs.cs_ide == IDE_A600A1200)
return read_gayle_int ();
return 0;
}
return 0;
}
ide_reg = get_gayle_ide_reg (addr, &ide);
/* Emulated "ide killer". Prevents long KS boot delay if no drives installed */
if (!ide_isdrive (idedrive[0]) && !ide_isdrive (idedrive[1]) && !ide_isdrive (idedrive[2]) && !ide_isdrive (idedrive[3])) {
if (ide_reg == IDE_STATUS)
return 0x7f;
return 0xff;
}
return ide_read_reg (ide, ide_reg);
}
static void gayle_write2 (uaecptr addr, uae_u32 val)
{
struct ide_hdf *ide = NULL;
int ide_reg;
if ((GAYLE_LOG > 3 && (addr != 0x2000 && addr != 0x2001 && addr != 0x3020 && addr != 0x3021 && addr != GAYLE_IRQ_1200)) || GAYLE_LOG > 5)
write_log (_T("IDE_WRITE %08X=%02X PC=%X\n"), addr, (uae_u32)val & 0xff, M68K_GETPC);
if (currprefs.cs_ide <= 0)
return;
if (currprefs.cs_ide == IDE_A600A1200) {
if (addr == GAYLE_IRQ_1200) {
write_gayle_irq (val);
return;
}
if (addr == GAYLE_INT_1200) {
write_gayle_int (val);
return;
}
}
if (addr >= 0x4000)
return;
ide_reg = get_gayle_ide_reg (addr, &ide);
ide_write_reg (ide, ide_reg, val);
}
static int gayle_read (uaecptr addr)
{
uaecptr oaddr = addr;
uae_u32 v = 0;
int got = 0;
if (currprefs.cs_ide == IDE_A600A1200) {
if ((addr & 0xA0000) != 0xA0000)
return 0;
}
addr &= 0xffff;
if (currprefs.cs_pcmcia) {
if (currprefs.cs_ide != IDE_A600A1200) {
if (addr == GAYLE_IRQ_1200) {
v = read_gayle_irq ();
got = 1;
} else if (addr == GAYLE_INT_1200) {
v = read_gayle_int ();
got = 1;
}
}
if (addr == GAYLE_CS_1200) {
v = read_gayle_cs ();
got = 1;
if (PCMCIA_LOG)
write_log (_T("PCMCIA STATUS READ %08X=%02X PC=%08X\n"), oaddr, (uae_u32)v & 0xff, M68K_GETPC);
} else if (addr == GAYLE_CFG_1200) {
v = read_gayle_cfg ();
got = 1;
if (PCMCIA_LOG)
write_log (_T("PCMCIA CONFIG READ %08X=%02X PC=%08X\n"), oaddr, (uae_u32)v & 0xff, M68K_GETPC);
}
}
if (!got)
v = gayle_read2 (addr);
if (GAYLE_LOG)
write_log (_T("GAYLE_READ %08X=%02X PC=%08X\n"), oaddr, (uae_u32)v & 0xff, M68K_GETPC);
return v;
}
static void gayle_write (uaecptr addr, int val)
{
uaecptr oaddr = addr;
int got = 0;
if (currprefs.cs_ide == IDE_A600A1200) {
if ((addr & 0xA0000) != 0xA0000)
return;
}
addr &= 0xffff;
if (currprefs.cs_pcmcia) {
if (currprefs.cs_ide != IDE_A600A1200) {
if (addr == GAYLE_IRQ_1200) {
write_gayle_irq (val);
got = 1;
} else if (addr == GAYLE_INT_1200) {
write_gayle_int (val);
got = 1;
}
}
if (addr == GAYLE_CS_1200) {
write_gayle_cs (val);
got = 1;
if (PCMCIA_LOG > 1)
write_log (_T("PCMCIA STATUS WRITE %08X=%02X PC=%08X\n"), oaddr, (uae_u32)val & 0xff, M68K_GETPC);
} else if (addr == GAYLE_CFG_1200) {
write_gayle_cfg (val);
got = 1;
if (PCMCIA_LOG > 1)
write_log (_T("PCMCIA CONFIG WRITE %08X=%02X PC=%08X\n"), oaddr, (uae_u32)val & 0xff, M68K_GETPC);
}
}
if (GAYLE_LOG)
write_log (_T("GAYLE_WRITE %08X=%02X PC=%08X\n"), oaddr, (uae_u32)val & 0xff, M68K_GETPC);
if (!got)
gayle_write2 (addr, val);
}
DECLARE_MEMORY_FUNCTIONS(gayle);
addrbank gayle_bank = {
gayle_lget, gayle_wget, gayle_bget,
gayle_lput, gayle_wput, gayle_bput,
default_xlate, default_check, NULL, NULL, _T("Gayle (low)"),
dummy_lgeti, dummy_wgeti,
ABFLAG_IO, S_READ, S_WRITE
};
void gayle_dataflyer_enable(bool enable)
{
if (!enable) {
dataflyer_state = 0;
dataflyer_disable_irq = 0;
return;
}
dataflyer_state = 1;
}
static bool isdataflyerscsiplus(uaecptr addr, uae_u32 *v, int size)
{
if (!dataflyer_state)
return false;
uaecptr addrmask = addr & 0xffff;
if (addrmask >= GAYLE_IRQ_4000 && addrmask <= GAYLE_IRQ_4000 + 1 && currprefs.cs_ide == IDE_A4000)
return false;
uaecptr addrbase = (addr & ~0xff) & ~0x1020;
int reg = ((addr & 0xffff) & ~0x2020) >> 2;
if (reg >= IDE_SECONDARY) {
reg &= ~IDE_SECONDARY;
if (reg >= 6) // normal IDE registers
return false;
if (size < 0) {
switch (reg)
{
case 0: // 53C80 fake dma port
soft_scsi_put(addrbase | 8, 1, *v);
break;
case 3:
dataflyer_byte = *v;
break;
}
} else {
switch (reg)
{
case 0: // 53C80 fake dma port
*v = soft_scsi_get(addrbase | 8, 1);
break;
case 3:
*v = 0;
if (ide_irq_check(idedrive[0], false))
*v = dataflyer_byte;
break;
case 4: // select SCSI
dataflyer_disable_irq = 1;
dataflyer_state |= 2;
break;
case 5: // select IDE
dataflyer_disable_irq = 1;
dataflyer_state &= ~2;
break;
}
}
#if 0
if (size < 0)
write_log(_T("SECONDARY BASE PUT(%d) %08x %08x PC=%08x\n"), -size, addr, *v, M68K_GETPC);
else
write_log(_T("SECONDARY BASE GET(%d) %08x PC=%08x\n"), size, addr, M68K_GETPC);
#endif
return true;
}
if (!(dataflyer_state & 2))
return false;
if (size < 0)
soft_scsi_put(addrbase | reg, -size, *v);
else
*v = soft_scsi_get(addrbase | reg, size);
return true;
}
static bool isa4000t (uaecptr *paddr)
{
if (!is_a4000t_scsi())
return false;
uaecptr addr = *paddr;
if ((addr & 0xffff) >= (GAYLE_BASE_4000 & 0xffff))
return false;
addr &= 0xff;
*paddr = addr;
return true;
}
static uae_u32 REGPARAM2 gayle_lget (uaecptr addr)
{
struct ide_hdf *ide = NULL;
int ide_reg;
uae_u32 v;
#ifdef NCR
if (is_a4000t_scsi() && (addr & 0xffff) == 0x3000)
return 0xffffffff; // NCR DIP BANK
if (isdataflyerscsiplus(addr, &v, 4)) {
return v;
}
if (isa4000t (&addr)) {
if (addr >= NCR_ALT_OFFSET) {
addr &= NCR_MASK;
v = (ncr710_io_bget_a4000t(addr + 3) << 0) | (ncr710_io_bget_a4000t(addr + 2) << 8) |
(ncr710_io_bget_a4000t(addr + 1) << 16) | (ncr710_io_bget_a4000t(addr + 0) << 24);
} else if (addr >= NCR_OFFSET) {
addr &= NCR_MASK;
v = (ncr710_io_bget_a4000t(addr + 3) << 0) | (ncr710_io_bget_a4000t(addr + 2) << 8) |
(ncr710_io_bget_a4000t(addr + 1) << 16) | (ncr710_io_bget_a4000t(addr + 0) << 24);
}
return v;
}
#endif
ide_reg = get_gayle_ide_reg (addr, &ide);
if (ide_reg == IDE_DATA) {
v = ide_get_data (ide) << 16;
v |= ide_get_data (ide);
if (GAYLE_LOG > 4)
write_log(_T("IDE_DATA_LONG %08X=%08X PC=%X\n"), addr, v, M68K_GETPC);
return v;
}
v = gayle_wget (addr) << 16;
v |= gayle_wget (addr + 2);
return v;
}
static uae_u32 REGPARAM2 gayle_wget (uaecptr addr)
{
struct ide_hdf *ide = NULL;
int ide_reg;
uae_u32 v;
#ifdef NCR
if (is_a4000t_scsi() && (addr & (0xffff - 1)) == 0x3000)
return 0xffff; // NCR DIP BANK
if (isdataflyerscsiplus(addr, &v, 2)) {
return v;
}
if (isa4000t(&addr)) {
if (addr >= NCR_OFFSET) {
addr &= NCR_MASK;
v = (ncr710_io_bget_a4000t(addr) << 8) | ncr710_io_bget_a4000t(addr + 1);
}
return v;
}
#endif
ide_reg = get_gayle_ide_reg (addr, &ide);
if (ide_reg == IDE_DATA) {
v = ide_get_data (ide);
if (GAYLE_LOG > 4)
write_log(_T("IDE_DATA_WORD %08X=%04X PC=%X\n"), addr, v & 0xffff, M68K_GETPC);
return v;
}
v = gayle_bget (addr) << 8;
v |= gayle_bget (addr + 1);
return v;
}
static uae_u32 REGPARAM2 gayle_bget (uaecptr addr)
{
uae_u32 v;
#ifdef NCR
if (is_a4000t_scsi() && (addr & (0xffff - 3)) == 0x3000)
return 0xff; // NCR DIP BANK
if (isdataflyerscsiplus(addr, &v, 1)) {
return v;
}
if (isa4000t(&addr)) {
if (addr >= NCR_OFFSET) {
addr &= NCR_MASK;
return ncr710_io_bget_a4000t(addr);
}
return 0;
}
#endif
v = gayle_read (addr);
return v;
}
static void REGPARAM2 gayle_lput (uaecptr addr, uae_u32 value)
{
struct ide_hdf *ide = NULL;
int ide_reg;
if (isdataflyerscsiplus(addr, &value, -4)) {
return;
}
if (isa4000t(&addr)) {
if (addr >= NCR_ALT_OFFSET) {
addr &= NCR_MASK;
ncr710_io_bput_a4000t(addr + 3, value >> 0);
ncr710_io_bput_a4000t(addr + 2, value >> 8);
ncr710_io_bput_a4000t(addr + 1, value >> 16);
ncr710_io_bput_a4000t(addr + 0, value >> 24);
} else if (addr >= NCR_OFFSET) {
addr &= NCR_MASK;
ncr710_io_bput_a4000t(addr + 3, value >> 0);
ncr710_io_bput_a4000t(addr + 2, value >> 8);
ncr710_io_bput_a4000t(addr + 1, value >> 16);
ncr710_io_bput_a4000t(addr + 0, value >> 24);
}
return;
}
ide_reg = get_gayle_ide_reg (addr, &ide);
if (ide_reg == IDE_DATA) {
ide_put_data (ide, value >> 16);
ide_put_data (ide, value & 0xffff);
return;
}
gayle_wput (addr, value >> 16);
gayle_wput (addr + 2, value & 0xffff);
}
static void REGPARAM2 gayle_wput (uaecptr addr, uae_u32 value)
{
struct ide_hdf *ide = NULL;
int ide_reg;
#ifdef NCR
if (isdataflyerscsiplus(addr, &value, -2)) {
return;
}
if (isa4000t(&addr)) {
if (addr >= NCR_OFFSET) {
addr &= NCR_MASK;
ncr710_io_bput_a4000t(addr, value >> 8);
ncr710_io_bput_a4000t(addr + 1, value);
}
return;
}
#endif
ide_reg = get_gayle_ide_reg (addr, &ide);
if (ide_reg == IDE_DATA) {
ide_put_data (ide, value);
return;
}
gayle_bput (addr, value >> 8);
gayle_bput (addr + 1, value & 0xff);
}
static void REGPARAM2 gayle_bput (uaecptr addr, uae_u32 value)
{
#ifdef NCR
if (isdataflyerscsiplus(addr, &value, -1)) {
return;
}
if (isa4000t(&addr)) {
if (addr >= NCR_OFFSET) {
addr &= NCR_MASK;
ncr710_io_bput_a4000t(addr, value);
}
return;
}
#endif
gayle_write (addr, value);
}
static void gayle2_write (uaecptr addr, uae_u32 v)
{
gayle_id_cnt = 0;
}
static uae_u32 gayle2_read (uaecptr addr)
{
uae_u8 v = 0;
addr &= 0xffff;
if (addr == 0x1000) {
/* Gayle ID. Gayle = 0xd0. AA Gayle = 0xd1 */
if (gayle_id_cnt == 0 || gayle_id_cnt == 1 || gayle_id_cnt == 3 || ((currprefs.chipset_mask & CSMASK_AGA) && gayle_id_cnt == 7) ||
(currprefs.cs_cd32cd && !currprefs.cs_ide && !currprefs.cs_pcmcia && gayle_id_cnt == 2))
v = 0x80;
else
v = 0x00;
gayle_id_cnt++;
}
return v;
}
DECLARE_MEMORY_FUNCTIONS(gayle2);
addrbank gayle2_bank = {
gayle2_lget, gayle2_wget, gayle2_bget,
gayle2_lput, gayle2_wput, gayle2_bput,
default_xlate, default_check, NULL, NULL, _T("Gayle (high)"),
dummy_lgeti, dummy_wgeti,
ABFLAG_IO, S_READ, S_WRITE
};
static uae_u32 REGPARAM2 gayle2_lget (uaecptr addr)
{
uae_u32 v;
v = gayle2_wget (addr) << 16;
v |= gayle2_wget (addr + 2);
return v;
}
static uae_u32 REGPARAM2 gayle2_wget (uaecptr addr)
{
uae_u16 v;
v = gayle2_bget (addr) << 8;
v |= gayle2_bget (addr + 1);
return v;
}
static uae_u32 REGPARAM2 gayle2_bget (uaecptr addr)
{
return gayle2_read (addr);
}
static void REGPARAM2 gayle2_lput (uaecptr addr, uae_u32 value)
{
gayle2_wput (addr, value >> 16);
gayle2_wput (addr + 2, value & 0xffff);
}
static void REGPARAM2 gayle2_wput (uaecptr addr, uae_u32 value)
{
gayle2_bput (addr, value >> 8);
gayle2_bput (addr + 1, value & 0xff);
}
static void REGPARAM2 gayle2_bput (uaecptr addr, uae_u32 value)
{
gayle2_write (addr, value);
}
static uae_u8 ramsey_config;
static int gary_coldboot;
int gary_timeout;
int gary_toenb;
static void mbres_write (uaecptr addr, uae_u32 val, int size)
{
addr &= 0xffff;
if (MBRES_LOG > 0)
write_log (_T("MBRES_WRITE %08X=%08X (%d) PC=%08X S=%d\n"), addr, val, size, M68K_GETPC, regs.s);
if (addr < 0x8000) {
uae_u32 addr2 = addr & 3;
uae_u32 addr64 = (addr >> 6) & 3;
if (addr64 == 0 && addr2 == 0x03)
ramsey_config = val;
if (addr2 == 0x02)
gary_coldboot = (val & 0x80) ? 1 : 0;
if (addr2 == 0x01)
gary_toenb = (val & 0x80) ? 1 : 0;
if (addr2 == 0x00)
gary_timeout = (val & 0x80) ? 1 : 0;
}
}
static uae_u32 mbres_read (uaecptr addr, int size)
{
uae_u32 v = 0;
addr &= 0xffff;
uae_u32 addr2 = addr & 3;
uae_u32 addr64 = (addr >> 6) & 3;
for (;;) {
if (addr64 == 1 && addr2 == 0x03) { /* RAMSEY revision */
if (currprefs.cs_ramseyrev >= 0)
v = currprefs.cs_ramseyrev;
break;
}
if (addr64 == 0 && addr2 == 0x03) { /* RAMSEY config */
if (currprefs.cs_ramseyrev >= 0)
v = ramsey_config;
break;
}
if (addr2 == 0x03) {
v = 0xff;
break;
}
if (addr2 == 0x02) { /* coldreboot flag */
if (currprefs.cs_fatgaryrev >= 0)
v = gary_coldboot ? 0x80 : 0x00;
}
if (addr2 == 0x01) { /* toenb flag */
if (currprefs.cs_fatgaryrev >= 0)
v = gary_toenb ? 0x80 : 0x00;
}
if (addr2 == 0x00) { /* timeout flag */
if (currprefs.cs_fatgaryrev >= 0)
v = gary_timeout ? 0x80 : 0x00;
}
v |= 0x7f;
break;
}
if (MBRES_LOG > 0)
write_log (_T("MBRES_READ %08X=%08X (%d) PC=%08X S=%d\n"), addr, v, size, M68K_GETPC, regs.s);
return v;
}
static uae_u32 REGPARAM3 mbres_lget (uaecptr) REGPARAM;
static uae_u32 REGPARAM3 mbres_wget (uaecptr) REGPARAM;
static uae_u32 REGPARAM3 mbres_bget (uaecptr) REGPARAM;
static void REGPARAM3 mbres_lput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 mbres_wput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 mbres_bput (uaecptr, uae_u32) REGPARAM;
static uae_u32 REGPARAM2 mbres_lget (uaecptr addr)
{
uae_u32 v;
v = mbres_wget (addr) << 16;
v |= mbres_wget (addr + 2);
return v;
}
static uae_u32 REGPARAM2 mbres_wget (uaecptr addr)
{
return mbres_read (addr, 2);
}
static uae_u32 REGPARAM2 mbres_bget (uaecptr addr)
{
return mbres_read (addr, 1);
}
static void REGPARAM2 mbres_lput (uaecptr addr, uae_u32 value)
{
mbres_wput (addr, value >> 16);
mbres_wput (addr + 2, value & 0xffff);
}
static void REGPARAM2 mbres_wput (uaecptr addr, uae_u32 value)
{
mbres_write (addr, value, 2);
}
static void REGPARAM2 mbres_bput (uaecptr addr, uae_u32 value)
{
mbres_write (addr, value, 1);
}
static addrbank mbres_sub_bank = {
mbres_lget, mbres_wget, mbres_bget,
mbres_lput, mbres_wput, mbres_bput,
default_xlate, default_check, NULL, NULL, _T("Motherboard Resources"),
dummy_lgeti, dummy_wgeti,
ABFLAG_IO, S_READ, S_WRITE
};
static struct addrbank_sub mbres_sub_banks[] = {
{ &mbres_sub_bank, 0x0000 },
{ &dummy_bank, 0x8000 },
{ NULL }
};
addrbank mbres_bank = {
sub_bank_lget, sub_bank_wget, sub_bank_bget,
sub_bank_lput, sub_bank_wput, sub_bank_bput,
sub_bank_xlate, sub_bank_check, NULL, NULL, _T("Motherboard Resources"),
sub_bank_lgeti, sub_bank_wgeti,
ABFLAG_IO, S_READ, S_WRITE, mbres_sub_banks
};
static int pcmcia_common_size, pcmcia_attrs_size, pcmcia_attrs_full;
static uae_u8 *pcmcia_common;
static uae_u8 *pcmcia_attrs;
static int pcmcia_write_min, pcmcia_write_max;
static uae_u16 pcmcia_idedata;
static const struct pci_board *ne2000;
static struct pci_board_state *ne2000_board_state;