⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fl_drver.c

📁 ertfs文件系统里面既有完整ucos程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright Peter Van Oudenaren , 1993
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/

/* fl_drver.c - Generic floppy disk driver routines.

    Routines in this file are generic routines to control an NEC765 class
    floppy disk controller in AT mode. The routines should be independent 
    of executive environment and of the system hosting the 765 controller.

Public routines:
  These routines are  pointed to by the RTFS bdevsw table.

    floppy_ioctl        -   IO control function. Does nothing
    floppy_open         -   Drive open routine. Initializes the controller and
                            establishes interrupt vector if open count is zero.
                            Increments the open count.
    floppy_close        -   Decreases the open count. If the open count goes
                            to zero it releases interrupts.
    floppy_io           -   Performs reads/writes on the drives

  This routine is public but is not in the device table. You may call it 
  directly. 

    fl_format           -   
  
  The rest of the routines are internal to the driver.

    fl_claim            -   Claims the controller for a drive. Establishes 
                            the media type if need be and sets the data rate
                            so the disk may be read/written.
    fl_establish_media  -   Determines the media type of the floppy disk in
                            the drive by varying the data rate and attempting to
                            read the sector ID off of the disk. Also seeks the
                            head to clear the disk changed line.
    fl_sense_interrupt  -   Requests sense (staust registers) from the floppy 
                            after reset,recal and seek
    fl_read_id          -   Reads sector IDs from a floppy. Used by establish
                            media
    fl_seek             -   Seeks the head.
    fl_recalibrate      -   Seeks the head to track 0 and resets chips internal 
                            head position counter
    fl_specify          -   Specify head load/unload times and seek step rate
    fl_controller_init  -   Clears internal floppy tables, establishes interrupts
                            and resets the 765 chip.
    fl_reset_controller -   Called by fl_controller_init. Issues a reset to 
                            the chip.
    fl_motor_on         -   Turns the floppy motor on and starts a daemon to 
                            shut it off.
    fl_motor_off        -   The daemon calls this to shut off the floppy motor
    fl_command_phase    -   Sends command phase values to the chip. Called by
                            higher level routines like fl_read_id, fl_io etc.
    fl_results_phase    -   Reads results phase values from the chip. Called by
                            higher level routines like fl_read_id, fl_io etc.
    fl_ready            -   Determines what data transfer state the floppy 
                            controller's state machine is in. TO, FROM or 
                            none.
    fl_change_line      -   Called by floppy_io to check the drive's change
                            line to see if the floppy disk has been removed.
                            If the drive has been removed we call establish
                            media to clear it. We should probaly add a call 
                            back mechanism here to alert the user to replace the
                            disk and possibly to give the file system a
                            chance to recover.
    fl_cp_parms         -   Copy parameters from the parameter table to the
                            _floppy structure.
    fl_dma_chk          -   Takes an address and returns the number of blocks
                            that may be transferd to that address before a 
                            dma segment wrap occurs.
    fl_dma_init         -   Sets up the dma controller for a to or from memory
                            transfer from/to the floppy controller
    fl_read_data        -   Reads a byte from the 765 data register
    fl_read_drr         -   Reads a byte from the 765 data rate register
    fl_read_msr         -   Reads a byte from the 765 master status register
    fl_write_data       -   Writes a byte to the 765 data register
    fl_write_dor        -   Writes a byte to the 765 digital output register
    fl_write_drr        -   Writes a byte to the 765 data rate register
    fl_report_error     -   Converts floppy errors to strings and prints them
    fl_waitdma          -   Waits for dma to complete and checks status
    fl_waitint          -   Waits for a floppy disk interrupt. Or tiomes out

*/

#include <pcdisk.h>
/*#include <stdio.h>   */

#if USE_FLOPPY
#include <dos.h>
#include <conio.h>
#include <ctype.h>

#if (defined(ERTFS_SA))
void hook_floppy_interrupt(int irq);
void ks_clear_floppy_signal(void);
void ks_invoke_floppy_interrupt(int controller_no);
#define OS_FLOPPY_SIGNAL_BIND(X)
#define OS_FLOPPY_SIGNAL_CLEAR(X)   ks_clear_floppy_signal()
#endif

byte os_floppy_type(int driveno);

#if (USE_DMA)

#ifdef PME
/* for pmiSetBaseAddr(), etc */
//#include "pme.h"
//#include "cpmi.h"
#endif

#if (N_FLOPPY_UNITS > 2)
#error Reduce N_FLOPPY_UNITS in PCCONF.H. Floppy driver supports up to 2 drives.
#endif

#if !defined(PME)
extern unsigned char _dma_buffer[512];
extern DMAPTYPE dma_buffer;

DMAPTYPE alloc_dma_buffer(void)
{
    return((DMAPTYPE) &_dma_buffer[0]);
}
#endif // PME

static void far_copybuf(DMAPTYPE to, DMAPTYPE from, int size)
{
    while (size--)
        *to++ = *from++;
}

//DM: added
#if defined(PME)
#define DMA_BUF_SECTS  18
#define LO_BUF_SIZE    (DMA_BUF_SECTS*512)
/* USER: The absolute address below is the start of the DMA buffer used when
   running under pmEasy.  Set it to an unused location in real memory.
   Ensure the buffer is not split across 64K boundary (size is LO_BUF_SIZE).
   This buffer is necessary because the DMA controller can not write to
   the user buffer in extended memory. It can only write to mem below 1MB. */
#define LO_BUF_SEG 0x9000  
word lo_buf_sel = 0;
byte far *lo_buf_prot;  // needed by us for copying results to/from user's buffer
byte far *lo_buf_real;  // needed by DMA controller to initiate read/write
#endif

#endif /* USE_DMA */


#if (!USE_DMA)
int polled_read(byte KS_FAR *buffer, word n, byte cmd);
int polled_write(byte KS_FAR *buffer, word n, byte cmd);
#endif

/* Shadow of the digital output register. We write to this each time we
   write to the dig. output reg. */
extern byte shadow_dig_out;
extern int shut_mo_off_in;
extern _FL_DEVPARMS fl_devparms[7];

/* Current selected floppy for use by fl_claim. 
 Note: We use the following confusing convention:
    0 = None selected
    1 = Drive one selected
    2 = Drive two selected
  This is confusing because usually driveno == 0, 1 for the first two drives */
/* Open function. This is pointed to by the bdevsw[] table */
extern int fl_controller_open_count;
extern int selected_floppy;
extern _FLOPPY floppy[N_FLOPPY_UNITS];
static BOOLEAN change_checked[N_FLOPPY_UNITS];

BOOLEAN floppy_open(void);
BOOLEAN floppy_io(int driveno, dword l_sector, void KS_FAR *in_buffer, word count, BOOLEAN reading);
BOOLEAN floppy_format(int  driveno, int drivesize, int interleave);
static BOOLEAN fl_controller_init(void);
static BOOLEAN fl_reset_controller(void);
static BOOLEAN fl_claim(int driveno);
BOOLEAN fl_establish_media(int  driveno);
static BOOLEAN fl_sense_interrupt(COMMAND_BLOCK *p);
static BOOLEAN fl_read_id(int  driveno, COMMAND_BLOCK *p);
static BOOLEAN fl_seek(int  driveno, word cyl, word head);
static BOOLEAN fl_recalibrate(int  driveno);
static BOOLEAN fl_specify(int  driveno);
void fl_motor_off(void);
static void fl_motor_on(int  driveno);
static BOOLEAN fl_command_phase(COMMAND_BLOCK *p);
static BOOLEAN fl_results_phase(COMMAND_BLOCK *p);
static int fl_ready(void);
BOOLEAN fl_change_line(int driveno);
static void fl_cp_parms(int  driveno, int parmindex);
static BOOLEAN fl_waitint(int ticks);
static BOOLEAN fl_report_error(int error, BOOLEAN return_me);
#if (USE_DMA)
static BOOLEAN fl_waitdma(int ticks);
static BOOLEAN fl_dma_init(DMAPTYPE in_address, word length, BOOLEAN reading);
//DM: added conditional to comment out if !PME
#if !defined(PME)
static word fl_dma_chk(DMAPTYPE in_address);
#endif
#endif
static void  fl_write_drr(byte value);
static byte fl_read_drr(void);
static void  fl_write_dor(byte value);
static void  fl_write_data(byte value);
static byte fl_read_data(void);
static byte fl_read_msr(void);

/* floppy_isr() - Implementation specific ISR routines.
*
*   This routine is the IBM-PC specific interupt service routine. It 
*   calls ide_interrupt(controller_number), the platform independent
*   portion of the interrupt routine, and then clears the PIC
*
*/
void  KS_FAR floppy_isr(int controller_no)                          /*__fn__*/
{
    /* Signal interrupt complete */
    ks_invoke_floppy_interrupt(controller_no);
}


BOOLEAN _floppy_open(void);


BOOLEAN floppy_open(void)                                    /*__fn__*/
{
    int i;

    for (i = 0; i < 3; i++)
        if (_floppy_open())
            return(TRUE);
    return(FALSE);
}

BOOLEAN _floppy_open(void)                                           /*__fn__*/
{
#if (USE_DMA)
//DM: added:
#if defined(PME)
  #ifdef FM 
    lo_buf_prot = (byte *) (LO_BUF_SEG << 4);
    lo_buf_real = (byte *) (LO_BUF_SEG << 4);  // is actually linear address, not far pointer
  #else
    if (lo_buf_sel == 0)
    {
        if (pmiAllocLD(1, &lo_buf_sel) != 0)
            return(FALSE);   /* error: insuff descr */
        pmiSetBaseAddr(lo_buf_sel, (dword)LO_BUF_SEG << 4);
        pmiSetLimit(lo_buf_sel, (dword)LO_BUF_SIZE - 1);
        pmiSetRights(lo_buf_sel, wData, 0);
        lo_buf_prot = (byte far *)MK_FP(lo_buf_sel,0);
        lo_buf_real = (byte far *)MK_FP(LO_BUF_SEG,0);
    }
  #endif
//DM: (end of added)
#else //DM: added #else -- real mode case

    /* Make sure we have a dma buffer in real memory. if not fail */
    if (!dma_buffer)
        dma_buffer = alloc_dma_buffer();
    if (!dma_buffer)
        return(FALSE);
 #endif //DM: added #endif
#endif
    /* Initialize the controller */
    if (!fl_controller_open_count)
    {
        if (!fl_controller_init())
            return(FALSE);
    }
    fl_controller_open_count += 1;
    return(TRUE);
}

