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

📄 floppy.c

📁 minix3.1.1源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* This file contains the device dependent part of the driver for the Floppy * Disk Controller (FDC) using the NEC PD765 chip. * * The file contains two entry points: * *   floppy_task:   main entry when system is brought up * * Changes: *   Sep 11, 2005   code cleanup (Andy Tanenbaum) *   Dec 01, 2004   floppy driver moved to user-space (Jorrit N. Herder) *   Sep 15, 2004   sync alarms/ local timer management  (Jorrit N. Herder) *   Aug 12, 2003   null seek no interrupt fix  (Mike Haertel) *   May 14, 2000   d-d/i rewrite  (Kees J. Bot) *   Apr 04, 1992   device dependent/independent split  (Kees J. Bot) *   Mar 27, 1992   last details on density checking  (Kees J. Bot) *   Feb 14, 1992   check drive density on opens only  (Andy Tanenbaum) *	     1991   len[] / motors / reset / step rate / ...  (Bruce Evans) *   May 13, 1991   renovated the errors loop  (Don Chapman) *           1989   I/O vector to keep up with 1-1 interleave  (Bruce Evans) *   Jan 06, 1988   allow 1.44 MB diskettes  (Al Crew) *   Nov 28, 1986   better resetting for 386  (Peter Kay) *   Oct 27, 1986   fdc_results fixed for 8 MHz  (Jakob Schripsema) */#include "floppy.h"#include <timers.h>#include <ibm/diskparm.h>#include <minix/sysutil.h>#include <minix/syslib.h>/* I/O Ports used by floppy disk task. */#define DOR            0x3F2	/* motor drive control bits */#define FDC_STATUS     0x3F4	/* floppy disk controller status register */#define FDC_DATA       0x3F5	/* floppy disk controller data register */#define FDC_RATE       0x3F7	/* transfer rate register */#define DMA_ADDR       0x004	/* port for low 16 bits of DMA address */#define DMA_TOP        0x081	/* port for top 8 bits of 24-bit DMA addr */#define DMA_COUNT      0x005	/* port for DMA count (count =  bytes - 1) */#define DMA_FLIPFLOP   0x00C	/* DMA byte pointer flip-flop */#define DMA_MODE       0x00B	/* DMA mode port */#define DMA_INIT       0x00A	/* DMA init port */#define DMA_RESET_VAL  0x006#define DMA_ADDR_MASK  0xFFFFFF	/* mask to verify DMA address is 24-bit *//* Status registers returned as result of operation. */#define ST0             0x00	/* status register 0 */#define ST1             0x01	/* status register 1 */#define ST2             0x02	/* status register 2 */#define ST3             0x00	/* status register 3 (return by DRIVE_SENSE) */#define ST_CYL          0x03	/* slot where controller reports cylinder */#define ST_HEAD         0x04	/* slot where controller reports head */#define ST_SEC          0x05	/* slot where controller reports sector */#define ST_PCN          0x01	/* slot where controller reports present cyl *//* Fields within the I/O ports. *//* Main status register. */#define CTL_BUSY        0x10	/* bit is set when read or write in progress */#define DIRECTION       0x40	/* bit is set when reading data reg is valid */#define MASTER          0x80	/* bit is set when data reg can be accessed *//* Digital output port (DOR). */#define MOTOR_SHIFT        4	/* high 4 bits control the motors in DOR */#define ENABLE_INT      0x0C	/* used for setting DOR port *//* ST0. */#define ST0_BITS_TRANS  0xD8	/* check 4 bits of status */#define TRANS_ST0       0x00	/* 4 bits of ST0 for READ/WRITE */#define ST0_BITS_SEEK   0xF8	/* check top 5 bits of seek status */#define SEEK_ST0        0x20	/* top 5 bits of ST0 for SEEK *//* ST1. */#define BAD_SECTOR      0x05	/* if these bits are set in ST1, recalibrate */#define WRITE_PROTECT   0x02	/* bit is set if diskette is write protected *//* ST2. */#define BAD_CYL         0x1F	/* if any of these bits are set, recalibrate *//* ST3 (not used). */#define ST3_FAULT       0x80	/* if this bit is set, drive is sick */#define ST3_WR_PROTECT  0x40	/* set when diskette is write protected */#define ST3_READY       0x20	/* set when drive is ready *//* Floppy disk controller command bytes. */#define FDC_SEEK        0x0F	/* command the drive to seek */#define FDC_READ        0xE6	/* command the drive to read */#define FDC_WRITE       0xC5	/* command the drive to write */#define FDC_SENSE       0x08	/* command the controller to tell its status */#define FDC_RECALIBRATE 0x07	/* command the drive to go to cyl 0 */#define FDC_SPECIFY     0x03	/* command the drive to accept params */#define FDC_READ_ID     0x4A	/* command the drive to read sector identity */#define FDC_FORMAT      0x4D	/* command the drive to format a track *//* DMA channel commands. */#define DMA_READ        0x46	/* DMA read opcode */#define DMA_WRITE       0x4A	/* DMA write opcode *//* Parameters for the disk drive. */#define HC_SIZE         2880	/* # sectors on largest legal disk (1.44MB) */#define NR_HEADS        0x02	/* two heads (i.e., two tracks/cylinder) */#define MAX_SECTORS	  18	/* largest # sectors per track */#define DTL             0xFF	/* determines data length (sector size) */#define SPEC2           0x02	/* second parameter to SPECIFY */#define MOTOR_OFF      (3*HZ)	/* how long to wait before stopping motor */#define WAKEUP	       (2*HZ)	/* timeout on I/O, FDC won't quit. *//* Error codes */#define ERR_SEEK         (-1)	/* bad seek */#define ERR_TRANSFER     (-2)	/* bad transfer */#define ERR_STATUS       (-3)	/* something wrong when getting status */#define ERR_READ_ID      (-4)	/* bad read id */#define ERR_RECALIBRATE  (-5)	/* recalibrate didn't work properly */#define ERR_DRIVE        (-6)	/* something wrong with a drive */#define ERR_WR_PROTECT   (-7)	/* diskette is write protected */#define ERR_TIMEOUT      (-8)	/* interrupt timeout *//* No retries on some errors. */#define err_no_retry(err)	((err) <= ERR_WR_PROTECT)/* Encoding of drive type in minor device number. */#define DEV_TYPE_BITS   0x7C	/* drive type + 1, if nonzero */#define DEV_TYPE_SHIFT     2	/* right shift to normalize type bits */#define FORMAT_DEV_BIT  0x80	/* bit in minor to turn write into format *//* Miscellaneous. */#define MAX_ERRORS         6	/* how often to try rd/wt before quitting */#define MAX_RESULTS        7	/* max number of bytes controller returns */#define NR_DRIVES          2	/* maximum number of drives */#define DIVISOR          128	/* used for sector size encoding */#define SECTOR_SIZE_CODE   2	/* code to say "512" to the controller */#define TIMEOUT_MICROS   500000L	/* microseconds waiting for FDC */#define TIMEOUT_TICKS     30	/* ticks waiting for FDC */#define NT                 7	/* number of diskette/drive combinations */#define UNCALIBRATED       0	/* drive needs to be calibrated at next use */#define CALIBRATED         1	/* no calibration needed */#define BASE_SECTOR        1	/* sectors are numbered starting at 1 */#define NO_SECTOR        (-1)	/* current sector unknown */#define NO_CYL		 (-1)	/* current cylinder unknown, must seek */#define NO_DENS		 100	/* current media unknown */#define BSY_IDLE	   0	/* busy doing nothing */#define BSY_IO		   1	/* busy doing I/O */#define BSY_WAKEN	   2	/* got a wakeup call *//* Seven combinations of diskette/drive are supported. * * # Diskette Drive  Sectors  Tracks   Rotation Data-rate  Comment * 0   360K    360K     9       40     300 RPM  250 kbps   Standard PC DSDD * 1   1.2M    1.2M    15       80     360 RPM  500 kbps   AT disk in AT drive * 2   360K    720K     9       40     300 RPM  250 kbps   Quad density PC * 3   720K    720K     9       80     300 RPM  250 kbps   Toshiba, et al. * 4   360K    1.2M     9       40     360 RPM  300 kbps   PC disk in AT drive * 5   720K    1.2M     9       80     360 RPM  300 kbps   Toshiba in AT drive * 6   1.44M   1.44M   18	80     300 RPM  500 kbps   PS/2, et al. * * In addition, 720K diskettes can be read in 1.44MB drives, but that does * not need a different set of parameters.  This combination uses * * 3   720K    1.44M    9       80     300 RPM  250 kbps   PS/2, et al. */PRIVATE struct density {	u8_t	secpt;		/* sectors per track */	u8_t	cyls;		/* tracks per side */	u8_t	steps;		/* steps per cylinder (2 = double step) */	u8_t	test;		/* sector to try for density test */	u8_t	rate;		/* data rate (2=250, 1=300, 0=500 kbps) */	u8_t	start;		/* motor start (clock ticks) */	u8_t	gap;		/* gap size */	u8_t	spec1;		/* first specify byte (SRT/HUT) */} fdensity[NT] = {	{  9, 40, 1, 4*9, 2, 4*HZ/8, 0x2A, 0xDF },	/*  360K / 360K  */	{ 15, 80, 1,  14, 0, 4*HZ/8, 0x1B, 0xDF },	/*  1.2M / 1.2M  */	{  9, 40, 2, 2*9, 2, 4*HZ/8, 0x2A, 0xDF },	/*  360K / 720K  */	{  9, 80, 1, 4*9, 2, 6*HZ/8, 0x2A, 0xDF },	/*  720K / 720K  */	{  9, 40, 2, 2*9, 1, 4*HZ/8, 0x23, 0xDF },	/*  360K / 1.2M  */	{  9, 80, 1, 4*9, 1, 4*HZ/8, 0x23, 0xDF },	/*  720K / 1.2M  */	{ 18, 80, 1,  17, 0, 6*HZ/8, 0x1B, 0xCF },	/* 1.44M / 1.44M */};/* The following table is used with the test_sector array to recognize a * drive/floppy combination.  The sector to test has been determined by * looking at the differences in gap size, sectors/track, and double stepping. * This means that types 0 and 3 can't be told apart, only the motor start * time differs.  If a read test succeeds then the drive is limited to the * set of densities it can support to avoid unnecessary tests in the future. */#define b(d)	(1 << (d))	/* bit for density d. */PRIVATE struct test_order {	u8_t	t_density;	/* floppy/drive type */	u8_t	t_class;	/* limit drive to this class of densities */} test_order[NT-1] = {	{ 6,  b(3) | b(6) },		/* 1.44M  {720K, 1.44M} */	{ 1,  b(1) | b(4) | b(5) },	/* 1.2M   {1.2M, 360K, 720K} */	{ 3,  b(2) | b(3) | b(6) },	/* 720K   {360K, 720K, 1.44M} */	{ 4,  b(1) | b(4) | b(5) },	/* 360K   {1.2M, 360K, 720K} */	{ 5,  b(1) | b(4) | b(5) },	/* 720K   {1.2M, 360K, 720K} */	{ 2,  b(2) | b(3) },		/* 360K   {360K, 720K} */	/* Note that type 0 is missing, type 3 can read/write it too, which is	 * why the type 3 parameters have been pessimized to be like type 0.	 */};/* Variables. */PRIVATE struct floppy {		/* main drive struct, one entry per drive */  unsigned fl_curcyl;		/* current cylinder */  unsigned fl_hardcyl;		/* hardware cylinder, as opposed to: */  unsigned fl_cylinder;		/* cylinder number addressed */  unsigned fl_sector;		/* sector addressed */  unsigned fl_head;		/* head number addressed */  char fl_calibration;		/* CALIBRATED or UNCALIBRATED */  u8_t fl_density;		/* NO_DENS = ?, 0 = 360K; 1 = 360K/1.2M; etc.*/  u8_t fl_class;		/* bitmap for possible densities */  timer_t fl_tmr_stop;		/* timer to stop motor */  struct device fl_geom;	/* Geometry of the drive */  struct device fl_part[NR_PARTITIONS];  /* partition's base & size */} floppy[NR_DRIVES];PRIVATE int irq_hook_id;	/* id of irq hook at the kernel */PRIVATE int motor_status;	/* bitmap of current motor status */PRIVATE int need_reset;		/* set to 1 when controller must be reset */PRIVATE unsigned f_drive;	/* selected drive */PRIVATE unsigned f_device;	/* selected minor device */PRIVATE struct floppy *f_fp;	/* current drive */PRIVATE struct density *f_dp;	/* current density parameters */PRIVATE struct density *prev_dp;/* previous density parameters */PRIVATE unsigned f_sectors;	/* equal to f_dp->secpt (needed a lot) */PRIVATE u16_t f_busy;		/* BSY_IDLE, BSY_IO, BSY_WAKEN */PRIVATE struct device *f_dv;	/* device's base and size */PRIVATE struct disk_parameter_s fmt_param; /* parameters for format */PRIVATE u8_t f_results[MAX_RESULTS];/* the controller can give lots of output *//* The floppy uses various timers. These are managed by the floppy driver * itself, because only a single synchronous alarm is available per process. * Besides the 'f_tmr_timeout' timer below, the floppy structure for each * floppy disk drive contains a 'fl_tmr_stop' timer.  */PRIVATE timer_t f_tmr_timeout;		/* timer for various timeouts */PRIVATE timer_t *f_timers;		/* queue of floppy timers */PRIVATE clock_t f_next_timeout; 	/* the next timeout time */FORWARD _PROTOTYPE( void f_expire_tmrs, (struct driver *dp, message *m_ptr) );FORWARD _PROTOTYPE( void f_set_timer, (timer_t *tp, clock_t delta,						 tmr_func_t watchdog) 	);FORWARD _PROTOTYPE( void stop_motor, (timer_t *tp) 			);FORWARD _PROTOTYPE( void f_timeout, (timer_t *tp) 			);FORWARD _PROTOTYPE( struct device *f_prepare, (int device) 		);FORWARD _PROTOTYPE( char *f_name, (void) 				);FORWARD _PROTOTYPE( void f_cleanup, (void) 				);FORWARD _PROTOTYPE( int f_transfer, (int proc_nr, int opcode, off_t position,					iovec_t *iov, unsigned nr_req) 	);FORWARD _PROTOTYPE( int dma_setup, (int opcode) 			);FORWARD _PROTOTYPE( void start_motor, (void) 				);FORWARD _PROTOTYPE( int seek, (void) 					);FORWARD _PROTOTYPE( int fdc_transfer, (int opcode) 			);FORWARD _PROTOTYPE( int fdc_results, (void) 				);FORWARD _PROTOTYPE( int fdc_command, (u8_t *cmd, int len) 		);FORWARD _PROTOTYPE( void fdc_out, (int val) 				);FORWARD _PROTOTYPE( int recalibrate, (void) 				);FORWARD _PROTOTYPE( void f_reset, (void) 				);FORWARD _PROTOTYPE( int f_intr_wait, (void) 				);FORWARD _PROTOTYPE( int read_id, (void) 				);FORWARD _PROTOTYPE( int f_do_open, (struct driver *dp, message *m_ptr) 	);FORWARD _PROTOTYPE( void floppy_stop, (struct driver *dp, message *m_ptr));FORWARD _PROTOTYPE( int test_read, (int density)	 		);FORWARD _PROTOTYPE( void f_geometry, (struct partition *entry)		);/* Entry points to this driver. */PRIVATE struct driver f_dtab = {  f_name,	/* current device's name */  f_do_open,	/* open or mount request, sense type of diskette */  do_nop,	/* nothing on a close */  do_diocntl,	/* get or set a partitions geometry */  f_prepare,	/* prepare for I/O on a given minor device */  f_transfer,	/* do the I/O */  f_cleanup,	/* cleanup before sending reply to user process */  f_geometry,	/* tell the geometry of the diskette */  floppy_stop,	/* floppy cleanup on shutdown */  f_expire_tmrs,/* expire all alarm timers */  nop_cancel,  nop_select,  NULL,  NULL};/*===========================================================================* *				floppy_task				     * *===========================================================================*/PUBLIC void main(){/* Initialize the floppy structure and the timers. */  struct floppy *fp;  int s;  struct sigaction sa;  sa.sa_handler = SIG_MESS;  sigemptyset(&sa.sa_mask);  sa.sa_flags = 0;  if (sigaction(SIGTERM,&sa,NULL)<0) panic("floppy","sigaction failed", errno);  signal(SIGTERM, SIG_IGN);  f_next_timeout = TMR_NEVER;  tmr_inittimer(&f_tmr_timeout);  for (fp = &floppy[0]; fp < &floppy[NR_DRIVES]; fp++) {	fp->fl_curcyl = NO_CYL;	fp->fl_density = NO_DENS;	fp->fl_class = ~0;	tmr_inittimer(&fp->fl_tmr_stop);  }  /* Set IRQ policy, only request notifications, do not automatically    * reenable interrupts. ID return on interrupt is the IRQ line number.    */  irq_hook_id = FLOPPY_IRQ;  if ((s=sys_irqsetpolicy(FLOPPY_IRQ, 0, &irq_hook_id )) != OK)  	panic("FLOPPY", "Couldn't set IRQ policy", s);  if ((s=sys_irqenable(&irq_hook_id)) != OK)  	panic("FLOPPY", "Couldn't enable IRQs", s);  driver_task(&f_dtab);}

⌨️ 快捷键说明

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