]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - common/cmd_fdc.c
* Get (mostly) rid of CFG_MONITOR_LEN definition; compute real length
[people/ms/u-boot.git] / common / cmd_fdc.c
index 712c14b57c7837fe85786fb2f31b56265f868cd0..3ee342fcfc06b838dd9e6b60fbd50b6a7848f627 100644 (file)
@@ -51,7 +51,7 @@
 #include <rtc.h>
 #endif
 
-#if (CONFIG_COMMANDS & CFG_CMD_FDC)
+#if ((CONFIG_COMMANDS & CFG_CMD_FDC) || (CONFIG_COMMANDS & CFG_CMD_FDOS))
 
 
 typedef struct {
@@ -173,21 +173,68 @@ const static FD_GEO_STRUCT floppy_type[2] = {
 
 static FDC_COMMAND_STRUCT cmd; /* global command struct */
 
+/* If the boot drive number is undefined, we assume it's drive 0             */
+#ifndef CFG_FDC_DRIVE_NUMBER
+#define CFG_FDC_DRIVE_NUMBER 0
+#endif
+
+/* Hardware access */
+#ifndef CFG_ISA_IO_STRIDE
+#define CFG_ISA_IO_STRIDE 1
+#endif
+
+#ifndef CFG_ISA_IO_OFFSET
+#define CFG_ISA_IO_OFFSET 0
+#endif
+
+
+#ifdef CONFIG_AMIGAONEG3SE
+unsigned char INT6_Status;
+
+void fdc_interrupt(void)
+{
+    INT6_Status = 0x80;
+}
+
+/* waits for an interrupt (polling) */
+int wait_for_fdc_int(void)
+{
+       unsigned long timeout;
+       timeout = FDC_TIME_OUT;
+       while(((volatile)INT6_Status & 0x80) == 0) {
+               timeout--;
+               udelay(10);
+               if(timeout == 0) /* timeout occured */
+                       return FALSE;
+       }
+       INT6_Status = 0;
+       return TRUE;
+}
+#endif
+   
 /* Supporting Functions */
 /* reads a Register of the FDC */
 unsigned char read_fdc_reg(unsigned int addr)
 {
-       volatile unsigned char *val = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS | addr);
-       return val[0];
+       volatile unsigned char *val =
+               (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS +
+                                          (addr * CFG_ISA_IO_STRIDE) +
+                                          CFG_ISA_IO_OFFSET);
+        
+       return val [0];
 }
 
 /* writes a Register of the FDC */
 void write_fdc_reg(unsigned int addr, unsigned char val)
 {
-               volatile unsigned char *tmp = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS | addr);
-               tmp[0]=val;
+        volatile unsigned char *tmp =
+               (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS +
+                                          (addr * CFG_ISA_IO_STRIDE) +
+                                          CFG_ISA_IO_OFFSET);
+       tmp[0]=val;
 }
 
+#ifndef CONFIG_AMIGAONEG3SE
 /* waits for an interrupt (polling) */
 int wait_for_fdc_int(void)
 {
@@ -202,6 +249,7 @@ int wait_for_fdc_int(void)
        return TRUE;
 }
 
+#endif
 
 /* reads a byte from the FIFO of the FDC and checks direction and RQM bit
    of the MSR. returns -1 if timeout, or byte if ok */
@@ -263,7 +311,9 @@ int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
        head = sect / pFG->sect; /* head nr */
        sect =  sect % pFG->sect; /* remaining blocks */
        sect++; /* sectors are 1 based */
