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

📄 ps2esdi.c

📁 Linux块设备驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		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 + -