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

📄 pd.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	int unit, res;	long flags;	unit = DEVICE_NR(dev);	if ((unit >= PD_UNITS) || !PD.present)		return -ENODEV;	save_flags(flags);	cli(); 	if (PD.access > 1) {		restore_flags(flags);		return -EBUSY;	}	pd_valid = 0;	restore_flags(flags);   	res = wipe_partitions(dev);	if (res == 0 && pd_identify(unit))		grok_partitions(dev, PD.capacity);	pd_valid = 1;	wake_up(&pd_wait_open);         return res;}#ifdef MODULE/* Glue for modules ... */void    cleanup_module(void);int     init_module(void){#ifdef PARIDE_JUMBO       { extern paride_init();         paride_init();       } #endif        return pd_init();}void    cleanup_module(void){	int unit;	devfs_unregister_blkdev(MAJOR_NR, name);	del_gendisk(&pd_gendisk);	for (unit=0; unit<PD_UNITS; unit++) 		if (PD.present)			pi_release(PI);}#endif#define	WR(c,r,v)	pi_write_regr(PI,c,r,v)#define	RR(c,r)		(pi_read_regr(PI,c,r))#define DRIVE		(0xa0+0x10*PD.drive)/*  ide command interface */static void pd_print_error( int unit, char * msg, int status ){       int     i;	printk("%s: %s: status = 0x%x =",PD.name,msg,status);        for(i=0;i<18;i++) if (status & (1<<i)) printk(" %s",pd_errs[i]);	printk("\n");}static void pd_reset( int unit )    /* called only for MASTER drive */{       pi_connect(PI);	WR(1,6,4);        udelay(50);        WR(1,6,0);	pi_disconnect(PI);	udelay(250);}#define DBMSG(msg)	((verbose>1)?(msg):NULL)static int pd_wait_for( int unit, int w, char * msg )    /* polled wait */{       int     k, r, e;        k=0;        while(k < PD_SPIN) {             r = RR(1,6);            k++;            if (((r & w) == w) && !(r & STAT_BUSY)) break;            udelay(PD_SPIN_DEL);        }        e = (RR(0,1)<<8) + RR(0,7);        if (k >= PD_SPIN)  e |= ERR_TMO;        if ((e & (STAT_ERR|ERR_TMO)) && (msg != NULL)) 		pd_print_error(unit,msg,e);        return e;}static void pd_send_command( int unit, int n, int s, int h, 			     int c0, int c1, int func ){        WR(0,6,DRIVE+h);        WR(0,1,0);                /* the IDE task file */        WR(0,2,n);        WR(0,3,s);        WR(0,4,c0);        WR(0,5,c1);        WR(0,7,func);        udelay(1);}static void pd_ide_command( int unit, int func, int block, int count )/* Don't use this call if the capacity is zero. */{       int c1, c0, h, s;        s  = ( block % PD.sectors) + 1;        h  = ( block / PD.sectors) % PD.heads;        c0 = ( block / (PD.sectors*PD.heads)) % 256;        c1 = ( block / (PD.sectors*PD.heads*256));        pd_send_command(unit,count,s,h,c0,c1,func);}/* According to the ATA standard, the default CHS geometry should be   available following a reset.  Some Western Digital drives come up   in a mode where only LBA addresses are accepted until the device   parameters are initialised.*/static void pd_init_dev_parms( int unit ) {       pi_connect(PI);        pd_wait_for(unit,0,DBMSG("before init_dev_parms"));        pd_send_command(unit,PD.sectors,0,PD.heads-1,0,0,IDE_INIT_DEV_PARMS);        udelay(300);        pd_wait_for(unit,0,"Initialise device parameters");        pi_disconnect(PI);}static void pd_doorlock( int unit, int func ){       pi_connect(PI);        if (pd_wait_for(unit,STAT_READY,"Lock") & STAT_ERR) {                pi_disconnect(PI);                return;        }        pd_send_command(unit,1,0,0,0,0,func);        pd_wait_for(unit,STAT_READY,"Lock done");        pi_disconnect(PI);}static void pd_eject( int unit ){	pi_connect(PI);        pd_wait_for(unit,0,DBMSG("before unlock on eject"));        pd_send_command(unit,1,0,0,0,0,IDE_DOORUNLOCK);        pd_wait_for(unit,0,DBMSG("after unlock on eject"));        pd_wait_for(unit,0,DBMSG("before eject"));        pd_send_command(unit,0,0,0,0,0,IDE_EJECT);        pd_wait_for(unit,0,DBMSG("after eject"));        pi_disconnect(PI);}static void pd_media_check( int unit ){       int 	r;        pi_connect(PI);        r = pd_wait_for(unit,STAT_READY,DBMSG("before media_check"));        if (!(r & STAT_ERR)) {                pd_send_command(unit,1,1,0,0,0,IDE_READ_VRFY);                  r = pd_wait_for(unit,STAT_READY,DBMSG("RDY after READ_VRFY"));        } else PD.changed = 1;   /* say changed if other error */        if (r & ERR_MC) {                PD.changed = 1;                pd_send_command(unit,1,0,0,0,0,IDE_ACKCHANGE);                pd_wait_for(unit,STAT_READY,DBMSG("RDY after ACKCHANGE"));		pd_send_command(unit,1,1,0,0,0,IDE_READ_VRFY);                r = pd_wait_for(unit,STAT_READY,DBMSG("RDY after VRFY"));        }        pi_disconnect(PI);}static void pd_standby_off( int unit ){       pi_connect(PI);        pd_wait_for(unit,0,DBMSG("before STANDBY"));        pd_send_command(unit,0,0,0,0,0,IDE_STANDBY);        pd_wait_for(unit,0,DBMSG("after STANDBY"));        pi_disconnect(PI);}#define  word_val(n) ((pd_scratch[2*n]&0xff)+256*(pd_scratch[2*n+1]&0xff))static int pd_identify( int unit ){       int	j;	char id[PD_ID_LEN+1];/* WARNING:  here there may be dragons.  reset() applies to both drives,   but we call it only on probing the MASTER. This should allow most   common configurations to work, but be warned that a reset can clear   settings on the SLAVE drive.*/ 	if (PD.drive == 0) pd_reset(unit);        pi_connect(PI);	WR(0,6,DRIVE);        pd_wait_for(unit,0,DBMSG("before IDENT"));          pd_send_command(unit,1,0,0,0,0,IDE_IDENTIFY);        if (pd_wait_for(unit,STAT_DRQ,DBMSG("IDENT DRQ")) & STAT_ERR) {                pi_disconnect(PI);                return 0;        }        pi_read_block(PI,pd_scratch,512);        pi_disconnect(PI);        PD.sectors = word_val(6);        PD.heads = word_val(3);        PD.cylinders  = word_val(1);        PD.capacity = PD.sectors*PD.heads*PD.cylinders;        for(j=0;j<PD_ID_LEN;j++) id[j^1] = pd_scratch[j+PD_ID_OFF];        j = PD_ID_LEN-1;        while ((j >= 0) && (id[j] <= 0x20)) j--;        j++; id[j] = 0;        PD.removable = (word_val(0) & 0x80);         printk("%s: %s, %s, %d blocks [%dM], (%d/%d/%d), %s media\n",                    PD.name,id,		    PD.drive?"slave":"master",		    PD.capacity,PD.capacity/2048,                    PD.cylinders,PD.heads,PD.sectors,                    PD.removable?"removable":"fixed");        if (PD.capacity) pd_init_dev_parms(unit);        if (!PD.standby) pd_standby_off(unit);	        return 1;}static int pd_probe_drive( int unit ){	if (PD.drive == -1) {		for (PD.drive=0;PD.drive<=1;PD.drive++)			if (pd_identify(unit))				return 1;		return 0;	}	return pd_identify(unit);}static int pd_detect( void ){       int	k, unit;	k = 0;	if (pd_drive_count == 0) {  /* nothing spec'd - so autoprobe for 1 */	    unit = 0;	    if (pi_init(PI,1,-1,-1,-1,-1,-1,pd_scratch,	             PI_PD,verbose,PD.name)) {		if (pd_probe_drive(unit)) {			PD.present = 1;			k = 1;		} else pi_release(PI);	    }   	} else for (unit=0;unit<PD_UNITS;unit++) if (DU[D_PRT])	    if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],			DU[D_PRO],DU[D_DLY],pd_scratch,			PI_PD,verbose,PD.name)) {                if (pd_probe_drive(unit)) {                        PD.present = 1;                        k = unit+1;                } else pi_release(PI);            }	for (unit=0;unit<PD_UNITS;unit++)		register_disk(&pd_gendisk,mk_kdev(MAJOR_NR,unit<<PD_BITS),				PD_PARTNS,&pd_fops,				PD.present?PD.capacity:0);/* We lie about the number of drives found, as the generic partition   scanner assumes that the drives are numbered sequentially from 0.   This can result in some bogus error messages if non-sequential   drive numbers are used.*/	if (k)		return k;         printk("%s: no valid drive found\n",name);        return 0;}/* The i/o request engine */static int pd_ready( void ){ 	int unit = pd_unit;	return (!(RR(1,6) & STAT_BUSY)) ;}static void do_pd_request (request_queue_t * q){	int	unit;        if (pd_busy) return;repeat:        if (QUEUE_EMPTY || (CURRENT->rq_status == RQ_INACTIVE)) return;        INIT_REQUEST;        pd_dev = minor(CURRENT->rq_dev);	pd_unit = unit = DEVICE_NR(CURRENT->rq_dev);        pd_block = CURRENT->sector;        pd_run = CURRENT->nr_sectors;        pd_count = CURRENT->current_nr_sectors;        if ((pd_dev >= PD_DEVS) || 	    ((pd_block+pd_count) > pd_hd[pd_dev].nr_sects)) {                end_request(0);                goto repeat;        }	pd_cmd = rq_data_dir(CURRENT);        pd_buf = CURRENT->buffer;        pd_retries = 0;	pd_busy = 1;        if (pd_cmd == READ) pi_do_claimed(PI,do_pd_read);        else if (pd_cmd == WRITE) pi_do_claimed(PI,do_pd_write);        else {  pd_busy = 0;		end_request(0);                goto repeat;        }}static void pd_next_buf( int unit ){	long	saved_flags;	spin_lock_irqsave(&pd_lock,saved_flags);	end_request(1);	if (!pd_run) {  spin_unlock_irqrestore(&pd_lock,saved_flags);			return; 	}	/* paranoia */	if (QUEUE_EMPTY ||	    (rq_data_dir(CURRENT) != pd_cmd) ||	    (minor(CURRENT->rq_dev) != pd_dev) ||	    (CURRENT->rq_status == RQ_INACTIVE) ||	    (CURRENT->sector != pd_block)) 		printk("%s: OUCH: request list changed unexpectedly\n",			PD.name);	pd_count = CURRENT->current_nr_sectors;	pd_buf = CURRENT->buffer;	spin_unlock_irqrestore(&pd_lock,saved_flags);}static void do_pd_read( void ){	ps_set_intr(do_pd_read_start,0,0,nice);}static void do_pd_read_start( void ) {       int	unit = pd_unit;	long    saved_flags;	pd_busy = 1;        pi_connect(PI);        if (pd_wait_for(unit,STAT_READY,"do_pd_read") & STAT_ERR) {                pi_disconnect(PI);                if (pd_retries < PD_MAX_RETRIES) {                        pd_retries++;                        pi_do_claimed(PI,do_pd_read_start);			return;                }		spin_lock_irqsave(&pd_lock,saved_flags);                end_request(0);                pd_busy = 0;		do_pd_request(NULL);		spin_unlock_irqrestore(&pd_lock,saved_flags);                return;        }        pd_ide_command(unit,IDE_READ,pd_block,pd_run);        ps_set_intr(do_pd_read_drq,pd_ready,PD_TMO,nice);}static void do_pd_read_drq( void ){       int	unit = pd_unit;	long    saved_flags;	while (1) {            if (pd_wait_for(unit,STAT_DRQ,"do_pd_read_drq") & STAT_ERR) {                pi_disconnect(PI);                if (pd_retries < PD_MAX_RETRIES) {                        pd_retries++;                        pi_do_claimed(PI,do_pd_read_start);                        return;                }		spin_lock_irqsave(&pd_lock,saved_flags);                end_request(0);                pd_busy = 0;		do_pd_request(NULL);		spin_unlock_irqrestore(&pd_lock,saved_flags);                return;            }            pi_read_block(PI,pd_buf,512);            pd_count--; pd_run--;            pd_buf += 512;	    pd_block++;	    if (!pd_run) break;	    if (!pd_count) pd_next_buf(unit);        }        pi_disconnect(PI);	spin_lock_irqsave(&pd_lock,saved_flags);        end_request(1);        pd_busy = 0;	do_pd_request(NULL);	spin_unlock_irqrestore(&pd_lock,saved_flags);}static void do_pd_write( void ){	 ps_set_intr(do_pd_write_start,0,0,nice);}static void do_pd_write_start( void ){       int 	unit = pd_unit;	long    saved_flags;	pd_busy = 1;        pi_connect(PI);        if (pd_wait_for(unit,STAT_READY,"do_pd_write") & STAT_ERR) {                pi_disconnect(PI);                if (pd_retries < PD_MAX_RETRIES) {                        pd_retries++;			pi_do_claimed(PI,do_pd_write_start);                        return;                }		spin_lock_irqsave(&pd_lock,saved_flags);                end_request(0);                pd_busy = 0;		do_pd_request(NULL);		spin_unlock_irqrestore(&pd_lock,saved_flags);                return;        }        pd_ide_command(unit,IDE_WRITE,pd_block,pd_run);	while (1) {            if (pd_wait_for(unit,STAT_DRQ,"do_pd_write_drq") & STAT_ERR) {                pi_disconnect(PI);                if (pd_retries < PD_MAX_RETRIES) {                        pd_retries++;                        pi_do_claimed(PI,do_pd_write_start);                        return;                }		spin_lock_irqsave(&pd_lock,saved_flags);                end_request(0);                pd_busy = 0;		do_pd_request(NULL);                spin_unlock_irqrestore(&pd_lock,saved_flags);		return;            }            pi_write_block(PI,pd_buf,512);	    pd_count--; pd_run--;	    pd_buf += 512;	    pd_block++;	    if (!pd_run) break;	    if (!pd_count) pd_next_buf(unit);	}        ps_set_intr(do_pd_write_done,pd_ready,PD_TMO,nice);}static void do_pd_write_done( void ){       int	unit = pd_unit;	long    saved_flags;        if (pd_wait_for(unit,STAT_READY,"do_pd_write_done") & STAT_ERR) {                pi_disconnect(PI);                if (pd_retries < PD_MAX_RETRIES) {                        pd_retries++;                        pi_do_claimed(PI,do_pd_write_start);                        return;                }		spin_lock_irqsave(&pd_lock,saved_flags);                end_request(0);                pd_busy = 0;		do_pd_request(NULL);		spin_unlock_irqrestore(&pd_lock,saved_flags);                return;        }        pi_disconnect(PI);	spin_lock_irqsave(&pd_lock,saved_flags);        end_request(1);        pd_busy = 0;	do_pd_request(NULL);	spin_unlock_irqrestore(&pd_lock,saved_flags);}/* end of pd.c */MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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