/* floppy_down() - Note that the floppy disk either not installed or
*  not formatted. Sets the media type to NONE.
*
*
*/
void floppy_down(int driveno)                                   /*__fn__*/
{
    floppy[driveno].media_type = (byte) DT_NONE;
    selected_floppy = 0;
}

/* Check if a floppy disk is installed. */

BOOLEAN floppy_installed(int driveno)                                   /*__fn__*/
{
    if (fl_claim(driveno))
        return(TRUE);
    else
        floppy_down(driveno);
    return(FALSE);
}



/* floppy_io - Floppy disk read write routine (in bdevsw[] table.)
* 
* Summary:
*
* BOOLEAN floppy_io(driveno, l_sector, in_buffer,  count, reading)
*
*
* Inputs:
*   word driveno      - 0 or 1 = a: b:
*   dword l_sector      - absolute sector to read/write
*   void *in_buffer     - address of data buffer
*   word count        - sectors to transfer
*   BOOLEAN reading        - TRUE if a read FALSE if a write
*
* Returns:
*   TRUE on success else FALSE.
*   
* This routine performs read and writes from to the floppy disk. It calculates
* head:sector:track from the physical sector number, then it reads/write of 
* track or count, whichever is less. If more data needs to be transfered it
* adjusts the current sector number, recalculates head:sector:track and repeats
* the IO procedure. This occurs until the process is completed.
*
* Note: On a PC AT the dma controller is a 16 BIT device. A 4 bit bank
*       switch register is used to address the lower 1 MEG. A segment 
*       wrap occurs when a transfer spans two banks. When this routine
*       senses this condition it breaks the request into two or 
*       more operations so the wrap does not occur.
*
* Note: This routine is basically portable except for the the DMA wrap 
*       calculation. Also in protected mode 386/486 systems a double
*       buffering scheme needs to be added since we can only dma to the
*       first 1 meg. This double buffer logic will be identical to the
*       logic used for double buffering in the DMA segment wrap situation, 
*       the only exception being the transfer should be larger than 1.
*       
*/

BOOLEAN _floppy_io(DDRIVE *pdr, dword l_sector, void KS_FAR *in_buffer, word count, BOOLEAN reading);

BOOLEAN floppy_io(int driveno, dword l_sector, void KS_FAR *in_buffer, word count, BOOLEAN reading)   /*__fn__*/
{
int i;
DDRIVE *pdr;

    pdr = pc_drno_to_drive_struct(driveno);
    if (pdr)
    {
        for (i = 0; i < 3; i++)
            if(_floppy_io(pdr, l_sector, in_buffer, count, reading))
                return(TRUE);
    }
    return(FALSE);
}

BOOLEAN _floppy_io(DDRIVE *pdr, dword l_sector, void KS_FAR *in_buffer, word count, BOOLEAN reading)   /*__fn__*/
{
    COMMAND_BLOCK b;
    word cyl;
    word head;
    word sec;
    word final_sec;
    word final_cyl;
    word final_head;
    word utemp;
    word sector;
    word nleft_track;
    word n_todo;
    byte  KS_FAR *buffer = (byte KS_FAR *) in_buffer;    
    int  unit_number;
#if (!USE_DMA)
    int i;
    int ready;
#else
   #if !defined(PME) //DM: added this conditional around use_dma_buff
    BOOLEAN   use_dma_buff;
   #endif
#endif

    unit_number = pdr->logical_unit_number;

    if (!count)                         /* Must have a count */
        return(FALSE);

    /* Establish media if the drive is different from before */
    /* fl_claim has its own error reporting */
    if (!fl_claim(unit_number))
        return(FALSE);
    sector = (word) l_sector;

    /* cylinder == sector / sectors/cylinder */
    cyl =   (word) (sector/floppy[unit_number].sectors_per_cyl);
    utemp = (word) (sector%floppy[unit_number].sectors_per_cyl);
    head =  (word) (utemp/floppy[unit_number].sectors_per_track);
    sec =   (word) (utemp%floppy[unit_number].sectors_per_track);

    nleft_track = (word) (floppy[unit_number].sectors_per_track - sec);
    if (count > nleft_track)
        n_todo =  nleft_track;
    else 
        n_todo = count;

    while (count)
    {
        if (fl_change_line(unit_number))
        {
            /* establish media. It has a hack in here to clear change line */
            /* establish media has its own error reporting */
            if (!fl_establish_media(unit_number))
                return(FALSE);
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -