ds1302, devsd: Split code for the DISCARD segment into separate files.
authorWill Sowerbutts <will@sowerbutts.com>
Thu, 12 Feb 2015 20:49:49 +0000 (20:49 +0000)
committerWill Sowerbutts <will@sowerbutts.com>
Thu, 12 Feb 2015 20:51:21 +0000 (20:51 +0000)
Includes required platform changes for n8vem-mark4, p112.

Kernel/dev/devide_discard.c
Kernel/dev/devsd.c
Kernel/dev/devsd.h
Kernel/dev/devsd_discard.c [new file with mode: 0644]
Kernel/dev/ds1302.c
Kernel/dev/ds1302.h
Kernel/dev/ds1302_discard.c [new file with mode: 0644]
Kernel/platform-n8vem-mark4/Makefile
Kernel/platform-n8vem-mark4/fuzix.lnk
Kernel/platform-p112/Makefile
Kernel/platform-p112/fuzix.lnk

index 735691a..f841d81 100644 (file)
@@ -18,9 +18,9 @@
 #include <blkdev.h>
 
 /****************************************************************************/
-/* Code below this point used only once, at startup, so we want it to live  */
+/* Code in this file is used only once, at startup, so we want it to live   */
 /* in the DISCARD segment. sdcc only allows us to specify one segment for   */
-/* each source file. This "solution" is a bit (well, very) hacky ...        */
+/* each source file.                                                        */
 /****************************************************************************/
 
 static void devide_delay(void)
index b190232..e39a9ef 100644 (file)
@@ -10,6 +10,8 @@
 /* and http://elm-chan.org/docs/mmc/mmc_e.html                           */
 /*-----------------------------------------------------------------------*/
 
+#define _SD_PRIVATE
+
 #include <kernel.h>
 #include <kdata.h>
 #include <printf.h>
 #include <stdbool.h>
 #include <blkdev.h>
 
-/* internal functions */
-static void sd_init_drive(uint8_t drive);
-static int sd_spi_init(uint8_t drive);
-static void sd_spi_release(uint8_t drive);
-static int sd_send_command(uint8_t drive, unsigned char cmd, uint32_t arg);
-static uint8_t sd_spi_wait(uint8_t drive, bool want_ff);
-
-static uint8_t devsd_transfer_sector(void)
+uint8_t devsd_transfer_sector(void)
 {
     uint8_t attempt, drive;
     bool success;
@@ -66,13 +61,13 @@ static uint8_t devsd_transfer_sector(void)
     return 0;
 }
 
-static void sd_spi_release(uint8_t drive)
+void sd_spi_release(uint8_t drive)
 {
     sd_spi_raise_cs(drive);
     sd_spi_receive_byte(drive);
 }
 
-static uint8_t sd_spi_wait(uint8_t drive, bool want_ff)
+uint8_t sd_spi_wait(uint8_t drive, bool want_ff)
 {
     unsigned int timer;
     unsigned char b;
@@ -97,7 +92,7 @@ static uint8_t sd_spi_wait(uint8_t drive, bool want_ff)
     return b;
 }
 
-static int sd_send_command(uint8_t drive, unsigned char cmd, uint32_t arg)
+int sd_send_command(uint8_t drive, unsigned char cmd, uint32_t arg)
 {
     unsigned char n, res, *p;
 
@@ -145,117 +140,3 @@ static int sd_send_command(uint8_t drive, unsigned char cmd, uint32_t arg)
 
     return res;         /* Return with the response value */
 }
