📄 ide-disk.c
字号:
return (lba48bit) ? WIN_MULTREAD_EXT : WIN_MULTREAD; else if (cmd == READ) return (lba48bit) ? WIN_READ_EXT : WIN_READ; else if ((cmd == WRITE) && (drive->using_dma)) return (lba48bit) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; else if ((cmd == WRITE) && (drive->mult_count)) return (lba48bit) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE; else if (cmd == WRITE) return (lba48bit) ? WIN_WRITE_EXT : WIN_WRITE; else return WIN_NOP;}static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block){ struct hd_drive_task_hdr taskfile; struct hd_drive_hob_hdr hobfile; ide_task_t args; task_ioreg_t command = get_command(drive, rq->cmd); unsigned int track = (block / drive->sect); unsigned int sect = (block % drive->sect) + 1; unsigned int head = (track % drive->head); unsigned int cyl = (track / drive->head); memset(&taskfile, 0, sizeof(task_struct_t)); memset(&hobfile, 0, sizeof(hob_struct_t)); taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors; taskfile.sector_number = sect; taskfile.low_cylinder = cyl; taskfile.high_cylinder = (cyl>>8); taskfile.device_head = head; taskfile.device_head |= drive->select.all; taskfile.command = command;#ifdef DEBUG printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); if (lba) printk("LBAsect=%lld, ", block); else printk("CHS=%d/%d/%d, ", cyl, head, sect); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);#endif memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); args.command_type = ide_cmd_type_parser(&args); args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); args.handler = ide_handler_parser(&taskfile, &hobfile); args.posthandler = NULL; args.rq = (struct request *) rq; args.block = block; rq->special = NULL; rq->special = (ide_task_t *)&args; return do_rw_taskfile(drive, &args);}static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block){ struct hd_drive_task_hdr taskfile; struct hd_drive_hob_hdr hobfile; ide_task_t args; task_ioreg_t command = get_command(drive, rq->cmd); memset(&taskfile, 0, sizeof(task_struct_t)); memset(&hobfile, 0, sizeof(hob_struct_t)); taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors; taskfile.sector_number = block; taskfile.low_cylinder = (block>>=8); taskfile.high_cylinder = (block>>=8); taskfile.device_head = ((block>>8)&0x0f); taskfile.device_head |= drive->select.all; taskfile.command = command;#ifdef DEBUG printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); if (lba) printk("LBAsect=%lld, ", block); else printk("CHS=%d/%d/%d, ", cyl, head, sect); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);#endif memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); args.command_type = ide_cmd_type_parser(&args); args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); args.handler = ide_handler_parser(&taskfile, &hobfile); args.posthandler = NULL; args.rq = (struct request *) rq; args.block = block; rq->special = NULL; rq->special = (ide_task_t *)&args; return do_rw_taskfile(drive, &args);}/* * 268435455 == 137439 MB or 28bit limit * 320173056 == 163929 MB or 48bit addressing * 1073741822 == 549756 MB or 48bit addressing fake drive */static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block){ struct hd_drive_task_hdr taskfile; struct hd_drive_hob_hdr hobfile; ide_task_t args; task_ioreg_t command = get_command(drive, rq->cmd); memset(&taskfile, 0, sizeof(task_struct_t)); memset(&hobfile, 0, sizeof(hob_struct_t)); taskfile.sector_count = rq->nr_sectors; hobfile.sector_count = (rq->nr_sectors>>8); if (rq->nr_sectors == 65536) { taskfile.sector_count = 0x00; hobfile.sector_count = 0x00; } taskfile.sector_number = block; /* low lba */ taskfile.low_cylinder = (block>>=8); /* mid lba */ taskfile.high_cylinder = (block>>=8); /* hi lba */ hobfile.sector_number = (block>>=8); /* low lba */ hobfile.low_cylinder = (block>>=8); /* mid lba */ hobfile.high_cylinder = (block>>=8); /* hi lba */ taskfile.device_head = drive->select.all; hobfile.device_head = taskfile.device_head; hobfile.control = (drive->ctl|0x80); taskfile.command = command;#ifdef DEBUG printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); if (lba) printk("LBAsect=%lld, ", block); else printk("CHS=%d/%d/%d, ", cyl, head, sect); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);#endif memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); args.command_type = ide_cmd_type_parser(&args); args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); args.handler = ide_handler_parser(&taskfile, &hobfile); args.posthandler = NULL; args.rq = (struct request *) rq; args.block = block; rq->special = NULL; rq->special = (ide_task_t *)&args; return do_rw_taskfile(drive, &args);}#else /* !__TASKFILE__IO *//* * do_rw_disk() issues READ and WRITE commands to a disk, * using LBA if supported, or CHS otherwise, to address sectors. * It also takes care of issuing special DRIVE_CMDs. */static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block){ if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl,IDE_CONTROL_REG);#ifdef CONFIG_BLK_DEV_PDC4030 if (drive->select.b.lba || IS_PDC4030_DRIVE) {#else /* !CONFIG_BLK_DEV_PDC4030 */ if (drive->select.b.lba) {#endif /* CONFIG_BLK_DEV_PDC4030 */ if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) { task_ioreg_t tasklets[10]; tasklets[0] = 0; tasklets[1] = 0; tasklets[2] = rq->nr_sectors; tasklets[3] = (rq->nr_sectors>>8); if (rq->nr_sectors == 65536) { tasklets[2] = 0x00; tasklets[3] = 0x00; } tasklets[4] = (task_ioreg_t) block; tasklets[5] = (task_ioreg_t) (block>>8); tasklets[6] = (task_ioreg_t) (block>>16); tasklets[7] = (task_ioreg_t) (block>>24); tasklets[8] = (task_ioreg_t) 0; tasklets[9] = (task_ioreg_t) 0;// tasklets[8] = (task_ioreg_t) (block>>32);// tasklets[9] = (task_ioreg_t) (block>>40);#ifdef DEBUG printk("%s: %sing: LBAsect=%lu, sectors=%ld, buffer=0x%08lx, LBAsect=0x%012lx\n", drive->name, (rq->cmd==READ)?"read":"writ", block, rq->nr_sectors, (unsigned long) rq->buffer, block); printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n", drive->name, tasklets[3], tasklets[2], tasklets[9], tasklets[8], tasklets[7], tasklets[6], tasklets[5], tasklets[4]);#endif OUT_BYTE(tasklets[1], IDE_FEATURE_REG); OUT_BYTE(tasklets[3], IDE_NSECTOR_REG); OUT_BYTE(tasklets[7], IDE_SECTOR_REG); OUT_BYTE(tasklets[8], IDE_LCYL_REG); OUT_BYTE(tasklets[9], IDE_HCYL_REG); OUT_BYTE(tasklets[0], IDE_FEATURE_REG); OUT_BYTE(tasklets[2], IDE_NSECTOR_REG); OUT_BYTE(tasklets[4], IDE_SECTOR_REG); OUT_BYTE(tasklets[5], IDE_LCYL_REG); OUT_BYTE(tasklets[6], IDE_HCYL_REG); OUT_BYTE(0x00|drive->select.all,IDE_SELECT_REG); } else {#ifdef DEBUG printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n", drive->name, (rq->cmd==READ)?"read":"writ", block, rq->nr_sectors, (unsigned long) rq->buffer);#endif OUT_BYTE(0x00, IDE_FEATURE_REG); OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG); OUT_BYTE(block,IDE_SECTOR_REG); OUT_BYTE(block>>=8,IDE_LCYL_REG); OUT_BYTE(block>>=8,IDE_HCYL_REG); OUT_BYTE(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG); } } else { unsigned int sect,head,cyl,track; track = block / drive->sect; sect = block % drive->sect + 1; OUT_BYTE(sect,IDE_SECTOR_REG); head = track % drive->head; cyl = track / drive->head; OUT_BYTE(0x00, IDE_FEATURE_REG); OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG); OUT_BYTE(cyl,IDE_LCYL_REG); OUT_BYTE(cyl>>8,IDE_HCYL_REG); OUT_BYTE(head|drive->select.all,IDE_SELECT_REG);#ifdef DEBUG printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n", drive->name, (rq->cmd==READ)?"read":"writ", cyl, head, sect, rq->nr_sectors, (unsigned long) rq->buffer);#endif }#ifdef CONFIG_BLK_DEV_PDC4030 if (IS_PDC4030_DRIVE) { extern ide_startstop_t do_pdc4030_io(ide_drive_t *, struct request *); return do_pdc4030_io (drive, rq); }#endif /* CONFIG_BLK_DEV_PDC4030 */ if (rq->cmd == READ) {#ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive))) return ide_started;#endif /* CONFIG_BLK_DEV_IDEDMA */ ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) { OUT_BYTE(drive->mult_count ? WIN_MULTREAD_EXT : WIN_READ_EXT, IDE_COMMAND_REG); } else { OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG); } return ide_started; } if (rq->cmd == WRITE) { ide_startstop_t startstop;#ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive))) return ide_started;#endif /* CONFIG_BLK_DEV_IDEDMA */ if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) { OUT_BYTE(drive->mult_count ? WIN_MULTWRITE_EXT : WIN_WRITE_EXT, IDE_COMMAND_REG); } else { OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG); } if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name, drive->mult_count ? "MULTWRITE" : "WRITE"); return startstop; } if (!drive->unmask) __cli(); /* local CPU only */ if (drive->mult_count) { ide_hwgroup_t *hwgroup = HWGROUP(drive); /* * Ugh.. this part looks ugly because we MUST set up * the interrupt handler before outputting the first block * of data to be written. If we hit an error (corrupted buffer list) * in ide_multwrite(), then we need to remove the handler/timer * before returning. Fortunately, this NEVER happens (right?). * * Except when you get an error it seems... */ hwgroup->wrq = *rq; /* scratchpad */ ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); if (ide_multwrite(drive, drive->mult_count)) { unsigned long flags; spin_lock_irqsave(&io_request_lock, flags); hwgroup->handler = NULL; del_timer(&hwgroup->timer); spin_unlock_irqrestore(&io_request_lock, flags); return ide_stopped; } } else { ide_set_handler (drive, &write_intr, WAIT_CMD, NULL); idedisk_output_data(drive, rq->buffer, SECTOR_WORDS); } return ide_started; } printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); ide_end_request(0, HWGROUP(drive)); return ide_stopped;}#endif /* __TASKFILE__IO */static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive){ MOD_INC_USE_COUNT; if (drive->removable && drive->usage == 1) { struct hd_drive_task_hdr taskfile; struct hd_drive_hob_hdr hobfile; memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); taskfile.command = WIN_DOORLOCK; check_disk_change(inode->i_rdev); /* * Ignore the return code from door_lock, * since the open() has already succeeded, * and the door_lock is irrelevant at this point. */ if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL)) drive->doorlocking = 0; } return 0;}static int do_idedisk_flushcache(ide_drive_t *drive);static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive){ if (drive->removable && !drive->usage) { struct hd_drive_task_hdr taskfile; struct hd_drive_hob_hdr hobfile; memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); taskfile.command = WIN_DOORUNLOCK; invalidate_bdev(inode->i_bdev, 0); if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL)) drive->doorlocking = 0; } if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) if (do_idedisk_flushcache(drive)) printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", drive->name); MOD_DEC_USE_COUNT;}static int idedisk_media_change (ide_drive_t *drive){ return drive->removable; /* if removable, always assume it was changed */}static void idedisk_revalidate (ide_drive_t *drive){ grok_partitions(HWIF(drive)->gd, drive->select.b.unit, 1<<PARTN_BITS, current_capacity(drive));}/* * Queries for true maximum capacity of the drive. * Returns maximum LBA address (> 0) of the drive, 0 if failed. */static unsigned long idedisk_read_native_max_address(ide_drive_t *drive){ ide_task_t args; unsigned long addr = 0; if (!(drive->id->command_set_1 & 0x0400) && !(drive->id->cfs_enable_2 & 0x0100))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -