📄 ps2esdi.c
字号:
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); break; } outb(CTRL_ENABLE_INTR, ESDI_CONTROL);}static void ps2esdi_geometry_int_handler(u_int int_ret_code){ u_int status, drive_num; unsigned long rba; int i; drive_num = int_ret_code >> 5; switch (int_ret_code & 0xf) { 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); break; } status = inw(ESDI_STT_INT); if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {#define REPLY_WORDS 5 /* we already read word 0 */ u_short reply[REPLY_WORDS]; if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) { /*BA */ printk("%s: Device Configuration Status for drive %u\n", DEVICE_NAME, drive_num); printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8); printk ("Config bits: %s%s%s%s%s\n", (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "", ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS)) ? "Zero Defect, " : "Defects Present, ", (reply[0] & CONFIG_SF) ? "Skewed Format, " : "", (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ", (reply[0] & CONFIG_RT) ? "No Retries" : "Retries"); rba = reply[1] | ((unsigned long) reply[2] << 16); printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba); printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n", DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff); if (!ps2esdi_info[drive_num].head) { ps2esdi_info[drive_num].head = 64; ps2esdi_info[drive_num].sect = 32; ps2esdi_info[drive_num].cyl = rba / (64 * 32); ps2esdi_info[drive_num].wpcom = 0; ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl; ps2esdi_info[drive_num].ctl = 8; 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 { if (!intg_esdi) ps2esdi_drives++; } }#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){ unsigned long flags; u_int status; u_int ending; int i; switch (int_ret_code & 0x0f) { case INT_TRANSFER_REQ: ps2esdi_prep_dma(current_req->buffer, current_req->current_nr_sectors, (rq_data_dir(current_req) == READ) ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ); outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL); ending = -1; break; case INT_ATTN_ERROR: printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, int_ret_code); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); ending = FAIL; 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_req->errors) >= MAX_RETRIES) ending = FAIL; else ending = -1; 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); ending = SUCCES; 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); ending = -1; 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); ending = SUCCES; 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_req->errors) >= MAX_RETRIES) ending = FAIL; else ending = -1; 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); ending = FAIL; 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); ending = -1; 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); ending = -1; 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); ending = -1; break; } if(ending != -1) { spin_lock_irqsave(&ps2esdi_lock, flags); end_request(current_req, ending); current_req = NULL; do_ps2esdi_request(ps2esdi_queue); spin_unlock_irqrestore(&ps2esdi_lock, flags); }} /* handle interrupts */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_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg){ struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data; struct ps2esdi_geometry geom; if (cmd != HDIO_GETGEO) return -EINVAL; memset(&geom, 0, sizeof(geom)); geom.heads = p->head; geom.sectors = p->sect; geom.cylinders = p->cyl; geom.start = get_start_sect(inode->i_bdev); if (copy_to_user((void __user *)arg, &geom, sizeof(geom))) return -EFAULT; return 0;}static 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -