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

📄 at_wini.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 3 页
字号:
10698	                }
10699	        }
10700	
10701	        /* For each sector, wait for an interrupt and fetch the data (read),
10702	         * or supply data to the controller and wait for an interrupt (write).
10703	         */
10704	
10705	        if (w_opcode == DEV_READ) {
10706	                if ((r = w_intr_wait()) == OK) {
10707	                        /* Copy data from the device's buffer to user space. */
10708	
10709	                        port_read(wn->base + REG_DATA, tp->phys, SECTOR_SIZE);
10710	
10711	                        tp->phys += SECTOR_SIZE;
10712	                        tp->iop->io_nbytes -= SECTOR_SIZE;
10713	                        w_count -= SECTOR_SIZE;
10714	                        if ((tp->count -= SECTOR_SIZE) == 0) tp++;
10715	                } else {
10716	                        /* Any faulty data? */
10717	                        if (w_status & STATUS_DRQ) {
10718	                                port_read(wn->base + REG_DATA, tmp_phys,
10719	                                                                SECTOR_SIZE);
10720	                        }
10721	                }
10722	        } else {
10723	                /* Wait for data requested. */
10724	                if (!waitfor(STATUS_DRQ, STATUS_DRQ)) {
10725	                        r = ERR;
10726	                } else {
10727	                        /* Fill the buffer of the drive. */
10728	
10729	                        port_write(wn->base + REG_DATA, tp->phys, SECTOR_SIZE);
10730	                        r = w_intr_wait();
10731	                }
10732	
10733	                if (r == OK) {
10734	                        /* Book the bytes successfully written. */
10735	
10736	                        tp->phys += SECTOR_SIZE;
10737	                        tp->iop->io_nbytes -= SECTOR_SIZE;
10738	                        w_count -= SECTOR_SIZE;
10739	                        if ((tp->count -= SECTOR_SIZE) == 0) tp++;
10740	                }
10741	        }
10742	
10743	        if (r != OK) {
10744	                /* Don't retry if sector marked bad or too many errors */
10745	                if (r == ERR_BAD_SECTOR || ++errors == MAX_ERRORS) {
10746	                        w_command = CMD_IDLE;
10747	                        return(tp->iop->io_nbytes = EIO);
10748	                }
10749	
10750	                /* Reset if halfway, but bail out if optional I/O. */
10751	                if (errors == MAX_ERRORS / 2) {
10752	                        w_need_reset();
10753	                        if (tp->iop->io_request & OPTIONAL_IO) {
10754	                                w_command = CMD_IDLE;
10755	                                return(tp->iop->io_nbytes = EIO);
10756	                        }
10757	                }
10758	                continue;       /* Retry */
10759	        }
10760	        errors = 0;
10761	  } while (w_count > 0);
10762	
10763	  w_command = CMD_IDLE;
10764	  return(OK);
10765	}
	
	
10768	/*============================================================================*
10769	 *                              com_out                                       *
10770	 *============================================================================*/
10771	PRIVATE int com_out(cmd)
10772	struct command *cmd;            /* Command block */
10773	{
10774	/* Output the command block to the winchester controller and return status */
10775	
10776	  struct wini *wn = w_wn;
10777	  unsigned base = wn->base;
10778	
10779	  if (!waitfor(STATUS_BSY, 0)) {
10780	        printf("%s: controller not ready\n", w_name());
10781	        return(ERR);
10782	  }
10783	
10784	  /* Select drive. */
10785	  out_byte(base + REG_LDH, cmd->ldh);
10786	
10787	  if (!waitfor(STATUS_BSY, 0)) {
10788	        printf("%s: drive not ready\n", w_name());
10789	        return(ERR);
10790	  }
10791	
10792	  /* Schedule a wakeup call, some controllers are flaky. */
10793	  clock_mess(WAKEUP, w_timeout);
10794	
10795	  out_byte(base + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0);
10796	  out_byte(base + REG_PRECOMP, cmd->precomp);
10797	  out_byte(base + REG_COUNT, cmd->count);
10798	  out_byte(base + REG_SECTOR, cmd->sector);
10799	  out_byte(base + REG_CYL_LO, cmd->cyl_lo);
10800	  out_byte(base + REG_CYL_HI, cmd->cyl_hi);
10801	  lock();
10802	  out_byte(base + REG_COMMAND, cmd->command);
10803	  w_command = cmd->command;
10804	  w_status = STATUS_BSY;
10805	  unlock();
10806	  return(OK);
10807	}
	
	
10810	/*===========================================================================*
10811	 *                              w_need_reset                                 *
10812	 *===========================================================================*/
10813	PRIVATE void w_need_reset()
10814	{
10815	/* The controller needs to be reset. */
10816	  struct wini *wn;
10817	
10818	  for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
10819	        wn->state |= DEAF;
10820	        wn->state &= ~INITIALIZED;
10821	  }
10822	}
	
	
10825	/*============================================================================*
10826	 *                              w_do_close                                    *
10827	 *============================================================================*/
10828	PRIVATE int w_do_close(dp, m_ptr)
10829	struct driver *dp;
10830	message *m_ptr;
10831	{
10832	/* Device close: Release a device. */
10833	
10834	  if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
10835	  w_wn->open_ct--;
10836	  return(OK);
10837	}
	
	
10840	/*============================================================================*
10841	 *                              com_simple                                    *
10842	 *============================================================================*/
10843	PRIVATE int com_simple(cmd)
10844	struct command *cmd;            /* Command block */
10845	{
10846	/* A simple controller command, only one interrupt and no data-out phase. */
10847	  int r;
10848	
10849	  if ((r = com_out(cmd)) == OK) r = w_intr_wait();
10850	  w_command = CMD_IDLE;
10851	  return(r);
10852	}
	
	
10855	/*===========================================================================*
10856	 *                              w_timeout                                    *
10857	 *===========================================================================*/
10858	PRIVATE void w_timeout()
10859	{
10860	  struct wini *wn = w_wn;
10861	
10862	  switch (w_command) {
10863	  case CMD_IDLE:
10864	        break;          /* fine */
10865	  case CMD_READ:
10866	  case CMD_WRITE:
10867	        /* Impossible, but not on PC's:  The controller does not respond. */
10868	
10869	        /* Limiting multisector I/O seems to help. */
10870	        if (wn->max_count > 8 * SECTOR_SIZE) {
10871	                wn->max_count = 8 * SECTOR_SIZE;
10872	        } else {
10873	                wn->max_count = SECTOR_SIZE;
10874	        }
10875	        /*FALL THROUGH*/
10876	  default:
10877	        /* Some other command. */
10878	        printf("%s: timeout on command %02x\n", w_name(), w_command);
10879	        w_need_reset();
10880	        w_status = 0;
10881	        interrupt(WINCHESTER);
10882	  }
10883	}
	
	
10886	/*===========================================================================*
10887	 *                              w_reset                                      *
10888	 *===========================================================================*/
10889	PRIVATE int w_reset()
10890	{
10891	/* Issue a reset to the controller.  This is done after any catastrophe,
10892	 * like the controller refusing to respond.
10893	 */
10894	
10895	  struct wini *wn;
10896	  int err;
10897	
10898	  /* Wait for any internal drive recovery. */
10899	  milli_delay(RECOVERYTIME);
10900	
10901	  /* Strobe reset bit */
10902	  out_byte(w_wn->base + REG_CTL, CTL_RESET);
10903	  milli_delay(1);
10904	  out_byte(w_wn->base + REG_CTL, 0);
10905	  milli_delay(1);
10906	
10907	  /* Wait for controller ready */
10908	  if (!w_waitfor(STATUS_BSY | STATUS_RDY, STATUS_RDY)) {
10909	        printf("%s: reset failed, drive busy\n", w_name());
10910	        return(ERR);
10911	  }
10912	
10913	  /* The error register should be checked now, but some drives mess it up. */
10914	
10915	  for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
10916	        if (wn->base == w_wn->base) wn->state &= ~DEAF;
10917	  }
10918	  return(OK);
10919	}
	
	
10922	/*============================================================================*
10923	 *                              w_intr_wait                                   *
10924	 *============================================================================*/
10925	PRIVATE int w_intr_wait()
10926	{
10927	/* Wait for a task completion interrupt and return results. */
10928	
10929	  message mess;
10930	  int r;
10931	
10932	  /* Wait for an interrupt that sets w_status to "not busy". */
10933	  while (w_status & STATUS_BSY) receive(HARDWARE, &mess);
10934	
10935	  /* Check status. */
10936	  lock();
10937	  if ((w_status & (STATUS_BSY | STATUS_RDY | STATUS_WF | STATUS_ERR))
10938	                                                        == STATUS_RDY) {
10939	        r = OK;
10940	        w_status |= STATUS_BSY; /* assume still busy with I/O */
10941	  } else
10942	  if ((w_status & STATUS_ERR) && (in_byte(w_wn->base + REG_ERROR) & ERROR_BB)) {
10943	        r = ERR_BAD_SECTOR;     /* sector marked bad, retries won't help */
10944	  } else {
10945	        r = ERR;                /* any other error */
10946	  }
10947	  unlock();
10948	  return(r);
10949	}
	
	
10952	/*==========================================================================*
10953	 *                              w_waitfor                                   *
10954	 *==========================================================================*/
10955	PRIVATE int w_waitfor(mask, value)
10956	int mask;                       /* status mask */
10957	int value;                      /* required status */
10958	{
10959	/* Wait until controller is in the required state.  Return zero on timeout. */
10960	
10961	  struct milli_state ms;
10962	
10963	  milli_start(&ms);
10964	  do {
10965	       if ((in_byte(w_wn->base + REG_STATUS) & mask) == value) return 1;
10966	  } while (milli_elapsed(&ms) < TIMEOUT);
10967	
10968	  w_need_reset();       /* Controller gone deaf. */
10969	  return(0);
10970	}
	
	
10973	/*==========================================================================*
10974	 *                              w_handler                                   *
10975	 *==========================================================================*/
10976	PRIVATE int w_handler(irq)
10977	int irq;
10978	{
10979	/* Disk interrupt, send message to winchester task and reenable interrupts. */
10980	
10981	  w_status = in_byte(w_wn->base + REG_STATUS);  /* acknowledge interrupt */
10982	  interrupt(WINCHESTER);
10983	  return 1;
10984	}
	
	
10987	/*============================================================================*
10988	 *                              w_geometry                                    *
10989	 *============================================================================*/
10990	PRIVATE void w_geometry(entry)
10991	struct partition *entry;
10992	{
10993	  entry->cylinders = w_wn->lcylinders;
10994	  entry->heads = w_wn->lheads;
10995	  entry->sectors = w_wn->lsectors;
10996	}
10997	#endif /* ENABLE_AT_WINI */

⌨️ 快捷键说明

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