📄 floppyctrlr.cxx
字号:
/* * Copyright (C) 1998, 1999, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Driver for floppy drive: */#include <eros/target.h>#include <kerninc/kernel.hxx>#include <kerninc/MsgLog.hxx>#include <kerninc/Thread.hxx>#include <kerninc/AutoConf.hxx>#include <kerninc/util.h>#include <kerninc/DMA.hxx>#include <kerninc/Machine.hxx>#include <io.h>#include "IDT.hxx"#if 0DEFMODULE(Floppy, Probe, Attach, "Floppy Driver");struct DiskUnit;static ThreadPile IdleQ;const DMA::chan_t FloppyDmaChan = 2;const uint32_t SpindownDelay = 10000; /* 10 seconds */const uint32_t SpinupDelay = 40;#define READ_WRITE_TRIES 5/* Formatting parameters for various media in various drives. * Note that the order of these is chosen so that the first five * entries match the drive type encodings returned by the CMOS NVRAM. */struct MediaInfo { uint16_t totSectors; uint8_t secsPerTrack; uint8_t secsPerCyl; uint8_t nHd; uint8_t nCyl; uint8_t doubleStep; uint8_t gap; uint8_t dataRate; uint8_t spec1; uint8_t fmt_gap; char * name; uint8_t nextToTry;};static const MediaInfo MediaParams[] = { { 0, 0,0,0, 0,0,0x00,0x00,0x00,0x00,"None", 0 }, /* no testing */ { 720, 9,18,2,40,0,0x2A,0x02,0xDF,0x50,"360k", 0 }, /* 360kB PC diskettes */ /* Following entry used to have '6' in its nextToTry slot: */ { 2400,15,30,2,80,0,0x1B,0x00,0xDF,0x54,"1.2M", 0 }, /* 1.2 MB AT-diskettes */ { 1440, 9,18,2,80,0,0x2A,0x02,0xDF,0x50,"720K", 0 }, /* 720kB diskette */ { 2880,18,36,2,80,0,0x1B,0x00,0xCF,0x6C,"1.44M", 3 }, /* 1.44MB diskette */#if 0 /* we do not support these ancient pieces of crap. Actually, we * only support 360 kb and 720 kb because it's easier than * adjusting what the BIOS tells us. */ { 720, 9,18,2,40,1,0x2A,0x02,0xDF,0x50,NULL, 0 }, /* 360kB in 720kB drive */ { 720, 9,18,2,40,1,0x23,0x01,0xDF,0x50,NULL, 0 }, /* 360kB in 1.2MB drive */ { 1440, 9,18,2,80,0,0x23,0x01,0xDF,0x50,NULL, 0 }, /* 720kB in 1.2MB drive */#endif};const uint32_t StackSize = 1024;static uint32_t Stack[StackSize];struct FloppyCtrlr : public KernThread { /* Ports on the NEC 765 controller: */ struct NECREG { enum { DOR = 0x2, /* digital output register */ TDR = 0x3, /* tape drive register (not on NEC 765) */ STATUS = 0x4, /* status register */ DATA = 0x5, /* data register */ DIR = 0x7, /* digital input register: read only */ DCR = 0x7, /* Diskette control register: write only */ }; }; /* bits in the DOR register: */ struct DOR { enum { Motor3 = 0x80, /* set if indicated motor is spinning */ Motor2 = 0x40, Motor1 = 0x20, Motor0 = 0x10, DmaGate = 0x08, /* set for most commands */ Reset = 0x04, /* set for most commands */ DrvSel1 = 0x02, DrvSel0 = 0x01, }; }; struct STATUS { enum { Master = 0x80, /* host can send if set to 1 */ ReqRead = 0x40, /* 1 indicates read */ NonDMA = 0x20, /* set in specify command */ CmdBusy = 0x10, /* 1 if command in progress */ Drv3Busy = 0x08, Drv2Busy = 0x04, Drv1Busy = 0x02, Drv0Busy = 0x01, }; }; /* NEC Commands that we use: */ struct NECCMD { enum { VERSION = 0x10, CONFIGURE = 0x13, SPECIFY = 0x03, RECALIBRATE = 0x07, SENSEI = 0x08, SEEK = 0x0f, /* Floppy I/O operations */ READID = 0x4a, /* with MFM */ READ = 0xc6, /* with MT, MFM. 0xE6 with skip deleted */ WRITE = 0xc5, /* with MT, MFM */ FORMAT = 0x4d, /* with MFM */ }; }; /* Masks and values for Status Register 0: */ struct SR0 { enum { IC = 0xC0, /* interrupt code mask */ ICnormal = 0x00, /* normal completion */ ICabnormal = 0x40, /* failed */ ICbadcmd = 0x80, /* bad command */ ICpolled = 0xC0, /* interrupted by a poll operation. */ SeekEnd = 0x20, /* Seek completed */ EquipChk = 0x10, /* Equipment Check - 1 if recalibrate */ /* did not make it to track 0 or a * relative seek overran track 0 */ Head = 0x04, /* Head address mask */ Head0 = 0x00, Head1 = 0x04, DrvSel = 0x03, /* Drive select mask. Values are 0..3 */ }; }; struct SR1 { enum { CylEnd = 0x80, /* Hit end of cylinder */ BadCrc = 0x20, /* CRC on data or ID failed */ Overrun = 0x10, /* DMA service too slow */ NoData = 0x04, /* sector may have been deleted */ WriteProt = 0x02, /* Write Protected */ NoAddr = 0x01, /* Missing address mark */ }; }; #if 0 uint32_t id;#endif enum { NUNITS = 4 } ; uint8_t dor; int nresults; /* number of results from last operation */ uint8_t results[8]; /* actual result values */ DiskUnit *unit[NUNITS]; /* max four units per FloppyCtrlr */ bool spinning[NUNITS]; MediaInfo* mediaInfo[NUNITS];#if 0 static MediaInfo* mediaInfo; /* contains information regarding */ /* current media in drive */#endif FloppyCtrlr(); void Start(); void FdReadWrite(bool iswrite, uint32_t u, uint32_t cyl, uint32_t hd, uint32_t sec, uint32_t xferSecs); /* void FdWrite(uint32_t u, uint32_t cyl, uint32_t hd, uint32_t sec, uint32_t xferSecs); */ void FdSeek(uint32_t unit, uint32_t cyl, uint32_t hd); void OutFloppyCtrlr(uint8_t b); int GetResults(void); void Reset(void); void StartMotor(uint32_t unit); void StopMotor(uint32_t unit);};static FloppyCtrlr TheFloppyCtrlr;FloppyCtrlr::FloppyCtrlr() : KernThread("FloppyCtrlr", Prio::Normal, (void *)&FloppyCtrlr::Start, Stack, &Stack[StackSize]){#if 0 id = AutoConf::GetDeviceID();#endif SleepOn(IdleQ, Thread::Stall); /* we do not know the format of the media until the drive has been probed */ for (uint32_t i = 0; i < NUNITS; i++) { unit[i]->mediaInfo = 0; }}void FloppyCtrlr::Start(){ assert(DMA::alloc(FloppyDmaChan) == FloppyDmaChan); printf("Starting floppy controller... Thread 0x%08x\n", this); /* Unit status is initially unknown. Make sure all drives are spun * down, consistent with initial state of the DiskUnit structures: */ for (uint32_t u = 0; u < NUNITS; u++) { /* DiskUnit *curUnit = unit[u]; */ StopMotor(u); /* if (curUnit) * curUnit->format = -1; */ } for(;;) { uint64_t wakeTime = ~(0ll); for (uint32_t u = 0; u < NUNITS; u++) { DiskUnit *curUnit = unit[u]; uint64_t now = SysTimer::Now(); if (!curUnit) /* no unit */ continue; if (!curUnit->opq) { /* nothing to do */ /* If unit has been idle a while, spin it down: */ if (curUnit->isReady && curUnit->readyTimer <= now) { StopMotor(u); curUnit->readyTimer = 0ll; curUnit->isReady = false; } continue; } /* There is something to do on this unit * Figure out the new spindown time for the unit: */ uint64_t spinDownTime = now + SpindownDelay; if (curUnit->isReady == false) { /* Unit is not ready. Spin it up and make sure we wake up at * the appropriate time. */ if (curUnit->readyTimer == 0) { /* need to start the unit spinning up: */ StartMotor(u); uint64_t spinupTime = now + Machine::MillisecondsToTicks(SpinupDelay); curUnit->readyTimer = spinupTime; if (spinupTime < wakeTime) wakeTime = curUnit->readyTimer; continue; } else if (curUnit->readyTimer <= now) { /* drive has spun up */ curUnit->isReady = true; curUnit->readyTimer = spinDownTime; } else continue; } /* We're actually going to DO something, and the unit is ready. */ if (spinDownTime < wakeTime) wakeTime = spinDownTime; /* Now committed to at least one operation on curUnit. */ while(curUnit->opq) { printf("FloppyCtrl found request(s) on unit %d\n", u); /* get nest request */ UnitIoReq *uior = curUnit->opq; IoRequest *ior = uior->ioReq; Word ioSec = uior->start; Word ioCount = ior->ioCount; /* number of bytes to xfer */ Word ioAddr = ior->ioAddr; /* number of bytes to xfer */ bool started = false; assert(curUnit->mediaInfo); const MediaInfo *mediaInfo = curUnit->mediaInfo; while(ioCount) { uint32_t sec = ioSec;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -