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

📄 floppy.c~

📁 The main purpose of this project is to add a new scheduling algorithm to GeekOS and to implement a s
💻 C~
📖 第 1 页 / 共 2 页
字号:
/* * My feeble attempt at a floppy driver * Copyright (c) 2003, David H. Hovemeyer <daveho@cs.umd.edu> * $Revision: 1.22 $ *  * This is free software.  You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". */#include <geekos/screen.h>#include <geekos/string.h>#include <geekos/mem.h>#include <geekos/malloc.h>#include <geekos/int.h>#include <geekos/irq.h>#include <geekos/dma.h>#include <geekos/io.h>#include <geekos/timer.h>#include <geekos/kthread.h>#include <geekos/blockdev.h>#include <geekos/floppy.h>/* * NOTES: * The primary hardware target for this driver is Bochs 2.0. * Hopefully it will work on real hardware as well. *//* * Information sources * - Jeff's original GeekOS floppy driver * - http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html * - Intel 82077AA data sheet: *   http://www.nondot.org/sabre/os/files/Disk/82077AA_FloppyControllerDatasheet.pdf * - Frank van Gilluwe, _The Undocumented PC_, ISBN 0-201-47950-8, Chapter 10 *//* * TODO: * - Resetting the controller probably shouldn't require calibration, *   since there is no guarantee a disk will be in the drive. * - Need to really support multiple drives. *//* * History: * 23-Oct-2003: Works under Bochs 2.0 for read transfers. * 12-Nov-2003: Modified to use block device API. *//* ---------------------------------------------------------------------- * Definitions * ---------------------------------------------------------------------- *//* * Floppy controller IRQ */#define FDC_IRQ				6/* * Floppy DMA channel */#define FDC_DMA				2/* * I/O ports */#define FDC_BASE			0x3F0#define FDC_DOR_REG			0x3F2	 /*!< Digital output register (write) */#define FDC_STATUS_REG			0x3F4	 /*!< Main status regiser (read) */#define FDC_DATA_RATE_SELECT_REG	0x3F4	 /*!< Data rate select register (write) */#define FDC_DATA_REG			0x3F5	 /*!< Data register (read, write) *//* * Status register */#define FDC_STATUS_MRQ			(1 << 7)#define FDC_STATUS_DIO			(1 << 6)#define FDC_STATUS_NDMA			(1 << 5)#define FDC_STATUS_BUSY			(1 << 4)#define FDC_STATUS_ACTIVE(drive)	(1 << (drive))#define FDC_STATUS_READY_MASK		(FDC_STATUS_MRQ | FDC_STATUS_DIO)#define FDC_STATUS_READY_WRITE		FDC_STATUS_MRQ#define FDC_STATUS_READY_READ		(FDC_STATUS_MRQ | FDC_STATUS_DIO)/* * DOR (Digital Output Register) bits */#define FDC_DOR_MOTOR(drive)		(1 << ((drive) + 4))#define FDC_DOR_DMA_ENABLE		(1 << 3)#define FDC_DOR_RESET_DISABLE		(1 << 2)#define FDC_DOR_DRIVE_SELECT(drive)	((drive) & 0x3)/* * Commands */#define FDC_COMMAND_CALIBRATE		0x07#define FDC_COMMAND_SENSE_INT_STATUS	0x08#define FDC_COMMAND_SEEK		0x0F#define FDC_COMMAND_WRITE_SECTOR	0x05#define FDC_COMMAND_READ_SECTOR		0x06/* * Command bits */#define FDC_MULTI_TRACK			0x80#define FDC_MFM				0x40#define FDC_SKIP_DELETED		0x20/* * Status registers (from result phase) */#define FDC_ST0_SEEK_END		(1 << 5)#define FDC_ST0_IS_SUCCESS(code)	((((code) >> 6) & 0x3) == 0)/* * CMOS configuration * See: http://www.osdever.net/tutorials/detecting_floppy_drives.php */#define CMOS_OUT			0x70#define CMOS_IN				0x71#define CMOS_FLOPPY_INDEX		0x10enum { FLOPPY_READ, FLOPPY_WRITE };/*#define FLOPPY_DEBUG */#ifdef FLOPPY_DEBUG#  define Debug(args...) Print(args)#else#  define Debug(args...)#endif/* ---------------------------------------------------------------------- * Variables * ---------------------------------------------------------------------- *//* * Floppy drive parameters. */struct Floppy_Parameters {    int cylinders;    int heads;    int sectors;    int sectorSizeCode;    int gapLengthCode;};#define INVALID_FLOPPY_TYPE { -1, -1, -1, -1, -1 }/* * Parameters of known floppy types. * These are indexed by the floppy type reported in the CMOS. */static struct Floppy_Parameters s_floppyParamsTable[] = {    INVALID_FLOPPY_TYPE,	 /* not installed */    INVALID_FLOPPY_TYPE,	 /* TODO: 360K 5.25" */    INVALID_FLOPPY_TYPE,	 /* TODO: 1.2M 5.25" */    INVALID_FLOPPY_TYPE,	 /* TODO: 720K 3.5" */    {80, 2, 18, 0x02, 0x1C},	 /* 1.44M 3.5" */    INVALID_FLOPPY_TYPE,	 /* TODO: 2.88M 3.5" */};#define NUM_FLOPPY_TYPES (sizeof(s_floppyParamsTable) / sizeof(struct Floppy_Parameters))#define IS_VALID_FLOPPY_TYPE(type) \    ((type) < NUM_FLOPPY_TYPES && s_floppyParamsTable[(type)].cylinders > 0)/* * Parameters and state information about a floppy drive. */struct Floppy_Drive {    struct Floppy_Parameters *params;};/* * Parameters and state information about installed drives. */struct Floppy_Drive s_driveTable[2];/* * Flag to indicate that a floppy interrupt occurred. */static volatile int s_interruptOccurred;/* * Page of memory used for floppy DMA. */static uchar_t *s_transferBuf;/* * Queue of floppy block I/O requests. */static struct Block_Request_List s_floppyRequestQueue;/* * Thread queue where request processing thread sleeps waiting for * a request to arrive. */static struct Thread_Queue s_floppyWaitQueue;/* ---------------------------------------------------------------------- * Private functions * ---------------------------------------------------------------------- *//* * Implementation of Open for floppy driver. */static int Floppy_Open(struct Block_Device *dev){    KASSERT(!dev->inUse);    return 0;}/* * Implementation of Close for floppy driver. */static int Floppy_Close(struct Block_Device *dev){    KASSERT(dev->inUse);    return 0;}/* * Implementation of Get_Num_Blocks for floppy driver. */static int Floppy_Get_Num_Blocks(struct Block_Device *dev){    struct Floppy_Drive *drive;    struct Floppy_Parameters *params = drive->params;    KASSERT(dev->unit >= 0 && dev->unit <= 1);    drive = &s_driveTable[dev->unit];    params = drive->params;    KASSERT(params != 0);    return params->cylinders * params->heads * params->sectors;}/* * Block_Device_Ops for floppy driver. */static struct Block_Device_Ops s_floppyDeviceOps = {    Floppy_Open,    Floppy_Close,    Floppy_Get_Num_Blocks,};/* * Interrupt handler. * The floppy controller generally issues an interrupt * to notify the driver of the completion of a command. *//* * For now, we just set a flag that the driver * can busy-wait for. */static void Floppy_Interrupt_Handler(struct Interrupt_State* state){    Begin_IRQ(state);    Debug("Floppy_Interrupt_Handler!\n");    s_interruptOccurred = 1;    End_IRQ(state);}/* * Initialize drive parameters based on the floppy type returned * by the CMOS. */static void Setup_Drive_Parameters(int drive, int type){    if (IS_VALID_FLOPPY_TYPE(type)) {	struct Floppy_Parameters* params = &s_floppyParamsTable[type];	char devname[BLOCKDEV_MAX_NAME_LEN+1];	int rc;	snprintf(devname, sizeof(devname), "fd%d", drive);	Print("    %s: cyl=%d, heads=%d, sectors=%d\n", devname,		 params->cylinders, params->heads, params->sectors);	s_driveTable[drive].params = params;	/* Register the block device. */	rc = Register_Block_Device(devname, &s_floppyDeviceOps, drive, 0,	    &s_floppyWaitQueue, &s_floppyRequestQueue);	if (rc != 0)	    Print("  Error: could not create block device for %s\n", devname);    }}/* * Convert LBA address to CHS. */static void LBA_To_CHS(struct Floppy_Drive* drive, int lba, int *cylinder, int *head, int *sector){    struct Floppy_Parameters* params = drive->params;    KASSERT(params != 0);    *cylinder = lba / (params->heads * params->sectors);    *head = (lba / params->sectors) % params->heads;    *sector = (lba % params->sectors) + 1;    KASSERT(*cylinder >= 0 && *cylinder < params->cylinders);    KASSERT(*head >= 0 && *head < params->heads);    KASSERT(*sector > 0 && *sector <= params->sectors);}/* * Wait for the MRQ bit to be set in the main status register. * This indicates that the controller is ready to accept data * or send data via the data register. */static void Wait_For_MRQ(uchar_t readyValue){    KASSERT(readyValue == FDC_STATUS_READY_READ || readyValue == FDC_STATUS_READY_WRITE);    /* Wait for MRQ bit to be set in main status register */    while ((In_Byte(FDC_STATUS_REG) & FDC_STATUS_READY_MASK) != readyValue)	;    /*Debug("Ready to accept command!\n"); */}/* * Get a byte from the data register. */static uchar_t Floppy_In(void){    Wait_For_MRQ(FDC_STATUS_READY_READ);    return In_Byte(FDC_DATA_REG);}/* * Write a byte to the data register.

⌨️ 快捷键说明

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