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

📄 pdc4030.c

📁 at91rm9200处理器ide接口驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
void __init ide_probe_for_pdc4030(void){	unsigned int	index;	ide_hwif_t	*hwif;	if (enable_promise_support == 0)		return;	for (index = 0; index < MAX_HWIFS; index++) {		hwif = &ide_hwifs[index];		if (hwif->chipset == ide_unknown && detect_pdc4030(hwif)) {			setup_pdc4030(hwif);		}	}}/* * promise_read_intr() is the handler for disk read/multread interrupts */static ide_startstop_t promise_read_intr (ide_drive_t *drive){	byte stat;	int total_remaining;	unsigned int sectors_left, sectors_avail, nsect;	struct request *rq;	if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {		return ide_error(drive, "promise_read_intr", stat);	}read_again:	do {		sectors_left = IN_BYTE(IDE_NSECTOR_REG);		IN_BYTE(IDE_SECTOR_REG);	} while (IN_BYTE(IDE_NSECTOR_REG) != sectors_left);	rq = HWGROUP(drive)->rq;	sectors_avail = rq->nr_sectors - sectors_left;	if (!sectors_avail)		goto read_again;read_next:	rq = HWGROUP(drive)->rq;	nsect = rq->current_nr_sectors;	if (nsect > sectors_avail)		nsect = sectors_avail;	sectors_avail -= nsect;	ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);#ifdef DEBUG_READ	printk(KERN_DEBUG "%s:  promise_read: sectors(%ld-%ld), "	       "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector,	       rq->sector+nsect-1, (unsigned long) rq->buffer,	       rq->nr_sectors-nsect);#endif	rq->sector += nsect;	rq->buffer += nsect<<9;	rq->errors = 0;	rq->nr_sectors -= nsect;	total_remaining = rq->nr_sectors;	if ((rq->current_nr_sectors -= nsect) <= 0) {		ide_end_request(1, HWGROUP(drive));	}/* * Now the data has been read in, do the following: *  * if there are still sectors left in the request,  *   if we know there are still sectors available from the interface, *     go back and read the next bit of the request. *   else if DRQ is asserted, there are more sectors available, so *     go back and find out how many, then read them in. *   else if BUSY is asserted, we are going to get an interrupt, so *     set the handler for the interrupt and just return */	if (total_remaining > 0) {		if (sectors_avail)			goto read_next;		stat = GET_STAT();		if (stat & DRQ_STAT)			goto read_again;		if (stat & BUSY_STAT) {			ide_set_handler (drive, &promise_read_intr, WAIT_CMD, NULL);#ifdef DEBUG_READ			printk(KERN_DEBUG "%s: promise_read: waiting for"			       "interrupt\n", drive->name);#endif			return ide_started;		}		printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left "		       "!DRQ !BUSY\n", drive->name);		return ide_error(drive, "promise read intr", stat);	}	return ide_stopped;}/* * promise_complete_pollfunc() * This is the polling function for waiting (nicely!) until drive stops * being busy. It is invoked at the end of a write, after the previous poll * has finished. * * Once not busy, the end request is called. */static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive){	ide_hwgroup_t *hwgroup = HWGROUP(drive);	struct request *rq = hwgroup->rq;	int i;	if (GET_STAT() & BUSY_STAT) {		if (time_before(jiffies, hwgroup->poll_timeout)) {			ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);			return ide_started; /* continue polling... */		}		hwgroup->poll_timeout = 0;		printk(KERN_ERR "%s: completion timeout - still busy!\n",		       drive->name);		return ide_error(drive, "busy timeout", GET_STAT());	}	hwgroup->poll_timeout = 0;#ifdef DEBUG_WRITE	printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);#endif	for (i = rq->nr_sectors; i > 0; ) {		i -= rq->current_nr_sectors;		ide_end_request(1, hwgroup);	}	return ide_stopped;}/* * promise_write_pollfunc() is the handler for disk write completion polling. */static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive){	ide_hwgroup_t *hwgroup = HWGROUP(drive);	if (IN_BYTE(IDE_NSECTOR_REG) != 0) {		if (time_before(jiffies, hwgroup->poll_timeout)) {			ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);			return ide_started; /* continue polling... */		}		hwgroup->poll_timeout = 0;		printk(KERN_ERR "%s: write timed-out!\n",drive->name);		return ide_error (drive, "write timeout", GET_STAT());	}	/*	 * Now write out last 4 sectors and poll for not BUSY	 */	ide_multwrite(drive, 4);	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;	ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);#ifdef DEBUG_WRITE	printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",		drive->name, GET_STAT());#endif	return ide_started;}/* * promise_write() transfers a block of one or more sectors of data to a * drive as part of a disk write operation. All but 4 sectors are transferred * in the first attempt, then the interface is polled (nicely!) for completion * before the final 4 sectors are transferred. There is no interrupt generated * on writes (at least on the DC4030VL-2), we just have to poll for NOT BUSY. */static ide_startstop_t promise_write (ide_drive_t *drive){	ide_hwgroup_t *hwgroup = HWGROUP(drive);	struct request *rq = &hwgroup->wrq;#ifdef DEBUG_WRITE	printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), "	       "buffer=%p\n", drive->name, rq->sector,	       rq->sector + rq->nr_sectors - 1, rq->buffer);#endif	/*	 * If there are more than 4 sectors to transfer, do n-4 then go into	 * the polling strategy as defined above.	 */	if (rq->nr_sectors > 4) {		if (ide_multwrite(drive, rq->nr_sectors - 4))			return ide_stopped;		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;		ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);		return ide_started;	} else {	/*	 * There are 4 or fewer sectors to transfer, do them all in one go	 * and wait for NOT BUSY.	 */		if (ide_multwrite(drive, rq->nr_sectors))			return ide_stopped;		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;		ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);#ifdef DEBUG_WRITE		printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "			"status = %02x\n", drive->name, GET_STAT());#endif		return ide_started;	}}/* * do_pdc4030_io() is called from do_rw_disk, having had the block number * already set up. It issues a READ or WRITE command to the Promise * controller, assuming LBA has been used to set up the block number. */ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq){	ide_startstop_t startstop;	unsigned long timeout;	byte stat;	switch(rq->cmd) {		case READ:#ifndef __TASKFILE__IO			OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);#endif/* * The card's behaviour is odd at this point. If the data is * available, DRQ will be true, and no interrupt will be * generated by the card. If this is the case, we need to call the  * "interrupt" handler (promise_read_intr) directly. Otherwise, if * an interrupt is going to occur, bit0 of the SELECT register will * be high, so we can set the handler the just return and be interrupted. * If neither of these is the case, we wait for up to 50ms (badly I'm * afraid!) until one of them is. */			timeout = jiffies + HZ/20; /* 50ms wait */			do {				stat=GET_STAT();				if (stat & DRQ_STAT) {					udelay(1);					return promise_read_intr(drive);				}				if (IN_BYTE(IDE_SELECT_REG) & 0x01) {#ifdef DEBUG_READ	printk(KERN_DEBUG "%s: read: waiting for interrupt\n", drive->name);#endif					ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL);					return ide_started;				}				udelay(1);			} while (time_before(jiffies, timeout));			printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n", drive->name);			return ide_stopped;		case WRITE:#ifndef __TASKFILE__IO			OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);#endif			if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {				printk(KERN_ERR "%s: no DRQ after issuing PROMISE_WRITE\n", drive->name);				return startstop;		    	}			if (!drive->unmask)				__cli();	/* local CPU only */			HWGROUP(drive)->wrq = *rq; /* scratchpad */			return promise_write(drive);		default:			printk("KERN_WARNING %s: bad command: %d\n", drive->name, rq->cmd);			ide_end_request(0, HWGROUP(drive));			return ide_stopped;	}}#ifdef __TASKFILE__IOide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block){	struct hd_drive_task_hdr taskfile;	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));	taskfile.sector_count	= rq->nr_sectors;	taskfile.sector_number	= block;	taskfile.low_cylinder	= (block>>=8);	taskfile.high_cylinder	= (block>>=8);	taskfile.device_head	= ((block>>8)&0x0f)|drive->select.all;	taskfile.command	= (rq->cmd==READ)?PROMISE_READ:PROMISE_WRITE;	do_taskfile(drive, &taskfile, NULL, NULL);	return do_pdc4030_io(drive, rq);}#endif

⌨️ 快捷键说明

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