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

📄 at_wini.c

📁 minix3的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
  		int s;  		irq_hook = irq;  		if (skip > 0) {  			if (w_pci_debug) printf("atapci skipping controller (remain %d)\n", skip);  			skip--;  			continue;  		}  		if ((s=sys_irqsetpolicy(irq, 0, &irq_hook)) != OK) {		  	printf("atapci: couldn't set IRQ policy %d\n", irq);		  	continue;		}		if ((s=sys_irqenable(&irq_hook)) != OK) {			printf("atapci: couldn't enable IRQ line %d\n", irq);		  	continue;		}  	} else {  		/* If not.. this is not the ata-pci controller we're  		 * looking for.  		 */  		if (w_pci_debug) printf("atapci skipping compatability controller\n");  		continue;  	}  	/* Primary channel not in compatability mode? */  	if (interface & ATA_IF_NOTCOMPAT1) {  		u32_t base_cmd, base_ctl;  		base_cmd = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;  		base_ctl = pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0;  		if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) {	  		init_drive(&wini[w_next_drive],	  			base_cmd, base_ctl, irq, 1, irq_hook, 0);  			init_drive(&wini[w_next_drive+1],  				base_cmd, base_ctl, irq, 1, irq_hook, 1);	  		if (w_pci_debug)		  		printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq);  		} else printf("atapci: ignored drives on primary channel, base %x\n", base_cmd);  	}  	/* Secondary channel not in compatability mode? */  	if (interface & ATA_IF_NOTCOMPAT2) {  		u32_t base_cmd, base_ctl;  		base_cmd = pci_attr_r32(devind, PCI_BAR_3) & 0xffffffe0;  		base_ctl = pci_attr_r32(devind, PCI_BAR_4) & 0xffffffe0;  		if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) {  			init_drive(&wini[w_next_drive+2],  				base_cmd, base_ctl, irq, 1, irq_hook, 2);	  		init_drive(&wini[w_next_drive+3],	  			base_cmd, base_ctl, irq, 1, irq_hook, 3);	  		if (w_pci_debug)  				printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq);  		} else printf("atapci: ignored drives on secondary channel, base %x\n", base_cmd);  	}  	w_next_drive += 4;  }}/*===========================================================================* *				w_do_open				     * *===========================================================================*/PRIVATE int w_do_open(dp, m_ptr)struct driver *dp;message *m_ptr;{/* Device open: Initialize the controller and read the partition table. */  struct wini *wn;  if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);  wn = w_wn;  /* If we've probed it before and it failed, don't probe it again. */  if (wn->state & IGNORING) return ENXIO;  /* If we haven't identified it yet, or it's gone deaf,    * (re-)identify it.   */  if (!(wn->state & IDENTIFIED) || (wn->state & DEAF)) {	/* Try to identify the device. */	if (w_identify() != OK) {#if VERBOSE  		printf("%s: probe failed\n", w_name());#endif		if (wn->state & DEAF) w_reset();		wn->state = IGNORING;		return(ENXIO);	}	  /* Do a test transaction unless it's a CD drive (then	   * we can believe the controller, and a test may fail	   * due to no CD being in the drive). If it fails, ignore	   * the device forever.	   */	  if (!(wn->state & ATAPI) && w_io_test() != OK) {  		wn->state |= IGNORING;	  	return(ENXIO);	  }#if VERBOSE	  printf("%s: AT driver detected ", w_name());	  if (wn->state & (SMART|ATAPI)) {		printf("%.40s\n", w_id_string);	  } else {		printf("%ux%ux%u\n", wn->pcylinders, wn->pheads, wn->psectors);	  }#endif  }#if ENABLE_ATAPI   if ((wn->state & ATAPI) && (m_ptr->COUNT & W_BIT))	return(EACCES);#endif   /* If it's not an ATAPI device, then don't open with RO_BIT. */   if (!(wn->state & ATAPI) && (m_ptr->COUNT & RO_BIT)) return EACCES;  /* Partition the drive if it's being opened for the first time,   * or being opened after being closed.   */  if (wn->open_ct == 0) {#if ENABLE_ATAPI	if (wn->state & ATAPI) {		int r;		if ((r = atapi_open()) != OK) return(r);	}#endif	/* Partition the disk. */	partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY, wn->state & ATAPI);  }  wn->open_ct++;  return(OK);}/*===========================================================================* *				w_prepare				     * *===========================================================================*/PRIVATE struct device *w_prepare(int device){/* Prepare for I/O on a device. */struct wini *prev_wn;prev_wn = w_wn;  w_device = device;  if (device < NR_MINORS) {			/* d0, d0p[0-3], d1, ... */	w_drive = device / DEV_PER_DRIVE;	/* save drive number */	w_wn = &wini[w_drive];	w_dv = &w_wn->part[device % DEV_PER_DRIVE];  } else  if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/	w_drive = device / SUB_PER_DRIVE;	w_wn = &wini[w_drive];	w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];  } else {  	w_device = -1;	return(NIL_DEV);  }  return(w_dv);}/*===========================================================================* *				w_identify				     * *===========================================================================*/PRIVATE int w_identify(){/* Find out if a device exists, if it is an old AT disk, or a newer ATA * drive, a removable media device, etc. */  struct wini *wn = w_wn;  struct command cmd;  int i, s;  unsigned long size;#define id_byte(n)	(&tmp_buf[2 * (n)])#define id_word(n)	(((u16_t) id_byte(n)[0] <<  0) \			|((u16_t) id_byte(n)[1] <<  8))#define id_longword(n)	(((u32_t) id_byte(n)[0] <<  0) \			|((u32_t) id_byte(n)[1] <<  8) \			|((u32_t) id_byte(n)[2] << 16) \			|((u32_t) id_byte(n)[3] << 24))  /* Try to identify the device. */  cmd.ldh     = wn->ldhpref;  cmd.command = ATA_IDENTIFY;  if (com_simple(&cmd) == OK) {	/* This is an ATA device. */	wn->state |= SMART;	/* Device information. */	if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, SECTOR_SIZE)) != OK)		panic(w_name(),"Call to sys_insw() failed", s);	/* Why are the strings byte swapped??? */	for (i = 0; i < 40; i++) w_id_string[i] = id_byte(27)[i^1];	/* Preferred CHS translation mode. */	wn->pcylinders = id_word(1);	wn->pheads = id_word(3);	wn->psectors = id_word(6);	size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;	if ((id_byte(49)[1] & 0x02) && size > 512L*1024*2) {		/* Drive is LBA capable and is big enough to trust it to		 * not make a mess of it.		 */		wn->ldhpref |= LDH_LBA;		size = id_longword(60);		if (w_lba48 && ((id_word(83)) & (1L << 10))) {			/* Drive is LBA48 capable (and LBA48 is turned on). */			if (id_word(102) || id_word(103)) {				/* If no. of sectors doesn't fit in 32 bits,				 * trunacte to this. So it's LBA32 for now.				 * This can still address devices up to 2TB				 * though.				 */				size = ULONG_MAX;			} else {				/* Actual number of sectors fits in 32 bits. */				size = id_longword(100);			}			wn->lba48 = 1;		}	}	if (wn->lcylinders == 0) {		/* No BIOS parameters?  Then make some up. */		wn->lcylinders = wn->pcylinders;		wn->lheads = wn->pheads;		wn->lsectors = wn->psectors;		while (wn->lcylinders > 1024) {			wn->lheads *= 2;			wn->lcylinders /= 2;		}	}#if ENABLE_ATAPI  } else  if (cmd.command = ATAPI_IDENTIFY, com_simple(&cmd) == OK) {	/* An ATAPI device. */	wn->state |= ATAPI;	/* Device information. */	if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, 512)) != OK)		panic(w_name(),"Call to sys_insw() failed", s);	/* Why are the strings byte swapped??? */	for (i = 0; i < 40; i++) w_id_string[i] = id_byte(27)[i^1];	size = 0;	/* Size set later. */#endif  } else {	/* Not an ATA device; no translations, no special features.  Don't	 * touch it unless the BIOS knows about it.	 */	if (wn->lcylinders == 0) { return(ERR); }	/* no BIOS parameters */	wn->pcylinders = wn->lcylinders;	wn->pheads = wn->lheads;	wn->psectors = wn->lsectors;	size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;  }  /* Size of the whole drive */  wn->part[0].dv_size = mul64u(size, SECTOR_SIZE);  /* Reset/calibrate (where necessary) */  if (w_specify() != OK && w_specify() != OK) {  	return(ERR);  }  if (wn->irq == NO_IRQ) {	  /* Everything looks OK; register IRQ so we can stop polling. */	  wn->irq = w_drive < 2 ? AT_WINI_0_IRQ : AT_WINI_1_IRQ;	  wn->irq_hook_id = wn->irq;	/* id to be returned if interrupt occurs */	  if ((s=sys_irqsetpolicy(wn->irq, IRQ_REENABLE, &wn->irq_hook_id)) != OK) 	  	panic(w_name(), "couldn't set IRQ policy", s);	  if ((s=sys_irqenable(&wn->irq_hook_id)) != OK)	  	panic(w_name(), "couldn't enable IRQ line", s);  }  wn->state |= IDENTIFIED;  return(OK);}/*===========================================================================* *				w_name					     * *===========================================================================*/PRIVATE char *w_name(){/* Return a name for the current device. */  static char name[] = "AT-D0";  name[4] = '0' + w_drive;  return name;}/*===========================================================================* *				w_io_test				     * *===========================================================================*/PRIVATE int w_io_test(void){	int r, save_dev;	int save_timeout, save_errors, save_wakeup;	iovec_t iov;#ifdef CD_SECTOR_SIZE	static char buf[CD_SECTOR_SIZE];#else	static char buf[SECTOR_SIZE];#endif	iov.iov_addr = (vir_bytes) buf;	iov.iov_size = sizeof(buf);	save_dev = w_device;	/* Reduce timeout values for this test transaction. */	save_timeout = timeout_ticks;	save_errors = max_errors;	save_wakeup = wakeup_ticks;	if (!w_standard_timeouts) {		timeout_ticks = HZ * 4;		wakeup_ticks = HZ * 6;		max_errors = 3;	}	w_testing = 1;	/* Try I/O on the actual drive (not any (sub)partition). */ 	if (w_prepare(w_drive * DEV_PER_DRIVE) == NIL_DEV) 		panic(w_name(), "Couldn't switch devices", NO_NUM);	r = w_transfer(SELF, DEV_GATHER, 0, &iov, 1);	/* Switch back. */ 	if (w_prepare(save_dev) == NIL_DEV) 		panic(w_name(), "Couldn't switch back devices", NO_NUM); 	/* Restore parameters. */	timeout_ticks = save_timeout;	max_errors = save_errors;	wakeup_ticks = save_wakeup;	w_testing = 0; 	/* Test if everything worked. */	if (r != OK || iov.iov_size != 0) {		return ERR;	}	/* Everything worked. */	return OK;}/*===========================================================================* *				w_specify				     * *===========================================================================*/PRIVATE int w_specify(){/* Routine to initialize the drive after boot or when a reset is needed. */  struct wini *wn = w_wn;  struct command cmd;  if ((wn->state & DEAF) && w_reset() != OK) {  	return(ERR);  }  if (!(wn->state & ATAPI)) {	/* Specify parameters: precompensation, number of heads and sectors. */	cmd.precomp = wn->precomp;	cmd.count   = wn->psectors;	cmd.ldh     = w_wn->ldhpref | (wn->pheads - 1);	cmd.command = CMD_SPECIFY;		/* Specify some parameters */	/* Output command block and see if controller accepts the parameters. */	if (com_simple(&cmd) != OK) return(ERR);	if (!(wn->state & SMART)) {		/* Calibrate an old disk. */		cmd.sector  = 0;		cmd.cyl_lo  = 0;		cmd.cyl_hi  = 0;		cmd.ldh     = w_wn->ldhpref;		cmd.command = CMD_RECALIBRATE;		if (com_simple(&cmd) != OK) return(ERR);	}  }  wn->state |= INITIALIZED;  return(OK);}/*===========================================================================* *				do_transfer				     * *===========================================================================*/PRIVATE int do_transfer(struct wini *wn, unsigned int precomp, unsigned int count,	unsigned int sector, unsigned int opcode){  	struct command cmd;	unsigned secspcyl = wn->pheads * wn->psectors;	cmd.precomp = precomp;	cmd.count   = count;	cmd.command = opcode == DEV_SCATTER ? CMD_WRITE : CMD_READ;	/* 	if (w_lba48 && wn->lba48) {	} else  */	if (wn->ldhpref & LDH_LBA) {		cmd.sector  = (sector >>  0) & 0xFF;		cmd.cyl_lo  = (sector >>  8) & 0xFF;		cmd.cyl_hi  = (sector >> 16) & 0xFF;		cmd.ldh     = wn->ldhpref | ((sector >> 24) & 0xF);	} else {  		int cylinder, head, sec;		cylinder = sector / secspcyl;		head = (sector % secspcyl) / wn->psectors;		sec = sector % wn->psectors;		cmd.sector  = sec + 1;		cmd.cyl_lo  = cylinder & BYTE;		cmd.cyl_hi  = (cylinder >> 8) & BYTE;		cmd.ldh     = wn->ldhpref | head;	}	return com_out(&cmd);}/*===========================================================================* *				w_transfer				     *

⌨️ 快捷键说明

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