-CSRCS = devlpr.c devtty.c devsd.c devrd.c
+CSRCS = devlpr.c devtty.c devrd.c devsdspi.c
CSRCS += devices.c main.c
-ASRCS = crt0.s devsd_hw.s devrd_hw.s socz80.s
+ASRCS = crt0.s devrd_hw.s socz80.s
ASRCS += tricks.s usermem.s commonmem.s
+DSRCS = ../dev/devsd.c ../dev/mbr.c ../dev/blkdev.c
+DOBJS = $(patsubst ../dev/%.c,%.rel, $(DSRCS))
+
COBJS = $(CSRCS:.c=.rel)
AOBJS = $(ASRCS:.s=.rel)
-OBJS = $(COBJS) $(AOBJS)
+OBJS = $(COBJS) $(AOBJS) $(DOBJS)
+
+CROSS_CCOPTS += -I../dev/
-JUNK = $(CSRCS:.c=.lst) $(CSRCS:.c=.asm) $(CSRCS:.c=.sym) $(ASRCS:.s=.lst) $(ASRCS:.s=.sym) $(CSRCS:.c=.rst) $(ASRCS:.s=.rst)
+JUNK = *.rel *.lst *.asm *.sym *.rst *.map *.ihx *.bin
all: $(OBJS)
+$(AOBJS): %.rel: %.s
+ $(CROSS_AS) $(ASOPTS) $<
+
$(COBJS): %.rel: %.c
$(CROSS_CC) $(CROSS_CCOPTS) -c $<
-$(AOBJS): %.rel: %.s
- $(CROSS_AS) $(ASOPTS) $<
+$(DOBJS): %.rel: ../dev/%.c
+ $(CROSS_CC) $(CROSS_CCOPTS) -c $<
clean:
rm -f $(OBJS) $(JUNK) core *~
#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */
#define NBUFS 10 /* Number of block buffers */
#define NMOUNTS 4 /* Number of mounts at a time */
+
+#define MAX_BLKDEV 1 /* Only the one SPI supported for now */
+#define SD_DRIVE_COUNT 1
\ No newline at end of file
#include <tty.h>
#include <version.h>
#include <kdata.h>
-#include <devsd.h>
#include <devrd.h>
#include <devsys.h>
#include <devlpr.h>
#include <devtty.h>
+#include <devsd.h>
+#include <blkdev.h>
struct devsw dev_tab[] = /* The device driver switch table */
{
// minor open close read write ioctl
// -----------------------------------------------------------------
/* 0: /dev/sd SD disc block devices */
- { sd_open, no_close, sd_read, sd_write, no_ioctl },
+ { blkdev_open, no_close, blkdev_read, blkdev_write, blkdev_ioctl },
/* 1: /dev/hd Hard disc block devices (RAMdisc) */
- { rd_open, no_close, rd_read, rd_write, no_ioctl },
+ { rd_open, no_close, rd_read, rd_write, no_ioctl },
/* 2: /dev/tty TTY devices */
{ tty_open, tty_close, tty_read, tty_write, tty_ioctl },
/* 3: /dev/lpr Printer devices */
{ lpr_open, lpr_close, no_rdwr, lpr_write, no_ioctl },
/* 4: /dev/mem etc System devices (one offs) */
- { no_open, no_close, sys_read, sys_write, sys_ioctl },
+ { no_open, no_close, sys_read, sys_write, sys_ioctl },
/* Pack to 7 with nxio if adding private devices and start at 8 */
};
void device_init(void)
{
- sd_init();
+ devsd_init();
}
+++ /dev/null
-/*-----------------------------------------------------------------------*/
-/* socz80 SD card driver */
-/* Based on: */
-/* MMCv3/SDv1/SDv2 (in SPI mode) control module (C)ChaN, 2007 */
-/* (from http://www.cl.cam.ac.uk/teaching/1011/P31/lib/diskio.c) */
-/* and http://elm-chan.org/docs/mmc/mmc_e.html */
-/*-----------------------------------------------------------------------*/
-
-#include <kernel.h>
-#include <kdata.h>
-#include <printf.h>
-#include <timer.h>
-#include <devsd.h>
-#include <stdbool.h>
-
-/* keep track of current card type, UZI partition offset */
-static int sd_card_type;
-static unsigned long sd_first_uzi_sector;
-
-/* used to track current transfer in progress */
-static int sd_blockdev_count;
-static char *sd_dptr;
-static int sd_dlen;
-static uint16_t sd_blocks;
-static unsigned long sd_next_block;
-
-void sd_setup(uint8_t minor, uint8_t rawflag)
-{
- blkno_t block;
-
- if(rawflag){
- sd_dlen = udata.u_count;
- sd_dptr = udata.u_base;
- block = udata.u_offset >> 9;
- sd_blocks = sd_dlen >> 9;
- }else{
- sd_dlen = 512;
- sd_dptr = udata.u_buf->bf_data;
- block = udata.u_buf->bf_blk;
- sd_blocks = 1;
- }
-
- if(sd_blocks != 1)
- panic("sd: unexpected block count");
-
- sd_next_block = sd_first_uzi_sector + /* start of our partition */
- (((unsigned long)minor) << UZI_BLOCKDEV_SIZE_LOG2_SECTORS) + /* start of this minor device */
- ((unsigned long)block); /* requested sector */
-}
-
-int sd_open(uint8_t minor, uint16_t flag)
-{
- flag;
- if(minor < sd_blockdev_count){
- return 0;
- } else {
- udata.u_error = EIO;
- return -1;
- }
-}
-
-int sd_readwrite(uint8_t minor, uint8_t rawflag, bool do_write)
-{
- int attempt;
- for(attempt=0; attempt<5; attempt++){
- sd_setup(minor, rawflag);
- if(do_write){
- if(sd_write_sector(sd_dptr, sd_next_block))
- return sd_blocks;
- }else{
- if(sd_read_sector(sd_dptr, sd_next_block))
- return sd_blocks;
- }
- kputs("sd: failed, resetting.\n");
- if(sd_init())
- break;
- }
- return -1;
-}
-
-int sd_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
-{
- flag;
- return sd_readwrite(minor, rawflag, false);
-}
-
-int sd_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
-{
- flag;
- return sd_readwrite(minor, rawflag, true);
-}
-
-static const char cardname[] = " MMC\0\0SDv1\0?>???SDv2\0";
-
-/* Stop sdcc inlining a ton of crap each time */
-static unsigned long shift11(unsigned long p)
-{
- return (p >> 11);
-}
-
-void sd_print_partition(unsigned char *p)
-{
- long size;
- if(!*p)
- return;
-
- size = *(unsigned long *)(p + 4);
-
- kprintf("sd: partition type 0x%x, offset %uMB, length %uMB (%s)\n",
- *p,
- (unsigned int)shift11(*(unsigned long *)(p + 4)),
- (unsigned int)shift11(size),
- *p != UZI_PARTITION_TYPE ? "ignored" :
- (sd_blockdev_count == 0 ? "UZI" : "unused"));
-
- /* We will use the first partition with the appropriate type */
- if(*p == UZI_PARTITION_TYPE && sd_blockdev_count == 0){
- sd_first_uzi_sector = *((unsigned long*)&p[4]);
- /* 16 bit shift */
- sd_blockdev_count = size >> UZI_BLOCKDEV_SIZE_LOG2_SECTORS;
- /* Allow a smaller than 32MB final 'device' */
- if (size & 0xFFFF)
- sd_blockdev_count++;
- }
-}
-
-int sd_init(void)
-{
- int n;
- unsigned long sector_count;
- unsigned char *sector;
- unsigned char *p; /* into sector */
-
- sd_first_uzi_sector = 0;
- sd_blockdev_count = 0;
-
- kputs("sd: Probing ... ");
-
- if (!(sd_card_type = sd_spi_init())) {
- kputs("No card found\n");
- return -1;
- }
-
- /* read and compute card size */
- sector_count = sd_get_size_sectors();
- if(!sector_count){
- kputs("Weird card\n");
- return -1;
- }
- n = shift11(sector_count);
-
- kprintf("Found %s card (%dMB, b%s addressed)\n",
- cardname + 5 * (sd_card_type & ~CT_BLOCK),
- n,
- (sd_card_type & CT_BLOCK) ? "lock" : "yte");
-
- /* read partition table, locate the UZI partition */
- sector = (unsigned char*)tmpbuf();
- if(!sd_read_sector(sector, 0)){
- kputs("sd: Failed to read partition table\n");
- }else{
- p = sector + 510;
- if(*p != 0x55 || p[1] != 0xAA){ /* check for presence of MBR boot signature */
- kputs("sd: Cannot find MBR partition table\n");
- }else{
- p = sector + 0x1BE + 4;
- for(n = 4; n > 0; n--) {
- sd_print_partition(p);
- p+=16;
- }
- if(sd_blockdev_count == 0){
- kprintf("sd: No UZI partition (type 0x%x) found\n", UZI_PARTITION_TYPE);
- }
- }
- }
-
- if(sd_blockdev_count > NUM_DEV_SD)
- sd_blockdev_count = NUM_DEV_SD;
-
- if(sd_blockdev_count)
- kprintf("sd: %d block devices, max 32MB each\n", sd_blockdev_count);
-
- brelse((bufptr)sector);
-
- return 0; /* success */
-}
-
-int sd_spi_init(void)
-{
- unsigned char n, cmd, card_type, ocr[4];
- timer_t timer;
-
- sd_spi_mode0();
- sd_spi_raise_cs();
-
- sd_spi_clock(255); /* 250kHz */
- for (n = 20; n; n--)
- sd_spi_receive_byte(); /* 160 dummy clocks */
-
- card_type = 0;
- /* Enter Idle state */
- if (sd_send_command(CMD0, 0) == 1) {
- /* initialisation timeout 1 second */
- timer = set_timer_sec(1);
- if (sd_send_command(CMD8, (uint32_t)0x1AA) == 1) { /* SDHC */
- /* Get trailing return value of R7 resp */
- for (n = 0; n < 4; n++) ocr[n] = sd_spi_receive_byte();
- /* The card can work at vdd range of 2.7-3.6V */
- if (ocr[2] == 0x01 && ocr[3] == 0xAA) {
- /* Wait for leaving idle state (ACMD41 with HCS bit) */
- while(!timer_expired(timer) && sd_send_command(ACMD41, (uint32_t)1 << 30));
- /* Check CCS bit in the OCR */
- if (!timer_expired(timer) && sd_send_command(CMD58, 0) == 0) {
- for (n = 0; n < 4; n++) ocr[n] = sd_spi_receive_byte();
- card_type = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */
- }
- }
- } else { /* SDSC or MMC */
- if (sd_send_command(ACMD41, 0) <= 1) {
- /* SDv1 */
- card_type = CT_SD1;
- cmd = ACMD41;
- } else {
- /* MMCv3 */
- card_type = CT_MMC;
- cmd = CMD1;
- }
- /* Wait for leaving idle state */
- while(!timer_expired(timer) && sd_send_command(cmd, 0));
- /* Set R/W block length to 512 */
- if(timer_expired(timer) || sd_send_command(CMD16, (uint32_t)512) != 0)
- card_type = 0;
- }
- }
- sd_spi_release();
-
- if (card_type) {
- if(card_type == CT_MMC)
- sd_spi_clock(3); /* 16MHz (can do up to 20MHz with MMC) */
- else
- sd_spi_clock(2); /* 21MHz (can do up to 25MHz with SD) */
- return card_type;
- }
-
- return 0; /* failed */
-}
-
-void sd_spi_release(void)
-{
- sd_spi_raise_cs();
- sd_spi_receive_byte();
-}
-
-int sd_spi_wait_ready(void)
-{
- unsigned char res;
- timer_t timer;
-
- timer = set_timer_ms(100); /* 100ms */
- sd_spi_receive_byte();
- do{
- res = sd_spi_receive_byte();
- }while ((res != 0xFF) && !timer_expired(timer));
-
- return res;
-}
-
-int sd_spi_transmit_block(void *ptr, int length)
-{
- unsigned char reply;
-
- if(sd_spi_wait_ready() != 0xFF)
- return 0; /* failed */
-
- sd_spi_transmit_byte(0xFE);
- sd_spi_transmit_from_memory(ptr, length);
- sd_spi_transmit_byte(0xFF); /* dummy CRC */
- sd_spi_transmit_byte(0xFF);
- reply = sd_spi_receive_byte();
- if((reply & 0x1f) != 0x05)
- return 0; /* failed */
- return 1; /* hooray! */
-}
-
-int sd_spi_receive_block(void *ptr, int length)
-{
- unsigned int timer;
- unsigned char b;
-
- timer = set_timer_ms(200); /* 200ms */
-
- do{
- b = sd_spi_receive_byte();
- }while(b == 0xFF && !timer_expired(timer));
- if(b != 0xFE)
- return 0; /* failed */
-
- return sd_spi_receive_to_memory(ptr, length); /* returns nonzero */
-}
-
-int sd_send_command(unsigned char cmd, uint32_t arg)
-{
- unsigned char n, res;
-
- if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
- cmd &= 0x7F;
- res = sd_send_command(CMD55, 0);
- if (res > 1)
- return res;
- }
-
- /* Select the card and wait for ready */
- sd_spi_raise_cs();
- sd_spi_lower_cs();
- if (sd_spi_wait_ready() != 0xFF)
- return 0xFF;
-
- /* Send command packet */
- sd_spi_transmit_byte(cmd); /* Start + Command index */
- sd_spi_transmit_byte((unsigned char)(arg >> 24)); /* Argument[31..24] */
- sd_spi_transmit_byte((unsigned char)(arg >> 16)); /* Argument[23..16] */
- sd_spi_transmit_byte((unsigned char)(arg >> 8)); /* Argument[15..8] */
- sd_spi_transmit_byte((unsigned char)arg); /* Argument[7..0] */
- /* there's only a few commands (in native mode) that need correct CRCs */
- n = 0x01; /* Dummy CRC + Stop */
- if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
- if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
- sd_spi_transmit_byte(n);
-
- /* Receive command response */
- if (cmd == CMD12)
- sd_spi_receive_byte(); /* Skip a stuff byte when stop reading */
- n = 10; /* Wait for a valid response in timeout of 10 attempts */
- do{
- res = sd_spi_receive_byte();
- }while ((res & 0x80) && --n);
-
- return res; /* Return with the response value */
-}
-
-unsigned long sd_get_size_sectors(void)
-{
- unsigned char csd[16], n;
- unsigned long sectors = 0;
-
- if(sd_send_command(CMD9, 0) == 0 && sd_spi_receive_block(csd, 16)){
- if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
- sectors = (csd[9] + ((unsigned int)csd[8] << 8) + 1) << 10;
- } else { /* SDC ver 1.XX or MMC*/
- n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
- sectors = (csd[8] >> 6) + ((unsigned int)csd[7] << 2) + ((unsigned int)(csd[6] & 3) << 10) + 1;
- sectors = sectors << (n - 9);
- }
- }
- sd_spi_release();
- return sectors;
-}
-
-int sd_read_sector(void *ptr, unsigned long lba)
-{
- int r = 0;
-
- if(sd_card_type == CT_NONE)
- return r;
-
- if(!(sd_card_type & CT_BLOCK))
- lba = lba << 9; /* multiply by 512 to get byte address */
-
- if(sd_send_command(CMD17, lba) == 0 && sd_spi_receive_block(ptr, 512)){
- r = -1;
- }
-
- sd_spi_release();
-
- return r;
-}
-
-int sd_write_sector(void *ptr, unsigned long lba)
-{
- int r = 0;
-
- if(sd_card_type == CT_NONE)
- return r;
-
- if(!(sd_card_type & CT_BLOCK))
- lba = lba << 9; /* multiply by 512 to get byte address */
-
- if(sd_send_command(CMD24, lba) == 0 && sd_spi_transmit_block(ptr, 512)){
- r = -1;
- }
-
- sd_spi_release();
-
- return r;
-}
+++ /dev/null
-#ifndef __DEVSD_DOT_H__
-#define __DEVSD_DOT_H__
-
-#define UZI_PARTITION_TYPE 0x5A /* ASCII "Z", Wikipedia suggests this partition type is not widely used */
-#define UZI_BLOCKDEV_SIZE_LOG2_SECTORS 16 /* Each device is 2^16 sectors ie 2^16 * 2^9 = 2^25 = 32MB */
-
-/* public interface */
-int sd_read(uint8_t minor, uint8_t rawflag, uint8_t flag);
-int sd_write(uint8_t minor, uint8_t rawflag, uint8_t flag);
-int sd_init(void);
-int sd_open(uint8_t minor, uint16_t flag);
-
-/* private interface */
-int sd_spi_init(void);
-int sd_read_sector(void *ptr, unsigned long lba);
-int sd_write_sector(void *ptr, unsigned long lba);
-unsigned long sd_get_size_sectors(void);
-
-/* internal functions */
-void sd_spi_clock(int divisor);
-/*
- sd_clock sets SPI bus to 64.0 / (1+divisor) MHz
- 0=64MHz, 1=32MHz, 2=21.33MHz, 3=16MHz, 4=12.8MHz,
- 5=10.66MHz, 6=9.14MHz, 7=8MHz, 15=4MHz, etc
- 255 = 0.25MHz, about right for MMC/SPI initialisation
-*/
-
-void sd_spi_mode0(void);
-void sd_spi_raise_cs(void);
-void sd_spi_lower_cs(void);
-void sd_spi_release(void);
-int sd_spi_wait_ready(void);
-void sd_spi_transmit_byte(unsigned char byte);
-unsigned char sd_spi_receive_byte(void);
-int sd_spi_receive_block(void *ptr, int length); /* waits for card ready then calls sd_spi_receive_to_memory */
-int sd_spi_transmit_block(void *ptr, int length); /* waits for card ready then calls sd_spi_receive_to_memory */
-int sd_spi_receive_to_memory(void *ptr, int length);
-int sd_spi_transmit_from_memory(void *ptr, int length);
-int sd_send_command(unsigned char cmd, uint32_t arg);
-
-/* Definitions for MMC/SDC command */
-#define CMD0 (0x40+0) /* GO_IDLE_STATE */
-#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
-#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
-#define CMD8 (0x40+8) /* SEND_IF_COND */
-#define CMD9 (0x40+9) /* SEND_CSD */
-#define CMD10 (0x40+10) /* SEND_CID */
-#define CMD12 (0x40+12) /* STOP_TRANSMISSION */
-#define ACMD13 (0xC0+13) /* SD_STATUS (SDC) */
-#define CMD16 (0x40+16) /* SET_BLOCKLEN */
-#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
-#define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
-#define CMD23 (0x40+23) /* SET_BLOCK_COUNT (MMC) */
-#define ACMD23 (0xC0+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
-#define CMD24 (0x40+24) /* WRITE_BLOCK */
-#define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
-#define CMD55 (0x40+55) /* APP_CMD */
-#define CMD58 (0x40+58) /* READ_OCR */
-
-#define CT_NONE 0x00
-#define CT_MMC 0x01
-#define CT_SD1 0x02
-#define CT_SD2 0x04
-#define CT_SDC (CT_SD1|CT_SD2)
-#define CT_BLOCK 0x08
-
-#endif /* __DEVSD_DOT_H__ */
+++ /dev/null
-; 2013-12-19 William R Sowerbutts
-
- .module devsd_hw
-
- ; exported symbols
- .globl _sd_spi_clock
- .globl _sd_spi_raise_cs
- .globl _sd_spi_lower_cs
- .globl _sd_spi_receive_byte
- .globl _sd_spi_transmit_byte
- .globl _sd_spi_receive_to_memory
- .globl _sd_spi_transmit_from_memory
- .globl _sd_spi_mode0
-
- .include "socz80.def"
-
- .area _CODE
-
-_sd_spi_clock:
- pop de
- pop hl
- push hl
- push de
- ld a, l
- out (SD_SPI_DIVISOR), a
- ret
-
-_sd_spi_raise_cs:
- ld a, #0xFF
- out (SD_SPI_CHIPSELECT), a
- ret
-
-_sd_spi_lower_cs:
- ld a, #0xFE
- out (SD_SPI_CHIPSELECT), a
- ret
-
-_sd_spi_mode0:
- xor a
- out (SD_SPI_MODE), a
- ret
-
-_sd_spi_receive_byte:
- ; read a byte
- ld a, #0xFF
- out (SD_SPI_TX), a
- in a, (SD_SPI_RX)
- ld h, #0
- ld l, a
- ret
-
-_sd_spi_transmit_from_memory:
- pop de ; return address
- pop hl ; memory pointer
- pop bc ; byte count
- push bc ; now put the stack back ...
- push hl
- push de
-tnextbyte:
- ld a, (hl)
- out (SD_SPI_TX), a
- inc hl
- dec bc
- ld a, b
- or c
- jr nz, tnextbyte
- ; return success in HL
- ld hl, #1
- ret
-
-
-_sd_spi_receive_to_memory:
- pop de ; return address
- pop hl ; memory pointer
- pop bc ; byte count
- push bc ; now put the stack back ...
- push hl
- push de
-rnextbyte:
- ld a, #0xFF
- out (SD_SPI_TX), a
- in a, (SD_SPI_RX)
- ld (hl), a
- inc hl
- dec bc
- ld a, b
- or c
- jr nz, rnextbyte
- ; there's also a 16-bit CRC that we discard
- call _sd_spi_receive_byte
- call _sd_spi_receive_byte
- ; return success in HL
- ld hl, #1
- ret
-
-_sd_spi_transmit_byte:
- pop de
- pop hl
- push hl
- push de
- ld a, l
- out (SD_SPI_TX), a
- ret
--- /dev/null
+/*
+ * SPI glue for the SocZ80. Based on Will Sowerbutts's UZI180 for SocZ80
+ * and his implementation for the N8VEM Mark 4
+ */
+
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <timer.h>
+#include <stdbool.h>
+#include "config.h"
+#include <blkdev.h>
+
+/* We should revisit this if we are willing to rely on the later VHDL
+ being used. At that point we've got mode setting but more importantly
+ the tx port is r/w as rx/tx so the port can sit in (c) */
+
+__sfr __at 0x30 sd_spi_chipselect;
+__sfr __at 0x31 sd_spi_status;
+__sfr __at 0x32 sd_spi_tx;
+__sfr __at 0x33 sd_spi_rx;
+__sfr __at 0x34 sd_spi_divisor;
+__sfr __at 0x35 sd_spi_gpio; /* only on later VHDL */
+__sfr __at 0x36 sd_spi_mode; /* only on later VHDL */
+
+#define SD_SPI_TX 0x32
+#define SD_SPI_RX 0x33
+
+void sd_spi_mode0(uint8_t drive)
+{
+ used(drive);
+ sd_spi_mode = 0;
+}
+
+void sd_spi_clock(uint8_t drive, bool go_fast)
+{
+ used(drive);
+// sd_spi_mode0(drive);
+ /* Currently the sd driver just uses 'slow' and 'fast'. That's ok for
+ sd but mmc really needs to be 16MHz */
+ if (go_fast)
+ sd_spi_divisor = 3; //2
+ else
+ sd_spi_divisor = 255;
+}
+
+void sd_spi_raise_cs(uint8_t drive)
+{
+ used(drive);
+ sd_spi_chipselect = 0xFF;
+}
+
+void sd_spi_lower_cs(uint8_t drive)
+{
+ used(drive);
+ sd_spi_chipselect = 0xFE;
+}
+
+void sd_spi_transmit_byte(uint8_t drive, unsigned char byte)
+{
+ used(drive);
+ sd_spi_tx = byte;
+}
+
+uint8_t sd_spi_receive_byte(uint8_t drive)
+{
+ uint8_t r;
+ used(drive);
+ sd_spi_tx = 0xFF;
+ r = sd_spi_rx;
+ return r;
+}
+
+COMMON_MEMORY
+
+bool sd_spi_receive_sector(uint8_t drive) __naked
+{
+ used(drive);
+ __asm
+ ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET);
+ ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET);
+ or a ; Set the Z flag up and save it, dont do it twice
+ push af
+ call nz,map_process_always
+ call rx256
+ call rx256
+ pop af
+ call nz,map_kernel
+ ret
+rx256:
+ ld a,#0xFF
+ ld bc, #SD_SPI_RX ; b = 0, c = port
+rx256_1:
+ out (SD_SPI_TX),a ; we could use (c),a on newer VHDL
+ ini
+ jr nz, rx256_1
+ ret
+ __endasm;
+}
+
+bool sd_spi_transmit_sector(uint8_t drive) __naked
+{
+ used(drive);
+ __asm
+ ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET)
+ ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)
+ or a ; Set the Z flag up and save it, dont do it twice
+ push af
+ call nz,map_process_always
+ call tx256
+ call tx256
+ pop af
+ call nz,map_kernel
+ ret
+tx256:
+ ld a,#0xFF
+ ld bc, #SD_SPI_RX * 256
+tx256_1:
+ out (SD_SPI_TX),a ; we could use (c),a on newer VHDL
+ outi
+ jr nz, tx256_1
+ ret
+ __endasm;
+}
timer.rel
kdata.rel
platform-socz80/devrd.rel
-platform-socz80/devsd.rel
-platform-socz80/devsd_hw.rel
platform-socz80/devrd_hw.rel
platform-socz80/devices.rel
devio.rel
devsys.rel
platform-socz80/devlpr.rel
platform-socz80/devtty.rel
+platform-socz80/devsd.rel
+platform-socz80/blkdev.rel
+platform-socz80/mbr.rel
+platform-socz80/devsdspi.rel
-e
__sfr __at 0x00 uart0_status;
__sfr __at 0x01 uart0_data;
-__sfr __at 0x10 timer_status;
-__sfr __at 0x11 timer_command;
__sfr __at 0x28 uart1_status;
__sfr __at 0x29 uart1_data;
+extern uint16_t irqwork;
+
void platform_interrupt(void)
{
uint8_t st0 = uart0_status;
uint8_t st1 = uart1_status;
- uint8_t ts = timer_status;
+ uint8_t ts = irqwork;
uint8_t d;
- if (ts & 0x80)
- timer_command = 0; /* Ack the timer */
- if (st0 & 0xC0) {
- kprintf("st0 %x\n", st0);
- uart0_status = st0 & 0xFC;
- if (st0 & 0x80) { /* RX data */
+ irqwork = 0;
+ if (ts & 0xC0) {
+ if (ts & 0x80) { /* RX data */
d = uart0_data;
tty_inproc(1, d);
}
- if (st0 & 0x40) /* TX idle */
+ if (ts & 0x40) /* TX idle */
tty_outproc(1);
}
if (st1 & 0xC0) {
if (st1 & 0x40) /* TX idle */
tty_outproc(2);
}
- if (ts & 0x80)
+ if (ts & 1)
timer_interrupt();
}
.globl map_restore
.globl platform_interrupt_all
.globl _kernel_flag
+ .globl _irqwork
; exported debugging tools
.globl _trap_monitor
; it's never a dull day with ROM around!
platform_interrupt_all:
+ in a,(TIMER_STATUS)
+ bit 7, a
+ jr z, not_timer
+ ld a,(_irqwork)
+ set 0, a
+ ld (_irqwork),a
+ xor a
+ out (TIMER_STATUS),a
+not_timer:
+ in a,(UART0_STATUS)
+ ld b, a
+ and #0xC0
+ ret z
+ ld a, #0xfc
+ and b
+ out (UART0_STATUS),a
+ and #0xC0
+ ld hl,#_irqwork
+ or (hl)
+ ld (hl),a
ret
+; FIXME: this in common is not ideal but not clear where it should go
+; to allow queued stuff to be handled reliably
+_irqwork: .dw 0
+
; -----------------------------------------------------------------------------
; KERNEL MEMORY BANK (below 0xF000, only accessible when the kernel is mapped)
; -----------------------------------------------------------------------------
inir
ret
+mmu_state_dump:
+ push bc
+ push hl
+ ld c, #0
+ ld b, #16
+dumpnextframe:
+ ld hl, #mmumsg
+ call outstring
+ ld a, c
+ out (MMU_SELECT), a
+ call outnibble
+ ld a, #':'
+ call outchar
+ ld a, #' '
+ call outchar
+ in a, (MMU_FRAMEHI)
+ ld h, a
+ in a, (MMU_FRAMELO)
+ ld l, a
+ call outhl
+ call outnewline
+ inc c
+ djnz dumpnextframe
+ pop hl
+ pop bc
+ ret
+
;------------------------------------------------------------------------------
; COMMON MEMORY PROCEDURES FOLLOW
mmumsg: .ascii "MMU page "
.db 0
-mmu_state_dump:
- push bc
- push hl
- ld c, #0
- ld b, #16
-dumpnextframe:
- ld hl, #mmumsg
- call outstring
- ld a, c
- out (MMU_SELECT), a
- call outnibble
- ld a, #':'
- call outchar
- ld a, #' '
- call outchar
- in a, (MMU_FRAMEHI)
- ld h, a
- in a, (MMU_FRAMELO)
- ld l, a
- call outhl
- call outnewline
- inc c
- djnz dumpnextframe
- pop hl
- pop bc
- ret
-
;
; Mapping routines. Not yet all fixed up for the new style memory management