📄 ps2esdi.c
字号:
#ifdef OBSOLETE if (!ps2esdi_info[drive_num].head) { ps2esdi_info[drive_num].head = reply[4] & 0Xff; ps2esdi_info[drive_num].sect = reply[4] >> 8; ps2esdi_info[drive_num].cyl = reply[3]; ps2esdi_info[drive_num].wpcom = 0; ps2esdi_info[drive_num].lzone = reply[3]; if (tp720esdi) { /* store the retrieved parameters */ ps2esdi_info[0].head = reply[4] & 0Xff; ps2esdi_info[0].sect = reply[4] >> 8; ps2esdi_info[0].cyl = reply[3]; ps2esdi_info[0].wpcom = 0; ps2esdi_info[0].lzone = reply[3]; } else { ps2esdi_drives++; } }#endif } else printk("%s: failed while getting device config\n", DEVICE_NAME);#undef REPLY_WORDS } else printk("%s: command %02X unknown by geometry handler\n", DEVICE_NAME, status & 0x1f); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); break; case INT_ATTN_ERROR: printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, int_ret_code); printk("%s: Device not available\n", DEVICE_NAME); break; case INT_CMD_ECC: case INT_CMD_RETRY: case INT_CMD_ECC_RETRY: case INT_CMD_WARNING: case INT_CMD_ABORT: case INT_CMD_FAILED: case INT_DMA_ERR: case INT_CMD_BLK_ERR: /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME); dump_cmd_complete_status(int_ret_code); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); break; default: printk("%s: Unknown interrupt reason: %02X\n", DEVICE_NAME, int_ret_code & 0xf); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); break; } wake_up(&ps2esdi_int); no_int_yet = FALSE; outb(CTRL_ENABLE_INTR, ESDI_CONTROL);}static void ps2esdi_normal_interrupt_handler(u_int int_ret_code){ u_int status; int i; switch (int_ret_code & 0x0f) { case INT_TRANSFER_REQ: ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors, (CURRENT->cmd == READ) ? DMA_READ_16 : DMA_WRITE_16); outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL); break; case INT_ATTN_ERROR: printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, int_ret_code); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); break; case INT_CMD_COMPLETE: for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { printk("%s: timeout reading status word\n", DEVICE_NAME); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); if ((++CURRENT->errors) < MAX_RETRIES) do_ps2esdi_request(NULL); else { end_request(FAIL); if (!QUEUE_EMPTY) do_ps2esdi_request(NULL); } break; } status = inw(ESDI_STT_INT); switch (status & 0x1F) { case (CMD_READ & 0xff): case (CMD_WRITE & 0xff): LITE_OFF; outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb(CTRL_ENABLE_INTR, ESDI_CONTROL);#if 0 printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT->bh->b_wait);#endif ps2esdi_continue_request(); break; default: printk("%s: interrupt for unknown command %02X\n", DEVICE_NAME, status & 0x1f); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); break; } break; case INT_CMD_ECC: case INT_CMD_RETRY: case INT_CMD_ECC_RETRY: LITE_OFF; dump_cmd_complete_status(int_ret_code); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); ps2esdi_continue_request(); break; case INT_CMD_WARNING: case INT_CMD_ABORT: case INT_CMD_FAILED: case INT_DMA_ERR: LITE_OFF; dump_cmd_complete_status(int_ret_code); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); if ((++CURRENT->errors) < MAX_RETRIES) do_ps2esdi_request(NULL); else { end_request(FAIL); if (!QUEUE_EMPTY) do_ps2esdi_request(NULL); } break; case INT_CMD_BLK_ERR: dump_cmd_complete_status(int_ret_code); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); end_request(FAIL); if (!QUEUE_EMPTY) do_ps2esdi_request(NULL); break; case INT_CMD_FORMAT: printk("%s: huh ? Who issued this format command ?\n" ,DEVICE_NAME); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); break; case INT_RESET: /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ; outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); break; default: printk("%s: Unknown interrupt reason: %02X\n", DEVICE_NAME, int_ret_code & 0xf); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); break; }} /* handle interrupts */static void ps2esdi_continue_request(void){ if (CURRENT->nr_sectors -= CURRENT->current_nr_sectors) { CURRENT->buffer += CURRENT->current_nr_sectors * SECT_SIZE; CURRENT->sector += CURRENT->current_nr_sectors; do_ps2esdi_request(NULL); } else { end_request(SUCCES); if (!QUEUE_EMPTY) do_ps2esdi_request(NULL); }}static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer){ int i; for (; max_words && num_words; max_words--, num_words--, buffer++) { for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { printk("%s: timeout reading status word\n", DEVICE_NAME); return FAIL; } *buffer = inw(ESDI_STT_INT); } return SUCCES;}static void dump_cmd_complete_status(u_int int_ret_code){#define WAIT_FOR_STATUS \ for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \ if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \ printk("%s: timeout reading status word\n",DEVICE_NAME); \ return; \ } int i, word_count; u_short stat_word; u_long rba; printk("%s: Device: %u, interrupt ID: %02X\n", DEVICE_NAME, int_ret_code >> 5, int_ret_code & 0xf); WAIT_FOR_STATUS; stat_word = inw(ESDI_STT_INT); word_count = (stat_word >> 8) - 1; printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count, stat_word & 0xff); if (word_count--) { WAIT_FOR_STATUS; stat_word = inw(ESDI_STT_INT); printk("%s: command status code: %02X, command error code: %02X\n", DEVICE_NAME, stat_word >> 8, stat_word & 0xff); } if (word_count--) { WAIT_FOR_STATUS; stat_word = inw(ESDI_STT_INT); printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME, (stat_word & 0x1000) ? "Ready, " : "Not Ready, ", (stat_word & 0x0800) ? "Selected, " : "Not Selected, ", (stat_word & 0x0400) ? "Write Fault, " : "", (stat_word & 0x0200) ? "Track 0, " : "", (stat_word & 0x0100) ? "Seek or command complete, " : "", stat_word >> 8); } if (word_count--) { WAIT_FOR_STATUS; stat_word = inw(ESDI_STT_INT); printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word); } if (word_count -= 2) { WAIT_FOR_STATUS; rba = inw(ESDI_STT_INT); WAIT_FOR_STATUS; rba |= inw(ESDI_STT_INT) << 16; printk(", Last Cyl: %u Head: %u Sector: %u\n", (u_short) ((rba & 0x1ff80000) >> 11), (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f)); } else printk("\n"); if (word_count--) { WAIT_FOR_STATUS; stat_word = inw(ESDI_STT_INT); printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word); } printk("\n");#undef WAIT_FOR_STATUS}static int ps2esdi_open(struct inode *inode, struct file *file){ int dev = DEVICE_NR(inode->i_rdev); if (dev < ps2esdi_drives) { while (!ps2esdi_valid[dev]) sleep_on(&ps2esdi_wait_open); access_count[dev]++; return (0); } else return (-ENODEV);}static int ps2esdi_release(struct inode *inode, struct file *file){ int dev = DEVICE_NR(inode->i_rdev); if (dev < ps2esdi_drives) { access_count[dev]--; } return 0;}static int ps2esdi_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg){ struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg; int dev = DEVICE_NR(inode->i_rdev), err; if (inode && (dev < ps2esdi_drives)) switch (cmd) { case HDIO_GETGEO: if (arg) { if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry)))) return (err); put_user(ps2esdi_info[dev].head, (char *) &geometry->heads); put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors); put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders); put_user(ps2esdi[MINOR(inode->i_rdev)].start_sect, (long *) &geometry->start); return (0); } break; case BLKGETSIZE: if (arg) { if ((err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)))) return (err); put_user(ps2esdi[MINOR(inode->i_rdev)].nr_sects, (long *) arg); return (0); } break; case BLKRRPART: if (!capable(CAP_SYS_ADMIN)) return -EACCES; return (ps2esdi_reread_partitions(inode->i_rdev)); case BLKROSET: case BLKROGET: case BLKRASET: case BLKRAGET: case BLKFLSBUF: case BLKPG: return blk_ioctl(inode->i_rdev, cmd, arg); } return (-EINVAL);}static int ps2esdi_reread_partitions(kdev_t dev){ int target = DEVICE_NR(dev); int start = target << ps2esdi_gendisk.minor_shift; int partition; cli(); ps2esdi_valid[target] = (access_count[target] != 1); sti(); if (ps2esdi_valid[target]) return (-EBUSY); for (partition = ps2esdi_gendisk.max_p - 1; partition >= 0; partition--) { int minor = (start | partition); kdev_t devp = MKDEV(MAJOR_NR, minor); struct super_block * sb = get_super(devp); sync_dev(devp); if (sb) invalidate_inodes(sb); invalidate_buffers(devp); ps2esdi_gendisk.part[start + partition].start_sect = 0; ps2esdi_gendisk.part[start + partition].nr_sects = 0; } grok_partitions(&ps2esdi_gendisk, target, 1<<6, ps2esdi_info[target].head * ps2esdi_info[target].cyl * ps2esdi_info[target].sect); ps2esdi_valid[target] = 1; wake_up(&ps2esdi_wait_open); return (0);}void ps2esdi_reset_timer(unsigned long unused){ int status; status = inb(ESDI_INTRPT); if ((status & 0xf) == INT_RESET) { outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); reset_status = 1; } wake_up(&ps2esdi_int);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -