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

📄 at_wini.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 3 页
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
				src/kernel/at_wini.c	 	 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

10100	/* This file contains the device dependent part of a driver for the IBM-AT
10101	 * winchester controller.
10102	 * It was written by Adri Koppes.
10103	 *
10104	 * The file contains one entry point:
10105	 *
10106	 *   at_winchester_task:        main entry when system is brought up
10107	 *
10108	 *
10109	 * Changes:
10110	 *      13 Apr 1992 by Kees J. Bot: device dependent/independent split.
10111	 */
10112	
10113	#include "kernel.h"
10114	#include "driver.h"
10115	#include "drvlib.h"
10116	
10117	#if ENABLE_AT_WINI
10118	
10119	/* I/O Ports used by winchester disk controllers. */
10120	
10121	/* Read and write registers */
10122	#define REG_BASE0       0x1F0   /* base register of controller 0 */
10123	#define REG_BASE1       0x170   /* base register of controller 1 */
10124	#define REG_DATA            0   /* data register (offset from the base reg.) */
10125	#define REG_PRECOMP         1   /* start of write precompensation */
10126	#define REG_COUNT           2   /* sectors to transfer */
10127	#define REG_SECTOR          3   /* sector number */
10128	#define REG_CYL_LO          4   /* low byte of cylinder number */
10129	#define REG_CYL_HI          5   /* high byte of cylinder number */
10130	#define REG_LDH             6   /* lba, drive and head */
10131	#define   LDH_DEFAULT           0xA0    /* ECC enable, 512 bytes per sector */
10132	#define   LDH_LBA               0x40    /* Use LBA addressing */
10133	#define   ldh_init(drive)       (LDH_DEFAULT | ((drive) << 4))
10134	
10135	/* Read only registers */
10136	#define REG_STATUS          7   /* status */
10137	#define   STATUS_BSY            0x80    /* controller busy */
10138	#define   STATUS_RDY            0x40    /* drive ready */
10139	#define   STATUS_WF             0x20    /* write fault */
10140	#define   STATUS_SC             0x10    /* seek complete (obsolete) */
10141	#define   STATUS_DRQ            0x08    /* data transfer request */
10142	#define   STATUS_CRD            0x04    /* corrected data */
10143	#define   STATUS_IDX            0x02    /* index pulse */
10144	#define   STATUS_ERR            0x01    /* error */
10145	#define REG_ERROR           1   /* error code */
10146	#define   ERROR_BB              0x80    /* bad block */
10147	#define   ERROR_ECC             0x40    /* bad ecc bytes */
10148	#define   ERROR_ID              0x10    /* id not found */
10149	#define   ERROR_AC              0x04    /* aborted command */
10150	#define   ERROR_TK              0x02    /* track zero error */
10151	#define   ERROR_DM              0x01    /* no data address mark */
10152	
10153	/* Write only registers */
10154	#define REG_COMMAND         7   /* command */
10155	#define   CMD_IDLE              0x00    /* for w_command: drive idle */
10156	#define   CMD_RECALIBRATE       0x10    /* recalibrate drive */
10157	#define   CMD_READ              0x20    /* read data */
10158	#define   CMD_WRITE             0x30    /* write data */
10159	#define   CMD_READVERIFY        0x40    /* read verify */
10160	#define   CMD_FORMAT            0x50    /* format track */
10161	#define   CMD_SEEK              0x70    /* seek cylinder */
10162	#define   CMD_DIAG              0x90    /* execute device diagnostics */
10163	#define   CMD_SPECIFY           0x91    /* specify parameters */
10164	#define   ATA_IDENTIFY          0xEC    /* identify drive */
10165	#define REG_CTL         0x206   /* control register */
10166	#define   CTL_NORETRY           0x80    /* disable access retry */
10167	#define   CTL_NOECC             0x40    /* disable ecc retry */
10168	#define   CTL_EIGHTHEADS        0x08    /* more than eight heads */
10169	#define   CTL_RESET             0x04    /* reset controller */
10170	#define   CTL_INTDISABLE        0x02    /* disable interrupts */
10171	
10172	/* Interrupt request lines. */
10173	#define AT_IRQ0         14      /* interrupt number for controller 0 */
10174	#define AT_IRQ1         15      /* interrupt number for controller 1 */
10175	
10176	/* Common command block */
10177	struct command {
10178	  u8_t  precomp;        /* REG_PRECOMP, etc. */
10179	  u8_t  count;
10180	  u8_t  sector;
10181	  u8_t  cyl_lo;
10182	  u8_t  cyl_hi;
10183	  u8_t  ldh;
10184	  u8_t  command;
10185	};
10186	
10187	
10188	/* Error codes */
10189	#define ERR              (-1)   /* general error */
10190	#define ERR_BAD_SECTOR   (-2)   /* block marked bad detected */
10191	
10192	/* Some controllers don't interrupt, the clock will wake us up. */
10193	#define WAKEUP          (32*HZ) /* drive may be out for 31 seconds max */
10194	
10195	/* Miscellaneous. */
10196	#define MAX_DRIVES         4    /* this driver supports 4 drives (hd0 - hd19) */
10197	#if _WORD_SIZE > 2
10198	#define MAX_SECS         256    /* controller can transfer this many sectors */
10199	#else
10200	#define MAX_SECS         127    /* but not to a 16 bit process */
10201	#endif
10202	#define MAX_ERRORS         4    /* how often to try rd/wt before quitting */
10203	#define NR_DEVICES      (MAX_DRIVES * DEV_PER_DRIVE)
10204	#define SUB_PER_DRIVE   (NR_PARTITIONS * NR_PARTITIONS)
10205	#define NR_SUBDEVS      (MAX_DRIVES * SUB_PER_DRIVE)
10206	#define TIMEOUT        32000    /* controller timeout in ms */
10207	#define RECOVERYTIME     500    /* controller recovery time in ms */
10208	#define INITIALIZED     0x01    /* drive is initialized */
10209	#define DEAF            0x02    /* controller must be reset */
10210	#define SMART           0x04    /* drive supports ATA commands */
10211	
10212	
10213	/* Variables. */
10214	PRIVATE struct wini {           /* main drive struct, one entry per drive */
10215	  unsigned state;               /* drive state: deaf, initialized, dead */
10216	  unsigned base;                /* base register of the register file */
10217	  unsigned irq;                 /* interrupt request line */
10218	  unsigned lcylinders;          /* logical number of cylinders (BIOS) */
10219	  unsigned lheads;              /* logical number of heads */
10220	  unsigned lsectors;            /* logical number of sectors per track */
10221	  unsigned pcylinders;          /* physical number of cylinders (translated) */
10222	  unsigned pheads;              /* physical number of heads */
10223	  unsigned psectors;            /* physical number of sectors per track */
10224	  unsigned ldhpref;             /* top four bytes of the LDH (head) register */
10225	  unsigned precomp;             /* write precompensation cylinder / 4 */
10226	  unsigned max_count;           /* max request for this drive */
10227	  unsigned open_ct;             /* in-use count */
10228	  struct device part[DEV_PER_DRIVE];    /* primary partitions: hd[0-4] */
10229	  struct device subpart[SUB_PER_DRIVE]; /* subpartitions: hd[1-4][a-d] */
10230	} wini[MAX_DRIVES], *w_wn;
10231	
10232	PRIVATE struct trans {
10233	  struct iorequest_s *iop;      /* belongs to this I/O request */
10234	  unsigned long block;          /* first sector to transfer */
10235	  unsigned count;               /* byte count */
10236	  phys_bytes phys;              /* user physical address */
10237	} wtrans[NR_IOREQS];
10238	
10239	PRIVATE struct trans *w_tp;             /* to add transfer requests */
10240	PRIVATE unsigned w_count;               /* number of bytes to transfer */
10241	PRIVATE unsigned long w_nextblock;      /* next block on disk to transfer */
10242	PRIVATE int w_opcode;                   /* DEV_READ or DEV_WRITE */
10243	PRIVATE int w_command;                  /* current command in execution */
10244	PRIVATE int w_status;                   /* status after interrupt */
10245	PRIVATE int w_drive;                    /* selected drive */
10246	PRIVATE struct device *w_dv;            /* device's base and size */
10247	
10248	FORWARD _PROTOTYPE( void init_params, (void) );
10249	FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
10250	FORWARD _PROTOTYPE( struct device *w_prepare, (int device) );
10251	FORWARD _PROTOTYPE( int w_identify, (void) );
10252	FORWARD _PROTOTYPE( char *w_name, (void) );
10253	FORWARD _PROTOTYPE( int w_specify, (void) );
10254	FORWARD _PROTOTYPE( int w_schedule, (int proc_nr, struct iorequest_s *iop) );
10255	FORWARD _PROTOTYPE( int w_finish, (void) );
10256	FORWARD _PROTOTYPE( int com_out, (struct command *cmd) );
10257	FORWARD _PROTOTYPE( void w_need_reset, (void) );
10258	FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
10259	FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) );
10260	FORWARD _PROTOTYPE( void w_timeout, (void) );
10261	FORWARD _PROTOTYPE( int w_reset, (void) );
10262	FORWARD _PROTOTYPE( int w_intr_wait, (void) );
10263	FORWARD _PROTOTYPE( int w_waitfor, (int mask, int value) );
10264	FORWARD _PROTOTYPE( int w_handler, (int irq) );
10265	FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry) );
10266	
10267	/* w_waitfor loop unrolled once for speed. */
10268	#define waitfor(mask, value)    \
10269	        ((in_byte(w_wn->base + REG_STATUS) & mask) == value \
10270	                || w_waitfor(mask, value))
10271	
10272	
10273	/* Entry points to this driver. */
10274	PRIVATE struct driver w_dtab = {
10275	  w_name,               /* current device's name */
10276	  w_do_open,            /* open or mount request, initialize device */
10277	  w_do_close,           /* release device */
10278	  do_diocntl,           /* get or set a partition's geometry */
10279	  w_prepare,            /* prepare for I/O on a given minor device */
10280	  w_schedule,           /* precompute cylinder, head, sector, etc. */
10281	  w_finish,             /* do the I/O */
10282	  nop_cleanup,          /* nothing to clean up */
10283	  w_geometry,           /* tell the geometry of the disk */
10284	};
10285	
10286	#if ENABLE_ATAPI
10287	#include "atapi.c"      /* extra code for ATAPI CD-ROM */
10288	#endif
10289	
10290	
10291	/*===========================================================================*
10292	 *                              at_winchester_task                           *
10293	 *===========================================================================*/
10294	PUBLIC void at_winchester_task()
10295	{
10296	/* Set special disk parameters then call the generic main loop. */
10297	
10298	  init_params();
10299	
10300	  driver_task(&w_dtab);
10301	}
	
	
10304	/*============================================================================*
10305	 *                              init_params                                   *
10306	 *============================================================================*/
10307	PRIVATE void init_params()
10308	{
10309	/* This routine is called at startup to initialize the drive parameters. */
10310	
10311	  u16_t parv[2];
10312	  unsigned int vector;
10313	  int drive, nr_drives, i;
10314	  struct wini *wn;
10315	  u8_t params[16];
10316	  phys_bytes param_phys = vir2phys(params);
10317	
10318	  /* Get the number of drives from the BIOS data area */
10319	  phys_copy(0x475L, param_phys, 1L);
10320	  if ((nr_drives = params[0]) > 2) nr_drives = 2;
10321	
10322	  for (drive = 0, wn = wini; drive < MAX_DRIVES; drive++, wn++) {
10323	        if (drive < nr_drives) {
10324	                /* Copy the BIOS parameter vector */
10325	                vector = drive == 0 ? WINI_0_PARM_VEC : WINI_1_PARM_VEC;
10326	                phys_copy(vector * 4L, vir2phys(parv), 4L);
10327	
10328	                /* Calculate the address of the parameters and copy them */
10329	                phys_copy(hclick_to_physb(parv[1]) + parv[0], param_phys, 16L);
10330	
10331	                /* Copy the parameters to the structures of the drive */
10332	                wn->lcylinders = bp_cylinders(params);
10333	                wn->lheads = bp_heads(params);
10334	                wn->lsectors = bp_sectors(params);
10335	                wn->precomp = bp_precomp(params) >> 2;
10336	        }
10337	        wn->ldhpref = ldh_init(drive);
10338	        wn->max_count = MAX_SECS << SECTOR_SHIFT;
10339	        if (drive < 2) {
10340	                /* Controller 0. */
10341	                wn->base = REG_BASE0;
10342	                wn->irq = AT_IRQ0;
10343	        } else {
10344	                /* Controller 1. */
10345	                wn->base = REG_BASE1;
10346	                wn->irq = AT_IRQ1;
10347	        }
10348	  }
10349	}
	
	
10352	/*============================================================================*
10353	 *                              w_do_open                                     *
10354	 *============================================================================*/
10355	PRIVATE int w_do_open(dp, m_ptr)
10356	struct driver *dp;
10357	message *m_ptr;
10358	{
10359	/* Device open: Initialize the controller and read the partition table. */
10360	
10361	  int r;
10362	  struct wini *wn;
10363	  struct command cmd;
10364	
10365	  if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
10366	  wn = w_wn;
10367	
10368	  if (wn->state == 0) {
10369	        /* Try to identify the device. */
10370	        if (w_identify() != OK) {
10371	                printf("%s: probe failed\n", w_name());
10372	                if (wn->state & DEAF) w_reset();
10373	                wn->state = 0;
10374	                return(ENXIO);
10375	        }
10376	  }
10377	  if (wn->open_ct++ == 0) {
10378	        /* Partition the disk. */
10379	        partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY);
10380	  }
10381	  return(OK);
10382	}
	
	
10385	/*===========================================================================*
10386	 *                              w_prepare                                    *
10387	 *===========================================================================*/
10388	PRIVATE struct device *w_prepare(device)
10389	int device;
10390	{
10391	/* Prepare for I/O on a device. */
10392	
10393	  /* Nothing to transfer as yet. */
10394	  w_count = 0;
10395	
10396	  if (device < NR_DEVICES) {                    /* hd0, hd1, ... */

⌨️ 快捷键说明

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