-
-/****************************************************************************/
-/* Code below this point used only once, at startup, so we want it to live  */
-/* in the DISCARD segment. sdcc only allows us to specify one segment for   */
-/* each source file. This "solution" is a bit (well, very) hacky ...        */
-/****************************************************************************/
-
-DISCARDABLE
-
-void devsd_init(void)
-{
-    uint8_t d;
-
-    for(d=0; d<SD_DRIVE_COUNT; d++)
-        sd_init_drive(d);
-}
-
-static void sd_init_drive(uint8_t drive)
-{
-    blkdev_t *blk;
-    unsigned char csd[16], n;
-    uint8_t card_type;
-
-    kprintf("SD drive %d: ", drive);
-    card_type = sd_spi_init(drive);
-
-    if(!(card_type & (~CT_BLOCK))){
-        kprintf("no card found\n");
-        return;
-    }
-
-    blk = blkdev_alloc();
-    if(!blk)
-        return;
-
-    blk->transfer = devsd_transfer_sector;
-    blk->driver_data = (drive & DRIVE_NR_MASK) | card_type;
-    
-    /* read and compute card size */
-    if(sd_send_command(drive, CMD9, 0) == 0 && sd_spi_wait(drive, false) == 0xFE){
-        for(n=0; n<16; n++)
-            csd[n] = sd_spi_receive_byte(drive);
-        if ((csd[0] >> 6) == 1) {
-            /* SDC ver 2.00 */
-            blk->drive_lba_count = ((uint32_t)csd[9] 
-                                   + (uint32_t)((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;
-            blk->drive_lba_count = (csd[8] >> 6) + ((unsigned int)csd[7] << 2) 
-                                   + ((unsigned int)(csd[6] & 3) << 10) + 1;
-            blk->drive_lba_count <<= (n-9);
-        }
-    }
-    sd_spi_release(drive);
-
-    blkdev_scan(blk, 0);
-}
-
-static int sd_spi_init(uint8_t drive)
-{
-    unsigned char n, cmd, card_type, ocr[4];
-    timer_t timer;
-
-    sd_spi_raise_cs(drive);
-
-    sd_spi_clock(drive, false);
-    for (n = 20; n; n--)
-        sd_spi_receive_byte(drive); /* 160 dummy clocks */
-
-    card_type = CT_NONE;
-    /* Enter Idle state */
-    if (sd_send_command(drive, CMD0, 0) == 1) {
-        /* initialisation timeout 1 second */
-        timer = set_timer_sec(1);
-        if (sd_send_command(drive, 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(drive);
-            /* 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(drive, ACMD41, (uint32_t)1 << 30));
-                /* Check CCS bit in the OCR */
-                if (!timer_expired(timer) && sd_send_command(drive, CMD58, 0) == 0) {
-                    for (n = 0; n < 4; n++) ocr[n] = sd_spi_receive_byte(drive);
-                    card_type = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;   /* SDv2 */
-                }
-            }
-        } else { /* SDSC or MMC */
-            if (sd_send_command(drive, 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(drive, cmd, 0));
-            /* Set R/W block length to 512 */
-            if(timer_expired || sd_send_command(drive, CMD16, 512) != 0)
-                card_type = CT_NONE;
-        }
-    }
-    sd_spi_release(drive);
-
-    if (card_type) {
-        sd_spi_clock(drive, true); /* up to 20MHz should be OK */
-        return card_type;
-    }
-
-    return CT_NONE; /* failed */
-}
index 997b332..aca45e6 100644 (file)
@@ -41,6 +41,16 @@ uint8_t sd_spi_receive_byte(uint8_t drive);
 bool sd_spi_receive_sector(uint8_t drive);
 bool sd_spi_transmit_sector(uint8_t drive);
 
+#ifdef _SD_PRIVATE
+
+/* internal functions */
+void sd_spi_release(uint8_t drive);
+int sd_send_command(uint8_t drive, unsigned char cmd, uint32_t arg);
+uint8_t sd_spi_wait(uint8_t drive, bool want_ff);
+void sd_init_drive(uint8_t drive);
+int sd_spi_init(uint8_t drive);
+uint8_t devsd_transfer_sector(void);
+
 /* Definitions for MMC/SDC command */
 #define CMD0    (0x40+0)    /* GO_IDLE_STATE */
 #define CMD1    (0x40+1)    /* SEND_OP_COND (MMC) */
@@ -71,4 +81,6 @@ bool sd_spi_transmit_sector(uint8_t drive);
 /* Low four bits of driver_data are available to store drive number */
 #define DRIVE_NR_MASK 0x0F
 
+#endif
+
 #endif /* __DEVSD_DOT_H__ */
diff --git a/Kernel/dev/devsd_discard.c b/Kernel/dev/devsd_discard.c
new file mode 100644 (file)
index 0000000..71b3b6a
--- /dev/null
@@ -0,0 +1,133 @@
+/*-----------------------------------------------------------------------*/
+/* Fuzix SD card driver                                                  */
+/* 2014-12-28 Will Sowerbutts                                            */
+/* 2015-01-04 WRS updated to new blkdev API                              */
+/* 2015-01-25 WRS updated to newer blkdev API                            */
+/*                                                                       */
+/* Based on UZI-socz80 SD card driver, which was itself 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                           */
+/*-----------------------------------------------------------------------*/
+
+#define _SD_PRIVATE
+
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <timer.h>
+#include <devsd.h>
+#include <stdbool.h>
+#include <blkdev.h>
+
+/****************************************************************************/
+/* Code in this file is used only once, at startup, so we want it to live   */
+/* in the DISCARD segment. sdcc only allows us to specify one segment for   */
+/* each source file.                                                        */
+/****************************************************************************/
+
+void devsd_init(void)
+{
+    uint8_t d;
+
+    for(d=0; d<SD_DRIVE_COUNT; d++)
+        sd_init_drive(d);
+}
+
+void sd_init_drive(uint8_t drive)
+{
+    blkdev_t *blk;
+    unsigned char csd[16], n;
+    uint8_t card_type;
+
+    kprintf("SD drive %d: ", drive);
+    card_type = sd_spi_init(drive);
+
+    if(!(card_type & (~CT_BLOCK))){
+        kprintf("no card found\n");
+        return;
+    }
+
+    blk = blkdev_alloc();
+    if(!blk)
+        return;
+
+    blk->transfer = devsd_transfer_sector;
+    blk->driver_data = (drive & DRIVE_NR_MASK) | card_type;
+    
+    /* read and compute card size */
+    if(sd_send_command(drive, CMD9, 0) == 0 && sd_spi_wait(drive, false) == 0xFE){
+        for(n=0; n<16; n++)
+            csd[n] = sd_spi_receive_byte(drive);
+        if ((csd[0] >> 6) == 1) {
+            /* SDC ver 2.00 */
+            blk->drive_lba_count = ((uint32_t)csd[9] 
+                                   + (uint32_t)((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;
+            blk->drive_lba_count = (csd[8] >> 6) + ((unsigned int)csd[7] << 2) 
+                                   + ((unsigned int)(csd[6] & 3) << 10) + 1;
+            blk->drive_lba_count <<= (n-9);
+        }
+    }
+    sd_spi_release(drive);
+
+    blkdev_scan(blk, 0);
+}
+
+int sd_spi_init(uint8_t drive)
+{
+    unsigned char n, cmd, card_type, ocr[4];
+    timer_t timer;
+
+    sd_spi_raise_cs(drive);
+
+    sd_spi_clock(drive, false);
+    for (n = 20; n; n--)
+        sd_spi_receive_byte(drive); /* 160 dummy clocks */
+
+    card_type = CT_NONE;
+    /* Enter Idle state */
+    if (sd_send_command(drive, CMD0, 0) == 1) {
+        /* initialisation timeout 1 second */
+        timer = set_timer_sec(1);
+        if (sd_send_command(drive, 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(drive);
+            /* 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(drive, ACMD41, (uint32_t)1 << 30));
+                /* Check CCS bit in the OCR */
+                if (!timer_expired(timer) && sd_send_command(drive, CMD58, 0) == 0) {
+                    for (n = 0; n < 4; n++) ocr[n] = sd_spi_receive_byte(drive);
+                    card_type = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;   /* SDv2 */
+                }
+            }
+        } else { /* SDSC or MMC */
+            if (sd_send_command(drive, 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(drive, cmd, 0));
+            /* Set R/W block length to 512 */
+            if(timer_expired || sd_send_command(drive, CMD16, 512) != 0)
+                card_type = CT_NONE;
+        }
+    }
+    sd_spi_release(drive);
+
+    if (card_type) {
+        sd_spi_clock(drive, true); /* up to 20MHz should be OK */
+        return card_type;
+    }
+
+    return CT_NONE; /* failed */
+}
index 56188ce..95c3d38 100644 (file)
@@ -9,7 +9,7 @@
 #include <printf.h>
 #include <ds1302.h>
 
-static void ds1302_send_byte(uint8_t byte)
+void ds1302_send_byte(uint8_t byte)
 {
     uint8_t i;
 
@@ -29,7 +29,7 @@ static void ds1302_send_byte(uint8_t byte)
     }
 }
 
-static uint8_t ds1302_receive_byte(void)
+uint8_t ds1302_receive_byte(void)
 {
     uint8_t i, b;
 
@@ -51,7 +51,7 @@ static uint8_t ds1302_receive_byte(void)
     return b;
 }
 
-static uint8_t from_bcd(uint8_t value)
+uint8_t uint8_from_bcd(uint8_t value)
 {
     return (value & 0x0F) + (10 * (value >> 4));
 }
@@ -79,137 +79,5 @@ uint8_t rtc_secs(void)
 {
     uint8_t buffer;
     ds1302_read_clock(&buffer, 1);   /* read out only the seconds value */
-    return from_bcd(buffer & 0x7F); /* mask off top bit (clock-halt) */
-}
-
-/****************************************************************************/
-/* Code below this point used only once, at startup, so we want it to live  */
-/* in the DISCARD segment. sdcc only allows us to specify one segment for   */
-/* each source file. This "solution" is a bit (well, very) hacky ...        */
-/****************************************************************************/
-static void DISCARDSEG(void) __naked { __asm .area _DISCARD __endasm; }
-
-/* we avoid using 32x32 bit multiply ds1302_read_rtc, because it causes sdcc to pull 
-   in a huge __mullong helper -- which is nearly 500 bytes! */
-static uint32_t multiply_8x32(uint8_t a, uint32_t b) __naked /* return a * b */
-{
-    __asm
-        ; WRS -- simple 8x32 multiply routine
-        ; low 16 bits in main registers, high 16 bits in alternate registers
-        ; DE contains b, shifts left, HL contains accumulated result, A contains a, shifts right.
-        ld iy, #0       ; load parameters from stack
-        add iy, sp
-        ld a, 2(iy)     ; load a
-        ld e, 3(iy)     ; load low 16 bits of b
-        ld d, 4(iy)
-        and a           ; clear carry flag
-        sbc hl, hl      ; low result = 0
-        exx
-        sbc hl, hl      ; high result = 0
-        ld e, 5(iy)     ; load high 16 bits of b
-        ld d, 6(iy)
-        exx
-mulgo:                  ; loop executes at most 8 times (depends on highest bit set in a)
-        or a            ; test value of A
-        jr z, muldone   ; if A is now zero we are done
-        rra             ; shift A right one bit, rotate low bit into carry flag
-        jr nc, mulnext  ; if low bit was zero, skip the accumulate
-        add hl, de      ; add low 16 bits
-        exx
-        adc hl, de      ; add high 16 bits
-        exx
-mulnext:
-        and a           ; clear carry flag
-        rl e            ; double low 16 bits
-        rl d
-        exx
-        rl e            ; double high 16 bits
-        rl d
-        exx
-        jr mulgo        ; go again
-muldone:
-        exx             ; get the high 16 bits into DE
-        push hl
-        exx
-        pop de
-        ret             ; return with 32-bit result in DEHL, as per sdcc callng convention
-    __endasm;
-    a; b;  /* squelch compiler warning */
-}
-
-static const uint16_t mktime_moffset[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
-
-uint32_t ds1302_read_rtc(void)
-{
-    uint32_t ret;
-    uint8_t buffer[7];
-    uint8_t year, month, day, hour, minute, second;
-
-    ds1302_read_clock(buffer, 7); /* read all calendar data */
-
-    year   = from_bcd(buffer[6]);
-    month  = from_bcd(buffer[4] & 0x1F);
-    day    = from_bcd(buffer[3] & 0x3F);
-    if(buffer[2] & 0x80) /* AM/PM 12-hour mode */
-        hour   = from_bcd(buffer[2] & 0x1F) + (buffer[2] & 0x20 ? 12 : 0);
-    else /* sensible 24-hour mode */
-        hour   = from_bcd(buffer[2] & 0x3F);
-    minute = from_bcd(buffer[1]);
-    second = from_bcd(buffer[0] & 0x7F);
-
-    if(year < 70)
-        year += 100;
-
-    /* following code is based on utc_mktime() from ELKS 
-       https://github.com/jbruchon/elks/blob/master/elkscmd/sh_utils/date.c */
-
-    /* uses zero-based month index */
-    month--;
-
-    /* calculate days from years */
-    ret = multiply_8x32(year - 70, 365);
-
-    /* count leap days in preceding years */
-    ret += ((year - 69) >> 2);
-
-    /* calculate days from months */
-    ret += mktime_moffset[month];
-
-    /* add in this year's leap day, if any */
-    if (((year & 3) == 0) && (month > 1)) {
-        ret ++;
-    }
-
-    /* add in days in this month */
-    ret += (day - 1);
-
-    /* convert to hours */
-    ret = multiply_8x32(24, ret);
-    ret += hour;
-
-    /* convert to minutes */
-    ret = multiply_8x32(60, ret);
-    ret += minute;
-
-    /* convert to seconds */
-    ret = multiply_8x32(60, ret);
-    ret += second;
-
-    /* return the result */
-    return ret;
-}
-
-void ds1302_init(void)
-{
-    time_t tod;
-
-    /* initialise the hardware into a sensible state */
-    ds1302_set_pin_data_driven(true);
-    ds1302_set_pin_data(false);
-    ds1302_set_pin_ce(false);
-    ds1302_set_pin_clk(false);
-
-    tod.high = 0;                   /* until 2106 */
-    tod.low = ds1302_read_rtc();
-    wrtime(&tod);
+    return uint8_from_bcd(buffer & 0x7F); /* mask off top bit (clock-halt) */
 }
index 0c488e5..e57129b 100644 (file)
@@ -8,6 +8,8 @@ uint8_t rtc_secs(void);
    http://datasheets.maximintegrated.com/en/ds/DS1302.pdf table 3 */
 void ds1302_read_clock(uint8_t *buffer, uint8_t length);
 
+uint8_t uint8_from_bcd(uint8_t value);
+
 /* platform code must provide these functions */
 void ds1302_set_pin_clk(bool state);
 void ds1302_set_pin_ce(bool state);
diff --git a/Kernel/dev/ds1302_discard.c b/Kernel/dev/ds1302_discard.c
new file mode 100644 (file)
index 0000000..13aeecb
--- /dev/null
@@ -0,0 +1,141 @@
+/*-----------------------------------------------------------------------*/
+/* DS1202 and DS1302 Serial Real Time Clock driver                       */
+/* 2014-12-30 Will Sowerbutts                                            */
+/*-----------------------------------------------------------------------*/
+
+#include <kernel.h>
+#include <kdata.h>
+#include <stdbool.h>
+#include <printf.h>
+#include <ds1302.h>
+
+/****************************************************************************/
+/* Code in this file is used only once, at startup, so we want it to live   */
+/* in the DISCARD segment. sdcc only allows us to specify one segment for   */
+/* each source file.                                                        */
+/****************************************************************************/
+
+/* we avoid using 32x32 bit multiply ds1302_read_rtc, because it causes sdcc to pull 
+   in a huge __mullong helper -- which is nearly 500 bytes! */
+static uint32_t multiply_8x32(uint8_t a, uint32_t b) __naked /* return a * b */
+{
+    __asm
+        ; WRS -- simple 8x32 multiply routine
+        ; low 16 bits in main registers, high 16 bits in alternate registers
+        ; DE contains b, shifts left, HL contains accumulated result, A contains a, shifts right.
+        ld iy, #0       ; load parameters from stack
+        add iy, sp
+        ld a, 2(iy)     ; load a
+        ld e, 3(iy)     ; load low 16 bits of b
+        ld d, 4(iy)
+        and a           ; clear carry flag
+        sbc hl, hl      ; low result = 0
+        exx
+        sbc hl, hl      ; high result = 0
+        ld e, 5(iy)     ; load high 16 bits of b
+        ld d, 6(iy)
+        exx
+mulgo:                  ; loop executes at most 8 times (depends on highest bit set in a)
+        or a            ; test value of A
+        jr z, muldone   ; if A is now zero we are done
+        rra             ; shift A right one bit, rotate low bit into carry flag
+        jr nc, mulnext  ; if low bit was zero, skip the accumulate
+        add hl, de      ; add low 16 bits
+        exx
+        adc hl, de      ; add high 16 bits
+        exx
+mulnext:
+        and a           ; clear carry flag
+        rl e            ; double low 16 bits
+        rl d
+        exx
+        rl e            ; double high 16 bits
+        rl d
+        exx
+        jr mulgo        ; go again
+muldone:
+        exx             ; get the high 16 bits into DE
+        push hl
+        exx
+        pop de
+        ret             ; return with 32-bit result in DEHL, as per sdcc callng convention
+    __endasm;
+    a; b;  /* squelch compiler warning */
+}
+
+static const uint16_t mktime_moffset[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+uint32_t ds1302_read_rtc(void)
+{
+    uint32_t ret;
+    uint8_t buffer[7];
+    uint8_t year, month, day, hour, minute, second;
+
+    ds1302_read_clock(buffer, 7); /* read all calendar data */
+
+    year   = uint8_from_bcd(buffer[6]);
+    month  = uint8_from_bcd(buffer[4] & 0x1F);
+    day    = uint8_from_bcd(buffer[3] & 0x3F);
+    if(buffer[2] & 0x80) /* AM/PM 12-hour mode */
+        hour   = uint8_from_bcd(buffer[2] & 0x1F) + (buffer[2] & 0x20 ? 12 : 0);
+    else /* sensible 24-hour mode */
+        hour   = uint8_from_bcd(buffer[2] & 0x3F);
+    minute = uint8_from_bcd(buffer[1]);
+    second = uint8_from_bcd(buffer[0] & 0x7F);
+
+    if(year < 70)
+        year += 100;
+
+    /* following code is based on utc_mktime() from ELKS 
+       https://github.com/jbruchon/elks/blob/master/elkscmd/sh_utils/date.c */
+
+    /* uses zero-based month index */
+    month--;
+
+    /* calculate days from years */
+    ret = multiply_8x32(year - 70, 365);
+
+    /* count leap days in preceding years */
+    ret += ((year - 69) >> 2);
+
+    /* calculate days from months */
+    ret += mktime_moffset[month];
+
+    /* add in this year's leap day, if any */
+    if (((year & 3) == 0) && (month > 1)) {
+        ret ++;
+    }
+
+    /* add in days in this month */
+    ret += (day - 1);
+
+    /* convert to hours */
+    ret = multiply_8x32(24, ret);
+    ret += hour;
+
+    /* convert to minutes */
+    ret = multiply_8x32(60, ret);
+    ret += minute;
+
+    /* convert to seconds */
+    ret = multiply_8x32(60, ret);
+    ret += second;
+
+    /* return the result */
+    return ret;
+}
+
+void ds1302_init(void)
+{
+    time_t tod;
+
+    /* initialise the hardware into a sensible state */
+    ds1302_set_pin_data_driven(true);
+    ds1302_set_pin_data(false);
+    ds1302_set_pin_ce(false);
+    ds1302_set_pin_clk(false);
+
+    tod.high = 0;                   /* until 2106 */
+    tod.low = ds1302_read_rtc();
+    wrtime(&tod);
+}
index e12cbba..cc5d58e 100644 (file)
@@ -1,12 +1,14 @@
 CSRCS += devices.c main.c devtty.c devsdspi.c
 DSRCS = ../dev/devide.c ../dev/devsd.c ../dev/mbr.c ../dev/blkdev.c ../dev/ds1302.c
+DDSRCS = ../dev/devide_discard.c ../dev/devsd_discard.c ../dev/ds1302_discard.c
 ASRCS = crt0.s z180.s commonmem.s mark4.s ds1302-mark4.s monitor.s
 
 AOBJS = $(ASRCS:.s=.rel)
 COBJS = $(CSRCS:.c=.rel)
 DOBJS = $(patsubst ../dev/%.c,%.rel, $(DSRCS))
+DDOBJS = $(patsubst ../dev/%.c,%.rel, $(DDSRCS))
 
-OBJS  = $(AOBJS) $(COBJS) $(DOBJS)
+OBJS  = $(AOBJS) $(COBJS) $(DOBJS) $(DDOBJS)
 
 CROSS_CCOPTS += -I../dev/
 
@@ -23,6 +25,9 @@ $(COBJS): %.rel: %.c
 $(DOBJS): %.rel: ../dev/%.c
        $(CROSS_CC) $(CROSS_CCOPTS) -c $<
 
+$(DDOBJS): %.rel: ../dev/%.c
+       $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $<
+
 clean:
        rm -f $(OBJS) $(JUNK)  core *~ fuzix.com makecpmloader diskboot.bin
 
index a7fa673..82a930e 100644 (file)
@@ -33,11 +33,14 @@ swap.rel
 devsys.rel
 platform-n8vem-mark4/devtty.rel
 platform-n8vem-mark4/devide.rel
+platform-n8vem-mark4/devide_discard.rel
 platform-n8vem-mark4/devsd.rel
+platform-n8vem-mark4/devsd_discard.rel
 platform-n8vem-mark4/devsdspi.rel
 platform-n8vem-mark4/mbr.rel
 platform-n8vem-mark4/blkdev.rel
 platform-n8vem-mark4/ds1302.rel
+platform-n8vem-mark4/ds1302_discard.rel
 platform-n8vem-mark4/ds1302-mark4.rel
 platform-n8vem-mark4/monitor.rel
 -e
index f469c71..c92326f 100644 (file)
@@ -1,12 +1,14 @@
 CSRCS += devices.c main.c devtty.c devfd.c
 DSRCS = ../dev/blkdev.c ../dev/devide.c ../dev/mbr.c ../dev/ds1302.c
+DDSRCS = ../dev/devide_discard.c ../dev/ds1302_discard.c
 ASRCS = crt0.s z180.s commonmem.s p112.s ds1302-p112.s devfd2.s monitor.s flopboot.s
 
 AOBJS = $(ASRCS:.s=.rel)
 COBJS = $(CSRCS:.c=.rel)
 DOBJS = $(patsubst ../dev/%.c,%.rel, $(DSRCS))
+DDOBJS = $(patsubst ../dev/%.c,%.rel, $(DDSRCS))
 
-OBJS  = $(AOBJS) $(COBJS) $(DOBJS)
+OBJS  = $(AOBJS) $(COBJS) $(DOBJS) $(DDOBJS)
 
 CROSS_CCOPTS += -I../dev/
 
@@ -23,6 +25,9 @@ $(COBJS): %.rel: %.c
 $(DOBJS): %.rel: ../dev/%.c
        $(CROSS_CC) $(CROSS_CCOPTS) -c $<
 
+$(DDOBJS): %.rel: ../dev/%.c
+       $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $<
+
 clean:
        rm -f $(OBJS) $(JUNK)  core *~ fuzix.com fuzix-boot.fdd
 
index f0e51eb..2b0ec98 100644 (file)
@@ -33,9 +33,11 @@ swap.rel
 devsys.rel
 platform-p112/devtty.rel
 platform-p112/devide.rel
+platform-p112/devide_discard.rel
 platform-p112/blkdev.rel
 platform-p112/mbr.rel
 platform-p112/ds1302.rel
+platform-p112/ds1302_discard.rel
 platform-p112/ds1302-p112.rel
 platform-p112/monitor.rel
 platform-p112/devfd.rel