📄 pdc4030.c
字号:
IN_BYTE(IDE_NSECTOR_REG) == 'T' && IN_BYTE(IDE_SECTOR_REG) == 'I') { return 1; } else { return 0; }}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){ unsigned long timeout; byte stat; if (rq->cmd == READ) { OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);/* * 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; } else if (rq->cmd == WRITE) { ide_startstop_t startstop; OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG); 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); } else { printk("KERN_WARNING %s: bad command: %d\n", drive->name, rq->cmd); ide_end_request(0, HWGROUP(drive)); return ide_stopped; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -