Esempio n. 1
0
static void read_intr(void)
{
	struct request *req;
	int i, retries = 100000;

	do {
		i = (unsigned) inb_p(HD_STATUS);
		if (i & BUSY_STAT)
			continue;
		if (!OK_STATUS(i))
			break;
		if (i & DRQ_STAT)
			goto ok_to_read;
	} while (--retries > 0);
	dump_status("read_intr", i);
	bad_rw_intr();
	hd_request();
	return;

ok_to_read:
	req = hd_req;
	insw(HD_DATA, req->buffer, 256);
#ifdef DEBUG
	printk("%s: read: sector %ld, remaining = %u, buffer=%p\n",
	       req->rq_disk->disk_name, blk_rq_pos(req) + 1,
	       blk_rq_sectors(req) - 1, req->buffer+512);
#endif
	if (hd_end_request(0, 512)) {
		SET_HANDLER(&read_intr);
		return;
	}

	(void) inb_p(HD_STATUS);
#if (HD_DELAY > 0)
	last_req = read_timer();
#endif
	hd_request();
}
Esempio n. 2
0
static void write_intr(void)
{
	struct request *req = CURRENT;
	int i;
	int retries = 100000;

	do {
		i = (unsigned) inb_p(HD_STATUS);
		if (i & BUSY_STAT)
			continue;
		if (!OK_STATUS(i))
			break;
		if ((req->nr_sectors <= 1) || (i & DRQ_STAT))
			goto ok_to_write;
	} while (--retries > 0);
	dump_status("write_intr", i);
	bad_rw_intr();
	hd_request();
	return;
ok_to_write:
	req->sector++;
	i = --req->nr_sectors;
	--req->current_nr_sectors;
	req->buffer += 512;
	if (!i || (req->bio && req->current_nr_sectors <= 0))
		end_request(req, 1);
	if (i > 0) {
		SET_HANDLER(&write_intr);
		outsw(HD_DATA,req->buffer,256);
		local_irq_enable();
	} else {
#if (HD_DELAY > 0)
		last_req = read_timer();
#endif
		hd_request();
	}
	return;
}
Esempio n. 3
0
static void reset_hd(void)
{
	static int i;

repeat:
	if (reset) {
		reset = 0;
		i = -1;
		reset_controller();
	} else if (win_result()) {
		bad_rw_intr();
		if (reset)
			goto repeat;
	}
	i++;
	if (i < NR_HD) {
		hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
			hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
		if (reset)
			goto repeat;
	} else
		do_hd_request();
}
Esempio n. 4
0
File: hd.c Progetto: trbhoang/Vinix
static void read_intr(void)
{
    if (win_result()) {
	bad_rw_intr();
	return;
    }
    if (this_request->nsector == 2) {
	this_request->nsector--;
	port_read(HD_DATA, this_request->bh->b_data, 256);
    }
    else {
	port_read(HD_DATA, this_request->bh->b_data + 512, 256);
	return;
    }
    this_request->errors = 0;
    this_request->bh->b_uptodate = 1;
    this_request->bh->b_dirt = 0;
    wake_up(&wait_for_request);
    unlock_buffer(this_request->bh);
    this_request->hd = -1;
    this_request = this_request->next;
    do_request();
}
Esempio n. 5
0
static void read_intr(void)
{
    /* check previous read command success or not */
    if (win_result()) {
        bad_rw_intr();
        do_hd_request();
        return;
    }

    /* read data from hard disk from data register */
    port_read(HD_DATA, CURRENT_REQ->buffer, 256);

    CURRENT_REQ->errors = 0;
    CURRENT_REQ->buffer += 512;
    CURRENT_REQ->start_sector++;

    if (--CURRENT_REQ->nr_sectors) {
        do_hd = &read_intr;
        return;
    }

    end_request(1);
    do_hd_request();
}
Esempio n. 6
0
/*
 * The driver enables interrupts as much as possible.  In order to do this,
 * (a) the device-interrupt is disabled before entering hd_request(),
 * and (b) the timeout-interrupt is disabled before the sti().
 *
 * Interrupts are still masked (by default) whenever we are exchanging
 * data/cmds with a drive, because some drives seem to have very poor
 * tolerance for latency during I/O. The IDE driver has support to unmask
 * interrupts for non-broken hardware, so use that driver if required.
 */
static void hd_request(void)
{
	unsigned int block, nsect, sec, track, head, cyl;
	struct hd_i_struct *disk;
	struct request *req;

	if (do_hd)
		return;
repeat:
	del_timer(&device_timer);
	local_irq_enable();

	req = CURRENT;
	if (!req) {
		do_hd = NULL;
		return;
	}

	if (reset) {
		local_irq_disable();
		reset_hd();
		return;
	}
	disk = req->rq_disk->private_data;
	block = req->sector;
	nsect = req->nr_sectors;
	if (block >= get_capacity(req->rq_disk) ||
	    ((block+nsect) > get_capacity(req->rq_disk))) {
		printk("%s: bad access: block=%d, count=%d\n",
			req->rq_disk->disk_name, block, nsect);
		end_request(req, 0);
		goto repeat;
	}

	if (disk->special_op) {
		if (do_special_op(disk, req))
			goto repeat;
		return;
	}
	sec   = block % disk->sect + 1;
	track = block / disk->sect;
	head  = track % disk->head;
	cyl   = track / disk->head;
#ifdef DEBUG
	printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
		req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ",
		cyl, head, sec, nsect, req->buffer);
#endif
	if (blk_fs_request(req)) {
		switch (rq_data_dir(req)) {
		case READ:
			hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr);
			if (reset)
				goto repeat;
			break;
		case WRITE:
			hd_out(disk,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
			if (reset)
				goto repeat;
			if (wait_DRQ()) {
				bad_rw_intr();
				goto repeat;
			}
			outsw(HD_DATA,req->buffer,256);
			break;
		default:
			printk("unknown hd-command\n");
			end_request(req, 0);
			break;
		}
	}
}
Esempio n. 7
0
void do_hd_request(void)
{
    int i, r = 0;
    unsigned int start_sector, dev, partition;
    unsigned int start_sec, head, cyl;
    unsigned int nsect;

    CHECK_REQUEST;
    partition = MINOR(CURRENT_REQ->dev);  /* get partition */
    start_sector = CURRENT_REQ->start_sector;
    nsect = CURRENT_REQ->nr_sectors;

    /* need to check if nsect is exceed the partition limit or not */
    if (partition >= 5 * NR_HD || nsect > hd[partition].nr_sects) {
        end_request(0);
        goto repeat;	/* repeat defined in blk.h */
    }

    start_sector += hd[partition].start_sect;
    dev = partition / 5;

    /* get cyl, head, start_sec number according start_sector */
    /* div result: EAX = Quotient, EDX = Remainder */
    /*
     * start_sector / sect nrs per track = total track number(start_sector)
     * ... remainder sector number(start_sec)
     */
    __asm__("divl %4"
            :"=a" (start_sector), "=d" (start_sec)
            :"0" (start_sector), "1" (0), "r" (hd_info[dev].sect));

    /* totoal track number / total head nrs = cylinder number(cyl)
     * ... head nr(head) */
    __asm__("divl %4"
            :"=a" (cyl), "=d" (head)
            :"0" (start_sector), "1" (0), "r" (hd_info[dev].head));

    start_sec++;

    if (reset) {
        reset = 0;
        recalibrate = 1;
        reset_hd(CURRENT_DEV);
        return;
    }

    if (recalibrate) {
        recalibrate = 0;
        hd_out(dev, hd_info[CURRENT_DEV].sect, 0, 0, 0, WIN_RESTORE,
               recal_intr);
        return;
    }

    if (CURRENT_REQ->cmd == WRITE) {
        hd_out(dev, nsect, start_sec, head, cyl, WIN_WRITE, write_intr);

        /* wait DRQ_STAT signal */
        for(i = 0; i < 3000 && !(r = inb_p(HD_STATUS) & DRQ_STAT); i++)
            /* nothing */ ;

        if (!r) {
            bad_rw_intr();
            goto repeat;
        }

        /* write 512 byte (1 sector) to HD */
        port_write(HD_DATA, CURRENT_REQ->buffer, 256);
    } else if (CURRENT_REQ->cmd == READ) {
        hd_out(dev, nsect, start_sec, head, cyl, WIN_READ, read_intr);
    } else {
        panic("unknown hd-command");
    }
}
Esempio n. 8
0
static void recal_intr(void)
{
    if (win_result())
        bad_rw_intr();
    do_hd_request();
}
Esempio n. 9
0
File: hd.c Progetto: zhaokaihit/soft
void do_hd_request(void)
{
	int i,r = 0;
	unsigned int block,dev;
	unsigned int sec,head,cyl;
	unsigned int nsect;

	INIT_REQUEST;
	dev = MINOR(CURRENT->dev);
	//printk("In hd.c do_hd_request() dev (1st) is %d\n",dev );
	block = CURRENT->sector;
	
	if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) {
		end_request(0);
		goto repeat;
	}
	block += hd[dev].start_sect;
	dev /= 5;
	//printk("IN hd.c do_hd_quest() dev (2st) is %d\n",dev);
	__asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0),
		"r" (hd_info[dev].sect));
	__asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0),
		"r" (hd_info[dev].head));
	sec++;
	nsect = CURRENT->nr_sectors;
	if (reset) {
		reset = 0;
		recalibrate = 1;
		reset_hd(CURRENT_DEV);
		return;
	}
	if (recalibrate) {
		recalibrate = 0;
		hd_out(dev,hd_info[CURRENT_DEV].sect,0,0,0,
			WIN_RESTORE,&recal_intr);
		return;
	}	
	if (CURRENT->cmd == WRITE) {
		//printk("In hd.c do_hd_request() dev (1st) is %d\n",dev );
		//hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
		
		if(work == 1)
		{	
			devi = 0;	
			hd_out(devi,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
			
		}else if(work == 2)
		{
			devi = 1;
			hd_out(devi,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
		}else if (work == 3)
		{
			hd_out(devi,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
		}
		
		//printk("devi is %d" ,devi);
		for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
			/* nothing */ ;
		//hd_out(1,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
		//for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
			/* nothing */ ;
		if (!r) {
			bad_rw_intr();
			goto repeat;
		}
		port_write(HD_DATA,CURRENT->buffer,256);
	}
	 else if (CURRENT->cmd == READ) 
	{
		if(work == 1)
		{
			dev = 0 ;
		}
		else if (work == 2)
		{
			dev = 1;
		}
		hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
	} else
		panic("unknown hd-command");
}
Esempio n. 10
0
File: hd.c Progetto: 08opt/linux
/*
 * The driver enables interrupts as much as possible.  In order to do this,
 * (a) the device-interrupt is disabled before entering hd_request(),
 * and (b) the timeout-interrupt is disabled before the sti().
 *
 * Interrupts are still masked (by default) whenever we are exchanging
 * data/cmds with a drive, because some drives seem to have very poor
 * tolerance for latency during I/O. The IDE driver has support to unmask
 * interrupts for non-broken hardware, so use that driver if required.
 */
static void hd_request(void)
{
	unsigned int block, nsect, sec, track, head, cyl;
	struct hd_i_struct *disk;
	struct request *req;

	if (do_hd)
		return;
repeat:
	del_timer(&device_timer);

	if (!hd_req) {
		hd_req = blk_fetch_request(hd_queue);
		if (!hd_req) {
			do_hd = NULL;
			return;
		}
	}
	req = hd_req;

	if (reset) {
		reset_hd();
		return;
	}
	disk = req->rq_disk->private_data;
	block = blk_rq_pos(req);
	nsect = blk_rq_sectors(req);
	if (block >= get_capacity(req->rq_disk) ||
	    ((block+nsect) > get_capacity(req->rq_disk))) {
		printk("%s: bad access: block=%d, count=%d\n",
			req->rq_disk->disk_name, block, nsect);
		hd_end_request_cur(-EIO);
		goto repeat;
	}

	if (disk->special_op) {
		if (do_special_op(disk, req))
			goto repeat;
		return;
	}
	sec   = block % disk->sect + 1;
	track = block / disk->sect;
	head  = track % disk->head;
	cyl   = track / disk->head;
#ifdef DEBUG
	printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
		req->rq_disk->disk_name,
		req_data_dir(req) == READ ? "read" : "writ",
		cyl, head, sec, nsect, req->buffer);
#endif
	if (req->cmd_type == REQ_TYPE_FS) {
		switch (rq_data_dir(req)) {
		case READ:
			hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_READ,
				&read_intr);
			if (reset)
				goto repeat;
			break;
		case WRITE:
			hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_WRITE,
				&write_intr);
			if (reset)
				goto repeat;
			if (wait_DRQ()) {
				bad_rw_intr();
				goto repeat;
			}
			outsw(HD_DATA, req->buffer, 256);
			break;
		default:
			printk("unknown hd-command\n");
			hd_end_request_cur(-EIO);
			break;
		}
	}
}