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

📄 xd.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
		xd_gendisk.part[minor].nr_sects = 0;	};	grok_partitions(&xd_gendisk, target, 1<<6,			xd_info[target].heads * xd_info[target].cylinders * xd_info[target].sectors);	xd_valid[target] = 1;	wake_up(&xd_wait_open);	return 0;}/* xd_readwrite: handle a read/write request */static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block,u_int count){	u_char cmdblk[6],sense[4];	u_short track,cylinder;	u_char head,sector,control,mode = PIO_MODE,temp;	char **real_buffer;	register int i;	#ifdef DEBUG_READWRITE	printk("xd_readwrite: operation = %s, drive = %d, buffer = 0x%X, block = %d, count = %d\n",operation == READ ? "read" : "write",drive,buffer,block,count);#endif /* DEBUG_READWRITE */	control = xd_info[drive].control;	if (!xd_dma_buffer)		xd_dma_buffer = (char *)xd_dma_mem_alloc(xd_maxsectors * 0x200);	while (count) {		temp = count < xd_maxsectors ? count : xd_maxsectors;		track = block / xd_info[drive].sectors;		head = track % xd_info[drive].heads;		cylinder = track / xd_info[drive].heads;		sector = block % xd_info[drive].sectors;#ifdef DEBUG_READWRITE		printk("xd_readwrite: drive = %d, head = %d, cylinder = %d, sector = %d, count = %d\n",drive,head,cylinder,sector,temp);#endif /* DEBUG_READWRITE */		if (xd_dma_buffer) {			mode = xd_setup_dma(operation == READ ? DMA_MODE_READ : DMA_MODE_WRITE,(u_char *)(xd_dma_buffer),temp * 0x200);			real_buffer = &xd_dma_buffer;			for (i=0; i < (temp * 0x200); i++)				xd_dma_buffer[i] = buffer[i];		}		else			real_buffer = &buffer;		xd_build(cmdblk,operation == READ ? CMD_READ : CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control);		switch (xd_command(cmdblk,mode,(u_char *)(*real_buffer),(u_char *)(*real_buffer),sense,XD_TIMEOUT)) {			case 1:				printk("xd%c: %s timeout, recalibrating drive\n",'a'+drive,(operation == READ ? "read" : "write"));				xd_recalibrate(drive);				return (0);			case 2:				if (sense[0] & 0x30) {					printk("xd%c: %s - ",'a'+drive,(operation == READ ? "reading" : "writing"));					switch ((sense[0] & 0x30) >> 4) {					case 0: printk("drive error, code = 0x%X",sense[0] & 0x0F);						break;					case 1: printk("controller error, code = 0x%X",sense[0] & 0x0F);						break;					case 2: printk("command error, code = 0x%X",sense[0] & 0x0F);						break;					case 3: printk("miscellaneous error, code = 0x%X",sense[0] & 0x0F);						break;					}				}				if (sense[0] & 0x80)					printk(" - CHS = %d/%d/%d\n",((sense[2] & 0xC0) << 2) | sense[3],sense[1] & 0x1F,sense[2] & 0x3F);				/*	reported drive number = (sense[1] & 0xE0) >> 5 */				else					printk(" - no valid disk address\n");				return (0);		}		if (xd_dma_buffer)			for (i=0; i < (temp * 0x200); i++)				buffer[i] = xd_dma_buffer[i];		count -= temp, buffer += temp * 0x200, block += temp;	}	return (1);}/* xd_recalibrate: recalibrate a given drive and reset controller if necessary */static void xd_recalibrate (u_char drive){	u_char cmdblk[6];		xd_build(cmdblk,CMD_RECALIBRATE,drive,0,0,0,0,0);	if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8))		printk("xd%c: warning! error recalibrating, controller may be unstable\n", 'a'+drive);}/* xd_interrupt_handler: interrupt service routine */static void xd_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs){	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: unexpected interrupt\n");}/* xd_setup_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){	unsigned long f;		if (nodma)		return (PIO_MODE);	if (((unsigned long) buffer & 0xFFFF0000) != (((unsigned long) buffer + count) & 0xFFFF0000)) {#ifdef DEBUG_OTHER		printk("xd_setup_dma: using PIO, transfer overlaps 64k boundary\n");#endif /* DEBUG_OTHER */		return (PIO_MODE);	}		f=claim_dma_lock();	disable_dma(xd_dma);	clear_dma_ff(xd_dma);	set_dma_mode(xd_dma,mode);	set_dma_addr(xd_dma, (unsigned long) buffer);	set_dma_count(xd_dma,count);		release_dma_lock(f);	return (DMA_MODE);			/* use DMA and INT */}/* 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_wakeup is called from timer interrupt */static void xd_wakeup (unsigned long unused){	wake_up(&xdc_wait);}/* xd_wakeup is called from timer interrupt */static void xd_watchdog (unsigned long unused){	xd_error = 1;	wake_up(&xd_wait_int);}/* 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;	int success;	xdc_busy = 1;	while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry)) {		xd_timer.expires = jiffies;		cli();		add_timer(&xd_timer);		sleep_on(&xdc_wait);		del_timer(&xd_timer);		sti();	}	xdc_busy = 0;	return (success);}static inline u_int xd_wait_for_IRQ (void){	unsigned long flags;	xd_watchdog_int.expires = jiffies + 8 * HZ;	add_timer(&xd_watchdog_int);		flags=claim_dma_lock();	enable_dma(xd_dma);	release_dma_lock(flags);		sleep_on(&xd_wait_int);	del_timer(&xd_watchdog_int);	xdc_busy = 0;		flags=claim_dma_lock();	disable_dma(xd_dma);	release_dma_lock(flags);		if (xd_error) {		printk("xd: missed IRQ - command aborted\n");		xd_error = 0;		return (1);	}	return (0);}/* 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) {					if (xd_wait_for_IRQ())						return (1);				} else					outb(outdata ? *outdata++ : 0,XD_DATA);				break;			case STAT_INPUT:				if (mode == DMA_MODE) {					if (xd_wait_for_IRQ())						return (1);				} 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: 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 __init 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 * 8)) {	 		xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;			add_timer(&xd_timer);			sleep_on(&xdc_wait);			init_drive(count);			count++;	 		xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;			add_timer(&xd_timer);			sleep_on(&xdc_wait);		}	}	return (count);}static void __init xd_manual_geo_set (u_char drive){	xd_info[drive].heads = (u_char)(xd_geo[3 * drive + 1]);	xd_info[drive].cylinders = (u_short)(xd_geo[3 * drive]);	xd_info[drive].sectors = (u_char)(xd_geo[3 * drive + 2]);}static void __init xd_dtc_init_controller (unsigned int address){	switch (address) {		case 0x00000:		case 0xC8000:	break;			/*initial: 0x320 */		case 0xCA000:	xd_iobase = 0x324; 		case 0xD0000:				/*5150CX*/		case 0xD8000:	break;			/*5150CX & 5150XL*/		default:        printk("xd_dtc_init_controller: unsupported BIOS address %06x\n",address);				break;	}	xd_maxsectors = 0x01;		/* my card seems to have trouble doing multi-block transfers? */	outb(0,XD_RESET);		/* reset the controller */}static void __init xd_dtc5150cx_init_drive (u_char drive){	/* values from controller's BIOS - BIOS chip may be removed */	static u_short geometry_table[][4] = {		{0x200,8,0x200,0x100},		{0x267,2,0x267,0x267},		{0x264,4,0x264,0x80},		{0x132,4,0x132,0x0},		{0x132,2,0x80, 0x132},		{0x177,8,0x177,0x0},		{0x132,8,0x84, 0x0},		{},  /* not used */		{0x132,6,0x80, 0x100},		{0x200,6,0x100,0x100},		{0x264,2,0x264,0x80},		{0x280,4,0x280,0x100},		{0x2B9,3,0x2B9,0x2B9},		{0x2B9,5,0x2B9,0x2B9},		{0x280,6,0x280,0x100},		{0x132,4,0x132,0x0}};	u_char n;	n = inb(XD_JUMPER);	n = (drive ? n : (n >> 2)) & 0x33;	n = (n | (n >> 2)) & 0x0F;	if (xd_geo[3*drive])		xd_manual_geo_set(drive);	else		if (n != 7) {				xd_info[drive].heads = (u_char)(geometry_table[n][1]);			/* heads */			xd_info[drive].cylinders = geometry_table[n][0];	/* cylinders */			xd_info[drive].sectors = 17;				/* sectors */#if 0			xd_info[drive].rwrite = geometry_table[n][2];	/* reduced write */			xd_info[drive].precomp = geometry_table[n][3]		/* write precomp */			xd_info[drive].ecc = 0x0B;				/* ecc length */#endif /* 0 */		}		else {			printk("xd%c: undetermined drive geometry\n",'a'+drive);			return;		}	xd_info[drive].control = 5;				/* control byte */	xd_setparam(CMD_DTCSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,geometry_table[n][2],geometry_table[n][3],0x0B);	xd_recalibrate(drive);}static void __init 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 (xd_geo[3*drive])			xd_manual_geo_set(drive);#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 xd%c\n", 'a'+drive);	}	else		printk("xd_dtc_init_drive: error reading geometry for xd%c\n", 'a'+drive);}static void __init xd_wd_init_controller (unsigned int address){	switch (address) {		case 0x00000:		case 0xC8000:	break;			/*initial: 0x320 */		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 %06x\n",address);				break;	}

⌨️ 快捷键说明

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