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

📄 floppyctrlr.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -