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

📄 xd.c

📁 <Linux1.0核心游记>电子书+书后源码+Linux1.0源码
💻 C
📖 第 1 页 / 共 2 页
字号:
static void xd_interrupt_handler (int unused){	if (inb(XD_STATUS) & STAT_INTERRUPT) {							/* check if it was our device */#ifdef DEBUG_OTHER		printk("xd_interrupt_handler: interrupt detected\n");#endif /* DEBUG_OTHER */		outb(0,XD_CONTROL);								/* acknowledge interrupt */		wake_up(&xd_wait_int);								/* and wake up sleeping processes */	}	else		printk("xd_interrupt_handler: unexpected interrupt\n");}/* xd_dma: set up the DMA controller for a data transfer */static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count){	if (buffer < ((u_char *) 0x1000000 - count)) {		/* transfer to address < 16M? */		if (((u_int) buffer & 0xFFFF0000) != ((u_int) buffer + count) & 0xFFFF0000) {#ifdef DEBUG_OTHER			printk("xd_setup_dma: using PIO, transfer overlaps 64k boundary\n");#endif /* DEBUG_OTHER */			return (PIO_MODE);		}		disable_dma(xd_dma);		clear_dma_ff(xd_dma);		set_dma_mode(xd_dma,mode);		set_dma_addr(xd_dma,(u_int) buffer);		set_dma_count(xd_dma,count);		return (DMA_MODE);			/* use DMA and INT */	}#ifdef DEBUG_OTHER	printk("xd_setup_dma: using PIO, cannot DMA above 16 meg\n");#endif /* DEBUG_OTHER */	return (PIO_MODE);}/* xd_build: put stuff into an array in a format suitable for the controller */static u_char *xd_build (u_char *cmdblk,u_char command,u_char drive,u_char head,u_short cylinder,u_char sector,u_char count,u_char control){	cmdblk[0] = command;	cmdblk[1] = ((drive & 0x07) << 5) | (head & 0x1F);	cmdblk[2] = ((cylinder & 0x300) >> 2) | (sector & 0x3F);	cmdblk[3] = cylinder & 0xFF;	cmdblk[4] = count;	cmdblk[5] = control;		return (cmdblk);}/* xd_waitport: waits until port & mask == flags or a timeout occurs. return 1 for a timeout */static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long timeout){	u_long expiry = jiffies + timeout;	while (((inb(port) & mask) != flags) && (jiffies < expiry))		;	return (jiffies >= expiry);}/* xd_command: handle all data transfers necessary for a single command */static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outdata,u_char *sense,u_long timeout){	u_char cmdblk[6],csb,complete = 0;#ifdef DEBUG_COMMAND	printk("xd_command: command = 0x%X, mode = 0x%X, indata = 0x%X, outdata = 0x%X, sense = 0x%X\n",command,mode,indata,outdata,sense);#endif /* DEBUG_COMMAND */	outb(0,XD_SELECT);	outb(mode,XD_CONTROL);	if (xd_waitport(XD_STATUS,STAT_SELECT,STAT_SELECT,timeout))		return (1);		while (!complete) {		if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout))			return (1);		switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) {			case 0:			if (mode == DMA_MODE) {							enable_dma(xd_dma);							sleep_on(&xd_wait_int);							disable_dma(xd_dma);						}						else							outb(outdata ? *outdata++ : 0,XD_DATA);						break;			case STAT_INPUT:	if (mode == DMA_MODE) {							enable_dma(xd_dma);							sleep_on(&xd_wait_int);							disable_dma(xd_dma);						}						else							if (indata)								*indata++ = inb(XD_DATA);							else								inb(XD_DATA);						break;			case STAT_COMMAND:	outb(command ? *command++ : 0,XD_DATA); break;			case STAT_COMMAND			     | STAT_INPUT:	complete = 1; break;		}	}	csb = inb(XD_DATA);	if (xd_waitport(XD_STATUS,0,STAT_SELECT,timeout))					/* wait until deselected */		return (1);	if (csb & CSB_ERROR) {									/* read sense data if error */		xd_build(cmdblk,CMD_SENSE,(csb & CSB_LUN) >> 5,0,0,0,0,0);		if (xd_command(cmdblk,0,sense,0,0,XD_TIMEOUT))			printk("xd_command: warning! sense command failed!\n");	}#ifdef DEBUG_COMMAND	printk("xd_command: completed with csb = 0x%X\n",csb);#endif /* DEBUG_COMMAND */	return (csb & CSB_ERROR);}static u_char xd_initdrives (void (*init_drive)(u_char drive)){	u_char cmdblk[6],i,count = 0;	for (i = 0; i < XD_MAXDRIVES; i++) {		xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);		if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2)) {			init_drive(count);			count++;		}	}	return (count);}static void xd_dtc_init_controller (u_char *address){	switch ((u_long) address) {		case 0xC8000:	xd_iobase = 0x320; break;		case 0xCA000:	xd_iobase = 0x324; break;		default:        printk("xd_dtc_init_controller: unsupported BIOS address %p\n",address);				xd_iobase = 0x320; break;	}	xd_irq = 5;			/* the IRQ _can_ be changed on this card, but requires a hardware mod */	xd_dma = 3;	xd_maxsectors = 0x01;		/* my card seems to have trouble doing multi-block transfers? */	outb(0,XD_RESET);		/* reset the controller */}static void xd_dtc_init_drive (u_char drive){	u_char cmdblk[6],buf[64];	xd_build(cmdblk,CMD_DTCGETGEOM,drive,0,0,0,0,0);	if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {		xd_info[drive].heads = buf[0x0A];			/* heads */		xd_info[drive].cylinders = ((u_short *) (buf))[0x04];	/* cylinders */		xd_info[drive].sectors = 17;				/* sectors */#if 0		xd_info[drive].rwrite = ((u_short *) (buf + 1))[0x05];	/* reduced write */		xd_info[drive].precomp = ((u_short *) (buf + 1))[0x06];	/* write precomp */		xd_info[drive].ecc = buf[0x0F];				/* ecc length */#endif /* 0 */		xd_info[drive].control = 0;				/* control byte */		xd_setparam(CMD_DTCSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,((u_short *) (buf + 1))[0x05],((u_short *) (buf + 1))[0x06],buf[0x0F]);		xd_build(cmdblk,CMD_DTCSETSTEP,drive,0,0,0,0,7);		if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))			printk("xd_dtc_init_drive: error setting step rate for drive %d\n",drive);	}	else		printk("xd_dtc_init_drive: error reading geometry for drive %d\n",drive);}static void xd_wd_init_controller (u_char *address){	switch ((u_long) address) {		case 0xC8000:	xd_iobase = 0x320; break;		case 0xCA000:	xd_iobase = 0x324; break;		case 0xCC000:   xd_iobase = 0x328; break;		case 0xCE000:   xd_iobase = 0x32C; break;		case 0xD0000:	xd_iobase = 0x328; break;		case 0xD8000:	xd_iobase = 0x32C; break;		default:        printk("xd_wd_init_controller: unsupported BIOS address %p\n",address);				xd_iobase = 0x320; break;	}	xd_irq = 5;			/* don't know how to auto-detect this yet */	xd_dma = 3;	xd_maxsectors = 0x01;		/* this one doesn't wrap properly either... */	/* outb(0,XD_RESET); */		/* reset the controller */}static void xd_wd_init_drive (u_char drive){	u_char cmdblk[6],buf[0x200];	xd_build(cmdblk,CMD_READ,drive,0,0,0,1,0);	if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {		xd_info[drive].heads = buf[0x1AF];				/* heads */		xd_info[drive].cylinders = ((u_short *) (buf + 1))[0xD6];	/* cylinders */		xd_info[drive].sectors = 17;					/* sectors */#if 0		xd_info[drive].rwrite = ((u_short *) (buf))[0xD8];		/* reduced write */		xd_info[drive].wprecomp = ((u_short *) (buf))[0xDA];		/* write precomp */		xd_info[drive].ecc = buf[0x1B4];				/* ecc length */#endif /* 0 */		xd_info[drive].control = buf[0x1B5];				/* control byte */		xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);	}	else		printk("xd_wd_init_drive: error reading geometry for drive %d\n",drive);	}static void xd_seagate_init_controller (u_char *address){	switch ((u_long) address) {		case 0xC8000:	xd_iobase = 0x320; break;		case 0xD0000:	xd_iobase = 0x324; break;		case 0xD8000:	xd_iobase = 0x328; break;		case 0xE0000:	xd_iobase = 0x32C; break;		default:	printk("xd_seagate_init_controller: unsupported BIOS address %p\n",address);				xd_iobase = 0x320; break;	}	xd_irq = 5;			/* the IRQ and DMA channel are fixed on the Seagate controllers */	xd_dma = 3;	xd_maxsectors = 0x40;	outb(0,XD_RESET);		/* reset the controller */}static void xd_seagate_init_drive (u_char drive){	u_char cmdblk[6],buf[0x200];	xd_build(cmdblk,CMD_ST11GETGEOM,drive,0,0,0,1,0);	if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {		xd_info[drive].heads = buf[0x04];				/* heads */		xd_info[drive].cylinders = (buf[0x02] << 8) | buf[0x03];	/* cylinders */		xd_info[drive].sectors = buf[0x05];				/* sectors */		xd_info[drive].control = 0;					/* control byte */	}	else		printk("xd_seagate_init_drive: error reading geometry from drive %d\n",drive);}/* Omti support courtesy Dirk Melchers */static void xd_omti_init_controller (u_char *address){	switch ((u_long) address) {		case 0xC8000:	xd_iobase = 0x320; break;		case 0xD0000:	xd_iobase = 0x324; break;		case 0xD8000:	xd_iobase = 0x328; break;		case 0xE0000:	xd_iobase = 0x32C; break;		default:	printk("xd_omti_init_controller: unsupported BIOS address %p\n",address);				xd_iobase = 0x320; break;	}		xd_irq = 5;			/* the IRQ and DMA channel are fixed on the Omti controllers */	xd_dma = 3;	xd_maxsectors = 0x40;	outb(0,XD_RESET);		/* reset the controller */}static void xd_omti_init_drive (u_char drive){	/* gets infos from drive */	xd_override_init_drive(drive);	/* set other parameters, Hardcoded, not that nice :-) */	xd_info[drive].control = 2;}/* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads   etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */static void xd_override_init_drive (u_char drive){	u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 };	u_char cmdblk[6],i;	for (i = 0; i < 3; i++) {		while (min[i] != max[i] - 1) {			test[i] = (min[i] + max[i]) / 2;			xd_build(cmdblk,CMD_SEEK,drive,(u_char) test[0],(u_short) test[1],(u_char) test[2],0,0);			if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))				min[i] = test[i];			else				max[i] = test[i];		}		test[i] = min[i];	}	xd_info[drive].heads = (u_char) min[0] + 1;	xd_info[drive].cylinders = (u_short) min[1] + 1;	xd_info[drive].sectors = (u_char) min[2] + 1;	xd_info[drive].control = 0;}/* xd_setup: initialise from command line parameters */void xd_setup (char *command,int *integers){	xd_override = 1;	xd_type = integers[1];	xd_irq = integers[2];	xd_iobase = integers[3];	xd_dma = integers[4];	xd_maxsectors = 0x01;}/* xd_setparam: set the drive characteristics */static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc){	u_char cmdblk[14];	xd_build(cmdblk,command,drive,0,0,0,0,0);	cmdblk[6] = (u_char) (cylinders >> 8) & 0x03;	cmdblk[7] = (u_char) (cylinders & 0xFF);	cmdblk[8] = heads & 0x1F;	cmdblk[9] = (u_char) (rwrite >> 8) & 0x03;	cmdblk[10] = (u_char) (rwrite & 0xFF);	cmdblk[11] = (u_char) (wprecomp >> 8) & 0x03;	cmdblk[12] = (u_char) (wprecomp & 0xFF);	cmdblk[13] = ecc;	if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))		printk("xd_setparam: error setting characteristics for drive %d\n",drive);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -