aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@trantor.hos.anvin.org>2010-09-23 22:48:11 -0700
committerH. Peter Anvin <hpa@trantor.hos.anvin.org>2010-09-23 22:48:11 -0700
commit3a29ee93f85ed1964bb660f75ce3b8e0e2010d36 (patch)
tree4a2f99bf351bbb8a72f2e99cc9d0caa2a51aa2d9
parent7422dcf5fa1680f1156bd5c5404ac6423c239071 (diff)
downloadabc80-3a29ee93f85ed1964bb660f75ce3b8e0e2010d36.tar.gz
abc80-3a29ee93f85ed1964bb660f75ce3b8e0e2010d36.tar.xz
abc80-3a29ee93f85ed1964bb660f75ce3b8e0e2010d36.zip
Make it possible to change the SD controller unit mapping
A modern SD card generally will be way larger than 64 MB or 128 MB (the most that UFD-DOS and the controller interface can handle, respectively.) This adds a nonstandard controller command to reprogram the unit map to allow for up to 256 units instead of 8. This is expected to be useful when we have an ABC800 model, to be able to have the ABC80 and ABC800 system disk each as HD0: on the same card.
-rw-r--r--abc80.qsf1
-rw-r--r--data/sddrom.asm155
-rw-r--r--sddisk.v13
3 files changed, 128 insertions, 41 deletions
diff --git a/abc80.qsf b/abc80.qsf
index 399eb12..d798fad 100644
--- a/abc80.qsf
+++ b/abc80.qsf
@@ -540,7 +540,6 @@ set_instance_assignment -name CLOCK_SETTINGS clock_24 -to clock_24[1]
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
-set_global_assignment -name USE_CONFIGURATION_DEVICE ON
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name USE_SIGNALTAP_FILE stp6.stp
diff --git a/data/sddrom.asm b/data/sddrom.asm
index 0db9040..d6d79af 100644
--- a/data/sddrom.asm
+++ b/data/sddrom.asm
@@ -36,6 +36,12 @@ sect_arg: equ 0x8014 ; Sector number as argument
card_ocr: equ 0x8018 ; Bit 30 is the SDHC flag
init_arg: equ 0x801c ; Normally zero but modified by sd_init
clear_size: equ 0x20
+
+ ; Table of unit addresses
+unit_table: equ 0x8020 ; Must not cross a 256-byte boundary
+unit_table_l: equ 0x20 ; Low byte of unit_table
+unit_table_h: equ 0x80 ; High byte of unit_table
+
stack: equ 0x8200 ; Base of stack
ram_size: equ 2048
@@ -97,16 +103,6 @@ interrupt_reset:
ei
jr idle
-reset_1:
- ld hl,sysinfo
- push hl
- pop iy
- ld de,sysinfo+1
- ld bc,clear_size-1 ; Size of data area
- ld (hl),l ; Zero
- ldir ; Clear the data area
- rst 56 ; = interrupt
-
defs 0x0066-$
;:
; NMI handing -- we receive an NMI when the SD card is removed. Allow
@@ -134,6 +130,33 @@ nmi_wait_card:
rst 0 ; Reset everything
+;
+; Second half of the reset operation
+;
+reset_1:
+ ld hl,sysinfo
+ push hl
+ pop iy
+ ld de,sysinfo+1
+ ld bc,clear_size-1 ; Size of data area
+ ld (hl),l ; Zero
+ ldir ; Clear the data area
+
+ in a,(0x00)
+ bit 4,a ; Is this a hard reset?
+ jr z,reset_2
+
+ ld de,unit_table
+ ld hl,init_unit_table
+ ld bc,8*2
+ ldir
+
+reset_2:
+ rst 56 ; = interrupt
+
+;
+; Start of a command
+;
idle: ; Resume here to begin command
ld e,0
idle_err: ; Errcode in E
@@ -222,9 +245,9 @@ not_sector_host:
call transfer
not_sector_controller:
- ;:
+ ;
; WRITE SECTOR command
- ;:
+ ;
bit 3,(iy+0)
jr z,not_write_sector
@@ -249,6 +272,50 @@ not_sector_controller:
not_write_sector:
;
+ ; SPECIAL COMMAND command
+ ;
+ bit 4,(iy+0)
+ jr z,not_special_command
+
+ ; Set unit special command?
+ ld a,(iy+1)
+ ld d,a
+ or 0x07
+ inc a
+ jr nz,not_special_command
+
+ ld a,d
+ and 0x07
+ add a
+ ld ixl,a
+ ld ixh,unit_table_h
+
+ ld e,(iy+3) ; Sector = new unit number
+ ld d,0
+ ld l,e
+ ld h,d
+
+ ; Multiply with 119 (238/2*256 SD sectors per 256-sector track)
+ ld b,4
+ add hl,hl ; *2
+ add hl,hl ; *4
+ add hl,hl ; *8
+ add hl,hl ; *16
+ add hl,de ; *17
+ ld e,l
+ ld h,d
+ add hl,hl ; *34
+ add hl,hl ; *68
+ add hl,hl ; *136
+ ld a,l ; -17 -> 119
+ sub e
+ ld (ix+unit_table_l),a
+ ld a,h
+ sbc a,d
+ ld (ix+unit_table_l+1),a
+
+not_special_command:
+ ;
; All other commands ignored
;
jp idle
@@ -299,58 +366,57 @@ tr_wait:
jr tr_wait
;:
-; This routine converts the command contents to a SD sector number,
-; and loads it if it is not currently loaded.
+; This routine converts the command contents to a SD (512-byte)
+; sector number, and loads it if it is not currently loaded.
;
load_buffer:
; Initialize buffer addresses
xor a
- ld (iy+10),a
+ ld e,a ; Seek error
ld (iy+11),a
+ ; Compute unit number -> SD sector bytes [2:1]
+ ld a,(iy+1) ; K1 = unit + more
+ and 0x07 ; Unit number
+ add a ; *2
+ add unit_table_l
+ ld l,a
+ ld h,unit_table_h ; -> unit_table(unit number)
+ ; (HL) is now the base for the unit bytes [2:1]
+
; Get track
- ld e,a ; Seek error
ld a,(iy+2)
cp 238 ; 238 tracks/volume
ccf
ret c ; Bad sector
srl a
- ld (iy+9),a
- ; Get sector
- ld a,(iy+3)
- rr a ; Convert to SD sector + low byte of track
- ld (iy+8),a
+ ; Get sector for byte 0
+ ld d,(iy+3)
+ rr d ; LSB of SD sector =
+ ; track[0] : sector[7:1]
+ ld (iy+8),d
- ; Compute unit number -> third LBA byte
- ld a,(iy+1) ; K1 = unit + more
- and 0x07 ; Unit
- jr z,lb_haveunit ; Unit 0 skips loop
- ; Each unit has 238 tracks, that is the maximum supported.
- ; We multiply by 119 (238/2), this starts LBA bytes 2-3
- ld b,a
-lb_getunit:
- ld a,(iy+9)
- add a,119
+ ; Resume computation of byte 1
+ add (hl) ; Add the portion from the unit
ld (iy+9),a
- ld a,(iy+10)
- adc a,0
+ inc l ; Leaves the C flag unchanged!
+ ld a,(hl)
+ adc a,e
ld (iy+10),a
- djnz lb_getunit
-lb_haveunit:
; Now sd_need contains the LBA sector (including upper 4 control bits)
; that we need; sd_sect contains what's currently loaded in the SD
; sector buffer.
+ ; ld a,(iy+10) ; already loaded
+ cp (iy+6)
+ jr nz,lb_nomatch
ld a,(iy+8)
cp (iy+4)
jr nz,lb_nomatch
ld a,(iy+9)
cp (iy+5)
jr nz,lb_nomatch
- ld a,(iy+10)
- cp (iy+6)
- jr nz,lb_nomatch
ld a,(iy+11)
cp (iy+7)
ret z ; If match, we're done
@@ -752,3 +818,16 @@ confirm:
rst 32 ; Unlock
and a ; F.C <- 0
ret
+
+;
+; Initial values for the unit map table
+;
+init_unit_table:
+ defw 0*119
+ defw 1*119
+ defw 2*119
+ defw 3*119
+ defw 4*119
+ defw 5*119
+ defw 6*119
+ defw 7*119
diff --git a/sddisk.v b/sddisk.v
index 049ea2f..2b79715 100644
--- a/sddisk.v
+++ b/sddisk.v
@@ -218,6 +218,7 @@ module sdcontroller(
// D1 = direction bit (see above)
// D2 = card present
// D3 = card write protect
+ // D4 = set by hard reset, cleared by OUT 0x00
// ------------------------------------------------------------------------
reg [8:0] cpudata_ctr; // Bytes left to DMA
@@ -228,6 +229,7 @@ module sdcontroller(
wire dma_stat_sel = ~cpu_iorq_n & cpu_m1_n & ~cpu_a[5]; // IN 0x00
wire dma_active = |cpudata_ctr;
reg [7:0] abc_di;
+ reg hard_reset;
always @(*)
begin
@@ -253,6 +255,8 @@ module sdcontroller(
read_flag <= 1'b0;
main_status <= 8'h00;
aux_status <= 8'h00;
+ if ( ~reset_n )
+ hard_reset <= 1'b1;
end
else
begin
@@ -295,7 +299,10 @@ module sdcontroller(
begin
casex ( cpu_a[2:0] )
3'b000: // OUT 0x00
- main_status <= cpu_do;
+ begin
+ main_status <= cpu_do;
+ hard_reset <= 1'b0;
+ end
3'b001: // OUT 0x01
aux_status <= cpu_do;
3'b01x: // OUT 0x02-0x03
@@ -319,7 +326,9 @@ module sdcontroller(
// Bit 1: Direction of DMA
// Bit 2: Card Present
// Bit 3: Card Write Protected
- assign dma_status = { 4'b0, sd_we_n, ~sd_cd_n, cpudata_dir, dma_active };
+ // Bit 4: Hard reset
+ assign dma_status = { 3'b0, hard_reset,
+ sd_we_n, ~sd_cd_n, cpudata_dir, dma_active };
// ------------------------------------------------------------------------
// SD card interface