📄 pd.c
字号:
while ((j < PD_NAMELEN-2) && (PD.name[j]=name[j])) j++; PD.name[j++] = 'a' + unit; PD.name[j] = 0; PD.alt_geom = DU[D_GEO]; PD.standby = DU[D_SBY]; if (DU[D_PRT]) pd_drive_count++; }}static inline int pd_new_segment(request_queue_t *q, struct request *req, int max_segments){ if (max_segments > cluster) max_segments = cluster; if (req->nr_segments < max_segments) { req->nr_segments++; q->elevator.nr_segments++; return 1; } return 0;}static int pd_back_merge_fn(request_queue_t *q, struct request *req, struct buffer_head *bh, int max_segments){ if (req->bhtail->b_data + req->bhtail->b_size == bh->b_data) return 1; return pd_new_segment(q, req, max_segments);}static int pd_front_merge_fn(request_queue_t *q, struct request *req, struct buffer_head *bh, int max_segments){ if (bh->b_data + bh->b_size == req->bh->b_data) return 1; return pd_new_segment(q, req, max_segments);}static int pd_merge_requests_fn(request_queue_t *q, struct request *req, struct request *next, int max_segments){ int total_segments = req->nr_segments + next->nr_segments; int same_segment; if (max_segments > cluster) max_segments = cluster; same_segment = 0; if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) { total_segments--; same_segment = 1; } if (total_segments > max_segments) return 0; q->elevator.nr_segments -= same_segment; req->nr_segments = total_segments; return 1;}int pd_init (void){ int i; request_queue_t * q; if (disable) return -1; if (devfs_register_blkdev(MAJOR_NR,name,&pd_fops)) { printk("%s: unable to get major number %d\n", name,major); return -1; } q = BLK_DEFAULT_QUEUE(MAJOR_NR); blk_init_queue(q, DEVICE_REQUEST); q->back_merge_fn = pd_back_merge_fn; q->front_merge_fn = pd_front_merge_fn; q->merge_requests_fn = pd_merge_requests_fn; read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */ pd_gendisk.major = major; pd_gendisk.major_name = name; pd_gendisk.next = gendisk_head; gendisk_head = &pd_gendisk; for(i=0;i<PD_DEVS;i++) pd_blocksizes[i] = 1024; blksize_size[MAJOR_NR] = pd_blocksizes; printk("%s: %s version %s, major %d, cluster %d, nice %d\n", name,name,PD_VERSION,major,cluster,nice); pd_init_units(); pd_valid = 0; pd_gendisk.nr_real = pd_detect(); pd_valid = 1;#ifdef MODULE if (!pd_gendisk.nr_real) { cleanup_module(); return -1; }#endif return 0;}static int pd_open (struct inode *inode, struct file *file){ int unit = DEVICE_NR(inode->i_rdev); if ((unit >= PD_UNITS) || (!PD.present)) return -ENODEV; MOD_INC_USE_COUNT; wait_event (pd_wait_open, pd_valid); PD.access++; if (PD.removable) { pd_media_check(unit); pd_doorlock(unit,IDE_DOORLOCK); } return 0;}static int pd_ioctl(struct inode *inode,struct file *file, unsigned int cmd, unsigned long arg){ struct hd_geometry *geo = (struct hd_geometry *) arg; int dev, err, unit; if ((!inode) || (!inode->i_rdev)) return -EINVAL; dev = MINOR(inode->i_rdev); unit = DEVICE_NR(inode->i_rdev); if (dev >= PD_DEVS) return -EINVAL; if (!PD.present) return -ENODEV; switch (cmd) { case CDROMEJECT: if (PD.access == 1) pd_eject(unit); return 0; case HDIO_GETGEO: if (!geo) return -EINVAL; err = verify_area(VERIFY_WRITE,geo,sizeof(*geo)); if (err) return err; if (PD.alt_geom) { put_user(PD.capacity/(PD_LOG_HEADS*PD_LOG_SECTS), (short *) &geo->cylinders); put_user(PD_LOG_HEADS, (char *) &geo->heads); put_user(PD_LOG_SECTS, (char *) &geo->sectors); } else { put_user(PD.cylinders, (short *) &geo->cylinders); put_user(PD.heads, (char *) &geo->heads); put_user(PD.sectors, (char *) &geo->sectors); } put_user(pd_hd[dev].start_sect,(long *)&geo->start); return 0; case BLKGETSIZE: if (!arg) return -EINVAL; err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long)); if (err) return (err); put_user(pd_hd[dev].nr_sects,(long *) arg); return (0); case BLKRRPART: if (!capable(CAP_SYS_ADMIN)) return -EACCES; return pd_revalidate(inode->i_rdev); case BLKROSET: case BLKROGET: case BLKRASET: case BLKRAGET: case BLKFLSBUF: case BLKPG: return blk_ioctl(inode->i_rdev, cmd, arg); default: return -EINVAL; }}static int pd_release (struct inode *inode, struct file *file){ kdev_t devp; int unit; devp = inode->i_rdev; unit = DEVICE_NR(devp); if ((unit >= PD_UNITS) || (PD.access <= 0)) return -EINVAL; PD.access--; if (!PD.access && PD.removable) pd_doorlock(unit,IDE_DOORUNLOCK); MOD_DEC_USE_COUNT; return 0;}static int pd_check_media( kdev_t dev){ int r, unit; unit = DEVICE_NR(dev); if ((unit >= PD_UNITS) || (!PD.present)) return -ENODEV; if (!PD.removable) return 0; pd_media_check(unit); r = PD.changed; PD.changed = 0; return r;}static int pd_revalidate(kdev_t dev){ int p, unit, minor; long flags; kdev_t devp; struct super_block *sb; 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); for (p=(PD_PARTNS-1);p>=0;p--) { minor = p + unit*PD_PARTNS; devp = MKDEV(MAJOR_NR, minor); fsync_dev(devp); sb = get_super(devp); if (sb) invalidate_inodes(sb); invalidate_buffers(devp); pd_hd[minor].start_sect = 0; pd_hd[minor].nr_sects = 0; } if (pd_identify(unit)) grok_partitions(&pd_gendisk,unit,1<<PD_BITS,PD.capacity); pd_valid = 1; wake_up(&pd_wait_open); return 0;}#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){ struct gendisk **gdp; int unit; devfs_unregister_blkdev(MAJOR_NR,name); for(gdp=&gendisk_head;*gdp;gdp=&((*gdp)->next)) if (*gdp == &pd_gendisk) break; if (*gdp) *gdp = (*gdp)->next; 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -