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

📄 at_wini.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 3 页
字号:
10397	        w_drive = device / DEV_PER_DRIVE;       /* save drive number */
10398	        w_wn = &wini[w_drive];
10399	        w_dv = &w_wn->part[device % DEV_PER_DRIVE];
10400	  } else
10401	  if ((unsigned) (device -= MINOR_hd1a) < NR_SUBDEVS) { /* hd1a, hd1b, ... */
10402	        w_drive = device / SUB_PER_DRIVE;
10403	        w_wn = &wini[w_drive];
10404	        w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
10405	  } else {
10406	        return(NIL_DEV);
10407	  }
10408	  return(w_dv);
10409	}
	
	
10412	/*===========================================================================*
10413	 *                              w_identify                                   *
10414	 *===========================================================================*/
10415	PRIVATE int w_identify()
10416	{
10417	/* Find out if a device exists, if it is an old AT disk, or a newer ATA
10418	 * drive, a removable media device, etc.
10419	 */
10420	
10421	  struct wini *wn = w_wn;
10422	  struct command cmd;
10423	  char id_string[40];
10424	  int i, r;
10425	  unsigned long size;
10426	#define id_byte(n)      (&tmp_buf[2 * (n)])
10427	#define id_word(n)      (((u16_t) id_byte(n)[0] <<  0) \
10428	                        |((u16_t) id_byte(n)[1] <<  8))
10429	#define id_longword(n)  (((u32_t) id_byte(n)[0] <<  0) \
10430	                        |((u32_t) id_byte(n)[1] <<  8) \
10431	                        |((u32_t) id_byte(n)[2] << 16) \
10432	                        |((u32_t) id_byte(n)[3] << 24))
10433	
10434	  /* Check if the one of the registers exists. */
10435	  r = in_byte(wn->base + REG_CYL_LO);
10436	  out_byte(wn->base + REG_CYL_LO, ~r);
10437	  if (in_byte(wn->base + REG_CYL_LO) == r) return(ERR);
10438	
10439	  /* Looks OK; register IRQ and try an ATA identify command. */
10440	  put_irq_handler(wn->irq, w_handler);
10441	  enable_irq(wn->irq);
10442	
10443	  cmd.ldh     = wn->ldhpref;
10444	  cmd.command = ATA_IDENTIFY;
10445	  if (com_simple(&cmd) == OK) {
10446	        /* This is an ATA device. */
10447	        wn->state |= SMART;
10448	
10449	        /* Device information. */
10450	        port_read(wn->base + REG_DATA, tmp_phys, SECTOR_SIZE);
10451	
10452	        /* Why are the strings byte swapped??? */
10453	        for (i = 0; i < 40; i++) id_string[i] = id_byte(27)[i^1];
10454	
10455	        /* Preferred CHS translation mode. */
10456	        wn->pcylinders = id_word(1);
10457	        wn->pheads = id_word(3);
10458	        wn->psectors = id_word(6);
10459	        size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;
10460	
10461	        if ((id_byte(49)[1] & 0x02) && size > 512L*1024*2) {
10462	                /* Drive is LBA capable and is big enough to trust it to
10463	                 * not make a mess of it.
10464	                 */
10465	                wn->ldhpref |= LDH_LBA;
10466	                size = id_longword(60);
10467	        }
10468	
10469	        if (wn->lcylinders == 0) {
10470	                /* No BIOS parameters?  Then make some up. */
10471	                wn->lcylinders = wn->pcylinders;
10472	                wn->lheads = wn->pheads;
10473	                wn->lsectors = wn->psectors;
10474	                while (wn->lcylinders > 1024) {
10475	                        wn->lheads *= 2;
10476	                        wn->lcylinders /= 2;
10477	                }
10478	        }
10479	  } else {
10480	        /* Not an ATA device; no translations, no special features.  Don't
10481	         * touch it unless the BIOS knows about it.
10482	         */
10483	        if (wn->lcylinders == 0) return(ERR);   /* no BIOS parameters */
10484	        wn->pcylinders = wn->lcylinders;
10485	        wn->pheads = wn->lheads;
10486	        wn->psectors = wn->lsectors;
10487	        size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;
10488	  }
10489	  /* The fun ends at 4 GB. */
10490	  if (size > ((u32_t) -1) / SECTOR_SIZE) size = ((u32_t) -1) / SECTOR_SIZE;
10491	
10492	  /* Base and size of the whole drive */
10493	  wn->part[0].dv_base = 0;
10494	  wn->part[0].dv_size = size << SECTOR_SHIFT;
10495	
10496	  if (w_specify() != OK && w_specify() != OK) return(ERR);
10497	
10498	  printf("%s: ", w_name());
10499	  if (wn->state & SMART) {
10500	        printf("%.40s\n", id_string);
10501	  } else {
10502	        printf("%ux%ux%u\n", wn->pcylinders, wn->pheads, wn->psectors);
10503	  }
10504	  return(OK);
10505	}
	
	
10508	/*===========================================================================*
10509	 *                              w_name                                       *
10510	 *===========================================================================*/
10511	PRIVATE char *w_name()
10512	{
10513	/* Return a name for the current device. */
10514	  static char name[] = "at-hd15";
10515	  unsigned device = w_drive * DEV_PER_DRIVE;
10516	
10517	  if (device < 10) {
10518	        name[5] = '0' + device;
10519	        name[6] = 0;
10520	  } else {
10521	        name[5] = '0' + device / 10;
10522	        name[6] = '0' + device % 10;
10523	  }
10524	  return name;
10525	}
	
	
10528	/*===========================================================================*
10529	 *                              w_specify                                    *
10530	 *===========================================================================*/
10531	PRIVATE int w_specify()
10532	{
10533	/* Routine to initialize the drive after boot or when a reset is needed. */
10534	
10535	  struct wini *wn = w_wn;
10536	  struct command cmd;
10537	
10538	  if ((wn->state & DEAF) && w_reset() != OK) return(ERR);
10539	
10540	  /* Specify parameters: precompensation, number of heads and sectors. */
10541	  cmd.precomp = wn->precomp;
10542	  cmd.count   = wn->psectors;
10543	  cmd.ldh     = w_wn->ldhpref | (wn->pheads - 1);
10544	  cmd.command = CMD_SPECIFY;            /* Specify some parameters */
10545	
10546	  if (com_simple(&cmd) != OK) return(ERR);
10547	
10548	  if (!(wn->state & SMART)) {
10549	        /* Calibrate an old disk. */
10550	        cmd.sector  = 0;
10551	        cmd.cyl_lo  = 0;
10552	        cmd.cyl_hi  = 0;
10553	        cmd.ldh     = w_wn->ldhpref;
10554	        cmd.command = CMD_RECALIBRATE;
10555	
10556	        if (com_simple(&cmd) != OK) return(ERR);
10557	  }
10558	
10559	  wn->state |= INITIALIZED;
10560	  return(OK);
10561	}
	
	
10564	/*===========================================================================*
10565	 *                              w_schedule                                   *
10566	 *===========================================================================*/
10567	PRIVATE int w_schedule(proc_nr, iop)
10568	int proc_nr;                    /* process doing the request */
10569	struct iorequest_s *iop;        /* pointer to read or write request */
10570	{
10571	/* Gather I/O requests on consecutive blocks so they may be read/written
10572	 * in one controller command.  (There is enough time to compute the next
10573	 * consecutive request while an unwanted block passes by.)
10574	 */
10575	  struct wini *wn = w_wn;
10576	  int r, opcode;
10577	  unsigned long pos;
10578	  unsigned nbytes, count;
10579	  unsigned long block;
10580	  phys_bytes user_phys;
10581	
10582	  /* This many bytes to read/write */
10583	  nbytes = iop->io_nbytes;
10584	  if ((nbytes & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
10585	
10586	  /* From/to this position on the device */
10587	  pos = iop->io_position;
10588	  if ((pos & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
10589	
10590	  /* To/from this user address */
10591	  user_phys = numap(proc_nr, (vir_bytes) iop->io_buf, nbytes);
10592	  if (user_phys == 0) return(iop->io_nbytes = EINVAL);
10593	
10594	  /* Read or write? */
10595	  opcode = iop->io_request & ~OPTIONAL_IO;
10596	
10597	  /* Which block on disk and how close to EOF? */
10598	  if (pos >= w_dv->dv_size) return(OK);         /* At EOF */
10599	  if (pos + nbytes > w_dv->dv_size) nbytes = w_dv->dv_size - pos;
10600	  block = (w_dv->dv_base + pos) >> SECTOR_SHIFT;
10601	
10602	  if (w_count > 0 && block != w_nextblock) {
10603	        /* This new request can't be chained to the job being built */
10604	        if ((r = w_finish()) != OK) return(r);
10605	  }
10606	
10607	  /* The next consecutive block */
10608	  w_nextblock = block + (nbytes >> SECTOR_SHIFT);
10609	
10610	  /* While there are "unscheduled" bytes in the request: */
10611	  do {
10612	        count = nbytes;
10613	
10614	        if (w_count == wn->max_count) {
10615	                /* The drive can't do more then max_count at once */
10616	                if ((r = w_finish()) != OK) return(r);
10617	        }
10618	
10619	        if (w_count + count > wn->max_count)
10620	                count = wn->max_count - w_count;
10621	
10622	        if (w_count == 0) {
10623	                /* The first request in a row, initialize. */
10624	                w_opcode = opcode;
10625	                w_tp = wtrans;
10626	        }
10627	
10628	        /* Store I/O parameters */
10629	        w_tp->iop = iop;
10630	        w_tp->block = block;
10631	        w_tp->count = count;
10632	        w_tp->phys = user_phys;
10633	
10634	        /* Update counters */
10635	        w_tp++;
10636	        w_count += count;
10637	        block += count >> SECTOR_SHIFT;
10638	        user_phys += count;
10639	        nbytes -= count;
10640	  } while (nbytes > 0);
10641	
10642	  return(OK);
10643	}
	
	
10646	/*===========================================================================*
10647	 *                              w_finish                                     *
10648	 *===========================================================================*/
10649	PRIVATE int w_finish()
10650	{
10651	/* Carry out the I/O requests gathered in wtrans[]. */
10652	
10653	  struct trans *tp = wtrans;
10654	  struct wini *wn = w_wn;
10655	  int r, errors;
10656	  struct command cmd;
10657	  unsigned cylinder, head, sector, secspcyl;
10658	
10659	  if (w_count == 0) return(OK); /* Spurious finish. */
10660	
10661	  r = ERR;      /* Trigger the first com_out */
10662	  errors = 0;
10663	
10664	  do {
10665	        if (r != OK) {
10666	                /* The controller must be (re)programmed. */
10667	
10668	                /* First check to see if a reinitialization is needed. */
10669	                if (!(wn->state & INITIALIZED) && w_specify() != OK)
10670	                        return(tp->iop->io_nbytes = EIO);
10671	
10672	                /* Tell the controller to transfer w_count bytes */
10673	                cmd.precomp = wn->precomp;
10674	                cmd.count   = (w_count >> SECTOR_SHIFT) & BYTE;
10675	                if (wn->ldhpref & LDH_LBA) {
10676	                        cmd.sector  = (tp->block >>  0) & 0xFF;
10677	                        cmd.cyl_lo  = (tp->block >>  8) & 0xFF;
10678	                        cmd.cyl_hi  = (tp->block >> 16) & 0xFF;
10679	                        cmd.ldh     = wn->ldhpref | ((tp->block >> 24) & 0xF);
10680	                } else {
10681	                        secspcyl = wn->pheads * wn->psectors;
10682	                        cylinder = tp->block / secspcyl;
10683	                        head = (tp->block % secspcyl) / wn->psectors;
10684	                        sector = tp->block % wn->psectors;
10685	                        cmd.sector  = sector + 1;
10686	                        cmd.cyl_lo  = cylinder & BYTE;
10687	                        cmd.cyl_hi  = (cylinder >> 8) & BYTE;
10688	                        cmd.ldh     = wn->ldhpref | head;
10689	                }
10690	                cmd.command = w_opcode == DEV_WRITE ? CMD_WRITE : CMD_READ;
10691	
10692	                if ((r = com_out(&cmd)) != OK) {
10693	                        if (++errors == MAX_ERRORS) {
10694	                                w_command = CMD_IDLE;
10695	                                return(tp->iop->io_nbytes = EIO);
10696	                        }
10697	                        continue;       /* Retry */

⌨️ 快捷键说明

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