-       PRINTF("Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",track,head,sect,pCMD->drive,pCMD->blnr);
+       PRINTF("Cmd 0x%02x Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",
+               pCMD->cmd[0],track,head,sect,pCMD->drive,pCMD->blnr);
+
        if(head|=0) { /* max heads = 2 */
                pCMD->cmd[DRIVE]=pCMD->drive | 0x04; /* head 1 */
                pCMD->cmd[HEAD]=(unsigned char) head; /* head register */
@@ -392,7 +442,7 @@ int fdc_seek(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
        return(fdc_issue_cmd(pCMD,pFG));
 }
 
-
+#ifndef CONFIG_AMIGAONEG3SE
 /* terminates current command, by not servicing the FIFO
  * waits for interrupt and fills in the result bytes */
 int fdc_terminate(FDC_COMMAND_STRUCT *pCMD)
@@ -406,6 +456,27 @@ int fdc_terminate(FDC_COMMAND_STRUCT *pCMD)
        }
        return TRUE;
 }
+#endif
+#ifdef CONFIG_AMIGAONEG3SE
+int fdc_terminate(FDC_COMMAND_STRUCT *pCMD)
+{
+       int i;
+       for(i=0;i<100;i++)
+               udelay(500); /* wait 500usec for fifo overrun */
+       while((INT6_Status&0x80)==0x00); /* wait as long as no int has occured */
+       for(i=0;i<7;i++) {
+               pCMD->result[i]=(unsigned char)read_fdc_byte();
+       }
+       INT6_Status = 0;
+       return TRUE;
+}
+
+#endif
+
+#ifdef CONFIG_AMIGAONEG3SE
+#define disable_interrupts() 0
+#define enable_interrupts() (void)0
+#endif
 
 /* reads data from FDC, seek commands are issued automatic */
 int fdc_read_data(unsigned char *buffer, unsigned long blocks,FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
@@ -526,6 +597,11 @@ retrycal:
        return TRUE;
 }
 
+#ifdef CONFIG_AMIGAONEG3SE
+#undef disable_interrupts()
+#undef enable_interrupts()
+#endif
+
 /* Scan all drives and check if drive is present and disk is inserted */
 int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
 {
@@ -538,20 +614,20 @@ int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
                select_fdc_drive(pCMD);
                pCMD->blnr=0; /* set to the 1st block */
                if(fdc_recalibrate(pCMD,pFG)==FALSE)
-                       break;
+                       continue;
                if((pCMD->result[STATUS_0]&0x10)==0x10)
-                       break;
+                       continue;
                /* ok drive connected check for disk */
                state|=(1<<drives);
                pCMD->blnr=pFG->size; /* set to the last block */
                if(fdc_seek(pCMD,pFG)==FALSE)
-                       break;
+                       continue;
                pCMD->blnr=0; /* set to the 1st block */
                if(fdc_recalibrate(pCMD,pFG)==FALSE)
-                       break;
+                       continue;
                pCMD->cmd[COMMAND]=FDC_CMD_READ_ID;
                if(fdc_issue_cmd(pCMD,pFG)==FALSE)
-                       break;
+                       continue;
                state|=(0x10<<drives);
        }
        stop_fdc_drive(pCMD);
@@ -566,21 +642,30 @@ int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
 }
 
 
+
 /**************************************************************************
 * int fdc_setup
 * setup the fdc according the datasheet
 * assuming in PS2 Mode
 */
-int fdc_setup(FDC_COMMAND_STRUCT *pCMD,        FD_GEO_STRUCT *pFG)
+int fdc_setup(int drive, FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
 {
-
        int i;
+
+#ifdef CONFIG_AMIGAONEG3SE
+       irq_install_handler(6, (interrupt_handler_t *)fdc_interrupt, NULL);
+       i8259_unmask_irq(6);
+#endif
+
+#ifdef CFG_FDC_HW_INIT
+        fdc_hw_init ();
+#endif
        /* first, we reset the FDC via the DOR */
        write_fdc_reg(FDC_DOR,0x00);
        for(i=0; i<255; i++) /* then we wait some time */
                udelay(500);
        /* then, we clear the reset in the DOR */
-       pCMD->drive=0;
+       pCMD->drive=drive;
        select_fdc_drive(pCMD);
        /* initialize the CCR */
        write_fdc_reg(FDC_CCR,pFG->rate);
@@ -600,9 +685,8 @@ int fdc_setup(FDC_COMMAND_STRUCT *pCMD,     FD_GEO_STRUCT *pFG)
                        PRINTF("Sense Interrupt for drive %d failed\n",i);
                }
        }
-       /* assuming drive 0 for rest of configuration
-        * issue the configure command */
-       pCMD->drive=0;
+       /* issue the configure command */
+       pCMD->drive=drive;
        select_fdc_drive(pCMD);
        pCMD->cmd[COMMAND]=FDC_CMD_CONFIGURE;
        if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
@@ -621,9 +705,77 @@ int fdc_setup(FDC_COMMAND_STRUCT *pCMD,    FD_GEO_STRUCT *pFG)
        /* then, we clear the reset in the DOR */
        /* fdc_check_drive(pCMD,pFG);   */
        /*      write_fdc_reg(FDC_DOR,0x04); */
+
        return TRUE;
 }
+#endif /* ((CONFIG_COMMANDS & CFG_CMD_FDC)||(CONFIG_COMMANDS & CFG_CMD_FDOS))*/
 
+#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
+
+/* Low level functions for the Floppy-DOS layer                              */
+
+/**************************************************************************
+* int fdc_fdos_init
+* initialize the FDC layer 
+* 
+*/
+int fdc_fdos_init (int drive)
+{
+       FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
+       FDC_COMMAND_STRUCT *pCMD = &cmd;
+    
+       /* setup FDC and scan for drives  */
+       if(fdc_setup(drive,pCMD,pFG)==FALSE) {
+               printf("\n** Error in setup FDC **\n");
+               return FALSE;
+       }
+       if(fdc_check_drive(pCMD,pFG)==FALSE) {
+               printf("\n** Error in check_drives **\n");
+               return FALSE;
+       }
+       if((pCMD->flags&(1<<drive))==0) {
+               /* drive not available */
+               printf("\n** Drive %d not available **\n",drive);
+               return FALSE;
+       }
+       if((pCMD->flags&(0x10<<drive))==0) {
+               /* no disk inserted */
+               printf("\n** No disk inserted in drive %d **\n",drive);
+               return FALSE;
+       }
+       /* ok, we have a valid source */
+       pCMD->drive=drive;
+
+       /* read first block */
+       pCMD->blnr=0;
+        return TRUE;
+}
+/**************************************************************************
+* int fdc_fdos_seek
+* parameter is a block number 
+*/
+int fdc_fdos_seek (int where)
+{
+       FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
+       FDC_COMMAND_STRUCT *pCMD = &cmd;
+
+        pCMD -> blnr = where ;
+        return (fdc_seek (pCMD, pFG));
+}
+/**************************************************************************
+* int fdc_fdos_read
+*  the length is in block number
+*/
+int fdc_fdos_read (void *buffer, int len)
+{
+       FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
+       FDC_COMMAND_STRUCT *pCMD = &cmd;
+
+        return (fdc_read_data (buffer, len, pCMD, pFG));
+}
+#endif  /* (CONFIG_COMMANDS & CFG_CMD_FDOS)                                  */
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDC)
 /****************************************************************************
  * main routine do_fdcboot
  */
@@ -641,11 +793,11 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
        switch (argc) {
        case 1:
                addr = CFG_LOAD_ADDR;
-               boot_drive=0; /* default boot from drive 0 */
+               boot_drive=CFG_FDC_DRIVE_NUMBER; 
                break;
        case 2:
                addr = simple_strtoul(argv[1], NULL, 16);
-               boot_drive=0; /* default boot from drive 0 */
+               boot_drive=CFG_FDC_DRIVE_NUMBER;
                break;
        case 3:
                addr = simple_strtoul(argv[1], NULL, 16);
@@ -656,7 +808,7 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                return 1;
        }
        /* setup FDC and scan for drives  */
-       if(fdc_setup(pCMD,pFG)==FALSE) {
+       if(fdc_setup(boot_drive,pCMD,pFG)==FALSE) {
                printf("\n** Error in setup FDC **\n");
                return 1;
        }