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

📄 floppy.c

📁 minix3.1.1源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*===========================================================================* *				f_expire_tmrs				     * *===========================================================================*/PRIVATE void f_expire_tmrs(struct driver *dp, message *m_ptr){/* A synchronous alarm message was received. Check if there are any expired  * timers. Possibly reschedule the next alarm.   */  clock_t now;				/* current time */  timer_t *tp;  int s;  /* Get the current time to compare the timers against. */  if ((s=getuptime(&now)) != OK) 	panic("FLOPPY","Couldn't get uptime from clock.", s);  /* Scan the timers queue for expired timers. Dispatch the watchdog function   * for each expired timers. FLOPPY watchdog functions are f_tmr_timeout()    * and stop_motor(). Possibly a new alarm call must be scheduled.   */  tmrs_exptimers(&f_timers, now, NULL);  if (f_timers == NULL) {  	f_next_timeout = TMR_NEVER;  } else {  					  /* set new sync alarm */  	f_next_timeout = f_timers->tmr_exp_time;  	if ((s=sys_setalarm(f_next_timeout, 1)) != OK) 		panic("FLOPPY","Couldn't set synchronous alarm.", s);  }}/*===========================================================================* *				f_set_timer				     * *===========================================================================*/PRIVATE void f_set_timer(tp, delta, watchdog)timer_t *tp;				/* timer to be set */clock_t delta;				/* in how many ticks */tmr_func_t watchdog;			/* watchdog function to be called */{  clock_t now;				/* current time */  int s;  /* Get the current time. */  if ((s=getuptime(&now)) != OK) 	panic("FLOPPY","Couldn't get uptime from clock.", s);  /* Add the timer to the local timer queue. */  tmrs_settimer(&f_timers, tp, now + delta, watchdog, NULL);  /* Possibly reschedule an alarm call. This happens when the front of the    * timers queue was reinserted at another position, i.e., when a timer was    * reset, or when a new timer was added in front.    */  if (f_timers->tmr_exp_time != f_next_timeout) {  	f_next_timeout = f_timers->tmr_exp_time;   	if ((s=sys_setalarm(f_next_timeout, 1)) != OK) 		panic("FLOPPY","Couldn't set synchronous alarm.", s);  }}/*===========================================================================* *				f_prepare				     * *===========================================================================*/PRIVATE struct device *f_prepare(device)int device;{/* Prepare for I/O on a device. */  f_device = device;  f_drive = device & ~(DEV_TYPE_BITS | FORMAT_DEV_BIT);  if (f_drive < 0 || f_drive >= NR_DRIVES) return(NIL_DEV);  f_fp = &floppy[f_drive];  f_dv = &f_fp->fl_geom;  if (f_fp->fl_density < NT) {	f_dp = &fdensity[f_fp->fl_density];	f_sectors = f_dp->secpt;	f_fp->fl_geom.dv_size = mul64u((long) (NR_HEADS * f_sectors					* f_dp->cyls), SECTOR_SIZE);  }  /* A partition? */  if ((device &= DEV_TYPE_BITS) >= MINOR_fd0p0)	f_dv = &f_fp->fl_part[(device - MINOR_fd0p0) >> DEV_TYPE_SHIFT];  return f_dv;}/*===========================================================================* *				f_name					     * *===========================================================================*/PRIVATE char *f_name(){/* Return a name for the current device. */  static char name[] = "fd0";  name[2] = '0' + f_drive;  return name;}/*===========================================================================* *				f_cleanup				     * *===========================================================================*/PRIVATE void f_cleanup(){  /* Start a timer to turn the motor off in a few seconds. */  tmr_arg(&f_fp->fl_tmr_stop)->ta_int = f_drive;  f_set_timer(&f_fp->fl_tmr_stop, MOTOR_OFF, stop_motor);  /* Exiting the floppy driver, so forget where we are. */  f_fp->fl_sector = NO_SECTOR;}/*===========================================================================* *				f_transfer				     * *===========================================================================*/PRIVATE int f_transfer(proc_nr, opcode, position, iov, nr_req)int proc_nr;			/* process doing the request */int opcode;			/* DEV_GATHER or DEV_SCATTER */off_t position;			/* offset on device to read or write */iovec_t *iov;			/* pointer to read or write request vector */unsigned nr_req;		/* length of request vector */{  struct floppy *fp = f_fp;  iovec_t *iop, *iov_end = iov + nr_req;  int s, r, errors;  unsigned block;	/* Seen any 32M floppies lately? */  unsigned nbytes, count, chunk, sector;  unsigned long dv_size = cv64ul(f_dv->dv_size);  vir_bytes user_addr;  vir_bytes uaddrs[MAX_SECTORS], *up;  u8_t cmd[3];  /* Check disk address. */  if ((position & SECTOR_MASK) != 0) return(EINVAL);  errors = 0;  while (nr_req > 0) {	/* How many bytes to transfer? */	nbytes = 0;	for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size;	/* Which block on disk and how close to EOF? */	if (position >= dv_size) return(OK);		/* At EOF */	if (position + nbytes > dv_size) nbytes = dv_size - position;	block = div64u(add64ul(f_dv->dv_base, position), SECTOR_SIZE);	if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);	/* Using a formatting device? */	if (f_device & FORMAT_DEV_BIT) {		if (opcode != DEV_SCATTER) return(EIO);		if (iov->iov_size < SECTOR_SIZE + sizeof(fmt_param))			return(EINVAL);		if ((s=sys_datacopy(proc_nr, iov->iov_addr + SECTOR_SIZE,			SELF, (vir_bytes) &fmt_param, 			(phys_bytes) sizeof(fmt_param))) != OK)			panic("FLOPPY", "Sys_vircopy failed", s);		/* Check that the number of sectors in the data is reasonable,		 * to avoid division by 0.  Leave checking of other data to		 * the FDC.		 */		if (fmt_param.sectors_per_cylinder == 0) return(EIO);		/* Only the first sector of the parameters now needed. */		iov->iov_size = nbytes = SECTOR_SIZE;	}	/* Only try one sector if there were errors. */	if (errors > 0) nbytes = SECTOR_SIZE;	/* Compute cylinder and head of the track to access. */	fp->fl_cylinder = block / (NR_HEADS * f_sectors);	fp->fl_hardcyl = fp->fl_cylinder * f_dp->steps;	fp->fl_head = (block % (NR_HEADS * f_sectors)) / f_sectors;	/* For each sector on this track compute the user address it is to	 * go or to come from.	 */	for (up = uaddrs; up < uaddrs + MAX_SECTORS; up++) *up = 0;	count = 0;	iop = iov;	sector = block % f_sectors;	for (;;) {		user_addr = iop->iov_addr;		chunk = iop->iov_size;		if ((chunk & SECTOR_MASK) != 0) return(EINVAL);		while (chunk > 0) {			uaddrs[sector++] = user_addr;			chunk -= SECTOR_SIZE;			user_addr += SECTOR_SIZE;			count += SECTOR_SIZE;			if (sector == f_sectors || count == nbytes)				goto track_set_up;		}		iop++;	}  track_set_up:	/* First check to see if a reset is needed. */	if (need_reset) f_reset();	/* See if motor is running; if not, turn it on and wait. */	start_motor();	/* Set the stepping rate and data rate */	if (f_dp != prev_dp) {		cmd[0] = FDC_SPECIFY;		cmd[1] = f_dp->spec1;		cmd[2] = SPEC2;		(void) fdc_command(cmd, 3);		if ((s=sys_outb(FDC_RATE, f_dp->rate)) != OK)			panic("FLOPPY","Sys_outb failed", s);		prev_dp = f_dp;	}	/* If we are going to a new cylinder, perform a seek. */	r = seek();	/* Avoid read_id() if we don't plan to read much. */	if (fp->fl_sector == NO_SECTOR && count < (6 * SECTOR_SIZE))		fp->fl_sector = 0;	for (nbytes = 0; nbytes < count; nbytes += SECTOR_SIZE) {		if (fp->fl_sector == NO_SECTOR) {			/* Find out what the current sector is.  This often			 * fails right after a seek, so try it twice.			 */			if (r == OK && read_id() != OK) r = read_id();		}		/* Look for the next job in uaddrs[] */		if (r == OK) {			for (;;) {				if (fp->fl_sector >= f_sectors)					fp->fl_sector = 0;				up = &uaddrs[fp->fl_sector];				if (*up != 0) break;				fp->fl_sector++;			}		}		if (r == OK && opcode == DEV_SCATTER) {			/* Copy the user bytes to the DMA buffer. */			if ((s=sys_datacopy(proc_nr, *up,  SELF, 				(vir_bytes) tmp_buf,				(phys_bytes) SECTOR_SIZE)) != OK)			panic("FLOPPY", "Sys_vircopy failed", s);		}		/* Set up the DMA chip and perform the transfer. */		if (r == OK) {			if (dma_setup(opcode) != OK) {				/* This can only fail for addresses above 16MB				 * that cannot be handled by the controller,  				 * because it uses 24-bit addressing.				 */				return(EIO);			}			r = fdc_transfer(opcode);		}		if (r == OK && opcode == DEV_GATHER) {			/* Copy the DMA buffer to user space. */			if ((s=sys_datacopy(SELF, (vir_bytes) tmp_buf, 				proc_nr, *up, 				(phys_bytes) SECTOR_SIZE)) != OK)			panic("FLOPPY", "Sys_vircopy failed", s);		}		if (r != OK) {			/* Don't retry if write protected or too many errors. */			if (err_no_retry(r) || ++errors == MAX_ERRORS) {				return(EIO);			}			/* Recalibrate if halfway. */			if (errors == MAX_ERRORS / 2)				fp->fl_calibration = UNCALIBRATED;			nbytes = 0;			break;		/* retry */		}	}	/* Book the bytes successfully transferred. */	position += nbytes;	for (;;) {		if (nbytes < iov->iov_size) {			/* Not done with this one yet. */			iov->iov_addr += nbytes;			iov->iov_size -= nbytes;			break;		}		nbytes -= iov->iov_size;		iov->iov_addr += iov->iov_size;		iov->iov_size = 0;		if (nbytes == 0) {			/* The rest is optional, so we return to give FS a			 * chance to think it over.			 */			return(OK);		}		iov++;		nr_req--;	}  }  return(OK);}/*===========================================================================* *				dma_setup				     * *===========================================================================*/PRIVATE int dma_setup(opcode)int opcode;			/* DEV_GATHER or DEV_SCATTER */{/* The IBM PC can perform DMA operations by using the DMA chip.  To use it, * the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address * to be read from or written to, the byte count minus 1, and a read or write

⌨️ 快捷键说明

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