Update of /cvsroot/gc-linux/linux/drivers/block/gcn-di
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10355
Modified Files:
Makefile gcn-di.c
Added Files:
drive_all.S
Removed Files:
drive_20020402.asm
Log Message:
Added (untested) support for drive 06 and 08 too.
--- NEW FILE: drive_all.S ---
/*
* DVD-R compatible "cactus" firmware extensions
* Copyright (C) 2005 The GameCube Linux Team
* Copyright (C) 2005 Albert Herranz
*
* Based on analysis of Cobra 1.0 drive code released by tmbinc on dextrose.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
/*
* This code is compatible with binutils 2.15 limited mn10200 support.
*
*/
.equ NMICR, 0xfc40
.equ UNICR, 0xfc44
.equ UNID, (1<<0)
.equ ADB0, 0xfcd2
.equ ADB1, 0xfcd6
.equ ADBCTL, 0xfcda
.equ ADB0CK, (1<<0)
.equ ADB1CK, (1<<1)
.equ ADB0ON, (1<<2)
.equ ADB1ON, (1<<3)
.equ irq_handler_vector, 0x804c /* 04, 06, 08 */
.equ irq_depth, 0x805b /* 04, 06, 08 */
#if DRIVE_MODEL == 0x20020402 /* 04 */
.equ dicmdbuf0, 0x80b4
.equ entry_return_address, 0x08d47e
.equ data1, 0x008000
.equ data1_size, 0x6e
.equ data1_copy_from, 0x08ea2a
.equ bss, 0x00806e
.equ bss_size, 0x1b8
.equ cactus, 0x40ecf9
.equ bert, 0x8084
.equ ernie, 0x819c
.section absolute
.org 0x0808aa /* 04, 06, 08 */
initialize_drive:
.org 0x082f27 /* 04, 08 */
memcpy:
.org 0x082f49 /* 04, 08 */
memset:
.equ adb1_break_address, 0x08a7db
.org 0x08a88d
adb1_fixup_exit:
.equ adb0_break_address, 0x08ae28
.org 0x08ae33
adb0_fixup_exit:
.equ disable_extensions_when_called_from, 0x0885c1 /* 04, 08 */
#elif DRIVE_MODEL == 0x20010608 /* 06 */
.equ dicmdbuf0, 0x80a8
.equ entry_return_address, 0x08d41e
.equ data1, 0x008000
.equ data1_size, 0x6e
.equ data1_copy_from, 0x08e9c8
.equ bss, 0x00806e
.equ bss_size, 0x1ac
.equ cactus, 0x40ed02
.equ bert, 0x8078
.equ ernie, 0x8190
.section absolute
.org 0x0808aa /* 04, 06, 08 */
initialize_drive:
.org 0x082f2e
memcpy:
.org 0x082f50
memset:
.equ adb1_break_address, 0x08aaf0
.org 0x08aba2
adb1_fixup_exit:
.equ adb0_break_address, 0x08b145
.org 0x08b150
adb0_fixup_exit:
.equ disable_extensions_when_called_from, 0x0885b9
#elif DRIVE_MODEL == 0x20020823 /* 08 */
.equ dicmdbuf0, 0x80b0
.equ entry_return_address, 0x08d4d9
.equ data1, 0x008000
.equ data1_size, 0x6e
.equ data1_copy_from, 0x08ea7c
.equ bss, 0x00806e
.equ bss_size, 0x1b6
.equ cactus, 0x40ecf5
.equ bert, 0x8080
.equ ernie, 0x8198
.section absolute
.org 0x0808aa /* 04, 06, 08 */
initialize_drive:
.org 0x082f27 /* 04, 08 */
memcpy:
.org 0x082f49 /* 04, 08 */
memset:
.equ adb1_break_address, 0x08a828
.org 0x08a8da
adb1_fixup_exit:
.equ adb0_break_address, 0x08ae75
.org 0x08ae80
adb0_fixup_exit:
.equ disable_extensions_when_called_from, 0x0885c1 /* 04, 08 */
#else
#error Sorry, unsupported drive.
#endif
.section .text
.global _start
.global _exit
/*
* Our entry point is a bit special. We start executing for the first time
* from the interrupt handler.
*/
_start:
_main:
/*
* We reinitialize the hardware here, just like the firmware does.
*/
jsr initialize_drive
/* relocate initialized data */
mov data1, a0
mov data1_copy_from, d1
mov data1_size, d0
jsr memcpy
/* zero out the bss */
mov bss, a0
sub d0, d0
mov bss_size, d0
jsr memset
/* replace the current irq handler with ours */
mov our_irq_handler, a0
mov a0, (irq_handler_vector)
/* setup our extending functions ... */
mov adb1_break_address, a0
mov a0, (ADB1)
mov adb0_break_address, a0
mov a0, (ADB0)
/* ... and enable them */
mov ADB1ON|ADB0ON, d0
movb d0, (ADBCTL)
mov entry_return_address, a0
jmp (a0)
our_irq_handler:
/* check for Address Break 0 */
mov (ADBCTL), d0
and ADB0CK, d0
bne adb0_break_handler
/* check for Address Break 1 */
mov (ADBCTL), d0
and ADB1CK, d0
bne adb1_break_handler
/* tell the drive to please accept the disk */
mov cactus, a0
mov 2, d0
bset d0, (a0)
/* this seems to avoid errors if the drive idles for too long */
mov (bert), d0
mov d0, (ernie)
/* call the original handler */
mov (saved_irq_handler), a0
jsr (a0)
rts
/*
* This is how the stacks look like when our interrupt handler is called.
*
* Our interrupt handler is in fact not the real interrupt handler, but
* just a subroutine called by the real interrupt handler.
* That's why we just RTS and not RTI from our interrupt handler.
*
* | | | |
* 00| d0 0| <- old a3 | |
* 02| 8| | |
* 04| d1 6| | |
* 06| 4| | |
* 08| d2 2| | |
* 0a| 0| | |
* 0c| d3 8| | |
* 0e| 6| | |
* 10| a0 4| | |
* 12| 2| | |
* 14| a1 0| | |
* 16| 8| | |
* 18| a2 6| | |
* 1a| 4| | |
* 1c| MDR 2| | |
* 1e| PSW | | |
* 20| PC lo | | PC lo | <- a3
* 22| PC hi | | PC hi |
* : : | old a3 |
* | ... | | |
* +--------+ +--------+ <- (0x8ea1c) for drive 04
* normal context stack interrupt context stack
*
*/
adb0_break_handler:
/* ack the interrupt */
movbu (ADBCTL), d0
and ~ADB0CK, d0
movb d0, (ADBCTL)
movbu (UNICR), d0
and ~UNID, d0
movb d0, (UNICR)
/* point to the previous stack pointer */
mov a3, a0
add 4, a0
/*
* Special case. When entering interrupt context the first time,
* the old stack is pushed in the interrupt stack before calling us.
*/
movbu (irq_depth), d0
cmp 1, d0
bne 1f
mov (4, a3), a0 /* get the old stack pointer */
1:
/* overwrite the original return address (look at the stack layout) */
mov adb0_fixup, a1
mov a1, (0x20, a0)
/*
* We disable the extensions when an original disc is found.
*
* We do that by checking if we were called from a piece of
* code reached only when original discs are inserted. Tricky.
*/
/* 0x20 + 0x10 + 0x04 = 0x34 */
mov (0x34, a0), a1
cmp disable_extensions_when_called_from, a1
bne 1f
di_disable_extensions:
mov disable_extensions, a1
mov 1, d0
movb d0, (a1)
movbu (ADBCTL), d0
and ~ADB1ON, d0
movb d0, (ADBCTL)
1:
rts
adb0_fixup:
/* disable interrupts */
and 0xf7ff, psw
/* deal with the dvd seed */
mov (a0), d1
cmp 0x00f000, d1
bne 1f
mov 0x00, d0
movbu (disable_extensions), d1
cmp 0, d1
bne 1f
movb d0, (0x09, a0)
1:
/* skip the extra field */
mov (a0), d1
cmp 0x06, d1
bne 1f
mov (0x06, a0), d1
movbu (disable_extensions), d0
cmp 0, d0
bne 2f
add 6, d1
2:
mov d1, (0x06, a0)
1:
jmp adb0_fixup_exit
adb1_break_handler:
/* ack the interrupt */
movbu (ADBCTL), d0
and ~ADB1CK, d0
movb d0, (ADBCTL)
movbu (UNICR), d0
and ~UNID, d0
movb d0, (UNICR)
/* point to the previous stack pointer */
mov a3, a0
add 4, a0
/*
* Special case. When entering interrupt context the first time,
* the old stack is pushed in the interrupt stack before calling us.
*/
movbu (irq_depth), d0
cmp 1, d0
bne 1f
mov (4, a3), a0 /* get the old stack pointer */
1:
/* overwrite the original return address (look at the stack layout) */
mov adb1_fixup, a1
mov a1, (0x20, a0)
rts
adb1_fixup:
/* no disk id */
sub d0, d0
jmp adb1_fixup_exit
.align 2
saved_irq_handler:
.long 0x00080A74 /* 04, 06, 08 */
disable_extensions:
.byte 0x00
_exit:
Index: Makefile
===================================================================
RCS file: /cvsroot/gc-linux/linux/drivers/block/gcn-di/Makefile,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Makefile 14 May 2005 21:40:12 -0000 1.1
+++ Makefile 17 May 2005 20:08:38 -0000 1.2
@@ -1,8 +1,10 @@
obj-$(CONFIG_GAMECUBE_DI) += gcn-di.o
-$(obj)/gcn-di.o: $(obj)/drive_20020402.h
+$(obj)/gcn-di.o: $(obj)/drive_20020402.h \
+ $(obj)/drive_20010608.h \
+ $(obj)/drive_20020823.h
-#CONFIG_GAMECUBE_DI_BUILD_FIRMWARE=y
+CONFIG_GAMECUBE_DI_BUILD_FIRMWARE=y
ifeq ($(CONFIG_GAMECUBE_DI_BUILD_FIRMWARE),y)
@@ -12,17 +14,29 @@
quiet_cmd_build_difw = BLD FW $@
cmd_build_difw = \
- $(ASMN102) -o $(obj)/$(<F).o $<; \
+ $(CPP) -DDRIVE_MODEL=$(DRIVE_MODEL) $< > $(obj)/$(@F).s; \
+ $(ASMN102) -o $(obj)/$(@F).o $(obj)/$(@F).s; \
$(LDMN102) --section-start absolute=0 -Ttext=0x40d000 \
- -o $(obj)/$(<F).elf -e 0x40d000 $(obj)/$(<F).o; \
- $(OCMN102) -I elf32-mn10200 -O binary $(obj)/$(<F).elf \
- $(obj)/$(<F).bin; \
- (echo "static "; cat $(obj)/$(<F).bin | scripts/bin2c "$(subst .asm,,$(<F))_firmware") > $@; \
- rm -f $(obj)/$(<F).o $(obj)/$(<F).elf $(obj)/$(<F).bin
+ -o $(obj)/$(@F).elf -e 0x40d000 $(obj)/$(@F).o; \
+ $(OCMN102) -I elf32-mn10200 -O binary $(obj)/$(@F).elf \
+ $(obj)/$(@F).bin; \
+ (echo "static "; cat $(obj)/$(@F).bin | scripts/bin2c "$(subst .h,,$(@F))_firmware") > $@; \
+ rm -f $(obj)/$(@F).o $(obj)/$(@F).elf $(obj)/$(@F).bin $(obj)/$(@F).s
targets += drive_20020402.h
-$(obj)/drive_20020402.h: $(src)/drive_20020402.asm FORCE
+$(obj)/drive_20020402.h: DRIVE_MODEL := 0x20020402
+$(obj)/drive_20020402.h: $(src)/drive_all.S FORCE
+ $(call if_changed,build_difw)
+
+targets += drive_20010608.h
+$(obj)/drive_20010608.h: DRIVE_MODEL := 0x20010608
+$(obj)/drive_20010608.h: $(src)/drive_all.S FORCE
+ $(call if_changed,build_difw)
+
+targets += drive_20020823.h
+$(obj)/drive_20020823.h: DRIVE_MODEL := 0x20020823
+$(obj)/drive_20020823.h: $(src)/drive_all.S FORCE
$(call if_changed,build_difw)
endif
Index: gcn-di.c
===================================================================
RCS file: /cvsroot/gc-linux/linux/drivers/block/gcn-di/gcn-di.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- gcn-di.c 14 May 2005 21:40:12 -0000 1.1
+++ gcn-di.c 17 May 2005 20:08:38 -0000 1.2
@@ -249,13 +249,29 @@
* Drive 06 (XXX) firmware extensions.
*/
-/* XXX TODO */
+#include "drive_20010608.h"
+
+static struct di_drive_code drive_20010608[] = {
+ [0] = {
+ .address = DI_DRIVE_CODE_BASE,
+ .len = sizeof(drive_20010608_firmware),
+ .code = (u8 *)drive_20010608_firmware,
+ },
+};
/*
- * Drive 08 (XXX) firmware extensions.
+ * Drive 08 (20020823) firmware extensions.
*/
-/* XXX TODO */
+#include "drive_20020823.h"
+
+static struct di_drive_code drive_20020823[] = {
+ [0] = {
+ .address = DI_DRIVE_CODE_BASE,
+ .len = sizeof(drive_20020823_firmware),
+ .code = (u8 *)drive_20020823_firmware,
+ },
+};
/*
@@ -879,6 +895,18 @@
di_patch(ddev, &generic_drive_code_trigger, 1);
ddev->flags |= DI_INTEROPERABLE;
break;
+ case 0x20010608:
+ di_patch(ddev, drive_20010608,
+ ARRAY_SIZE(drive_20010608));
+ di_patch(ddev, &generic_drive_code_trigger, 1);
+ ddev->flags |= DI_INTEROPERABLE;
+ break;
+ case 0x20020823:
+ di_patch(ddev, drive_20020823,
+ ARRAY_SIZE(drive_20020823));
+ di_patch(ddev, &generic_drive_code_trigger, 1);
+ ddev->flags |= DI_INTEROPERABLE;
+ break;
default:
di_printk(KERN_ERR, "sorry, drive %x is not yet"
" supported\n",
--- drive_20020402.asm DELETED ---
|