📄 at_wini.c
字号:
10698 }
10699 }
10700
10701 /* For each sector, wait for an interrupt and fetch the data (read),
10702 * or supply data to the controller and wait for an interrupt (write).
10703 */
10704
10705 if (w_opcode == DEV_READ) {
10706 if ((r = w_intr_wait()) == OK) {
10707 /* Copy data from the device's buffer to user space. */
10708
10709 port_read(wn->base + REG_DATA, tp->phys, SECTOR_SIZE);
10710
10711 tp->phys += SECTOR_SIZE;
10712 tp->iop->io_nbytes -= SECTOR_SIZE;
10713 w_count -= SECTOR_SIZE;
10714 if ((tp->count -= SECTOR_SIZE) == 0) tp++;
10715 } else {
10716 /* Any faulty data? */
10717 if (w_status & STATUS_DRQ) {
10718 port_read(wn->base + REG_DATA, tmp_phys,
10719 SECTOR_SIZE);
10720 }
10721 }
10722 } else {
10723 /* Wait for data requested. */
10724 if (!waitfor(STATUS_DRQ, STATUS_DRQ)) {
10725 r = ERR;
10726 } else {
10727 /* Fill the buffer of the drive. */
10728
10729 port_write(wn->base + REG_DATA, tp->phys, SECTOR_SIZE);
10730 r = w_intr_wait();
10731 }
10732
10733 if (r == OK) {
10734 /* Book the bytes successfully written. */
10735
10736 tp->phys += SECTOR_SIZE;
10737 tp->iop->io_nbytes -= SECTOR_SIZE;
10738 w_count -= SECTOR_SIZE;
10739 if ((tp->count -= SECTOR_SIZE) == 0) tp++;
10740 }
10741 }
10742
10743 if (r != OK) {
10744 /* Don't retry if sector marked bad or too many errors */
10745 if (r == ERR_BAD_SECTOR || ++errors == MAX_ERRORS) {
10746 w_command = CMD_IDLE;
10747 return(tp->iop->io_nbytes = EIO);
10748 }
10749
10750 /* Reset if halfway, but bail out if optional I/O. */
10751 if (errors == MAX_ERRORS / 2) {
10752 w_need_reset();
10753 if (tp->iop->io_request & OPTIONAL_IO) {
10754 w_command = CMD_IDLE;
10755 return(tp->iop->io_nbytes = EIO);
10756 }
10757 }
10758 continue; /* Retry */
10759 }
10760 errors = 0;
10761 } while (w_count > 0);
10762
10763 w_command = CMD_IDLE;
10764 return(OK);
10765 }
10768 /*============================================================================*
10769 * com_out *
10770 *============================================================================*/
10771 PRIVATE int com_out(cmd)
10772 struct command *cmd; /* Command block */
10773 {
10774 /* Output the command block to the winchester controller and return status */
10775
10776 struct wini *wn = w_wn;
10777 unsigned base = wn->base;
10778
10779 if (!waitfor(STATUS_BSY, 0)) {
10780 printf("%s: controller not ready\n", w_name());
10781 return(ERR);
10782 }
10783
10784 /* Select drive. */
10785 out_byte(base + REG_LDH, cmd->ldh);
10786
10787 if (!waitfor(STATUS_BSY, 0)) {
10788 printf("%s: drive not ready\n", w_name());
10789 return(ERR);
10790 }
10791
10792 /* Schedule a wakeup call, some controllers are flaky. */
10793 clock_mess(WAKEUP, w_timeout);
10794
10795 out_byte(base + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0);
10796 out_byte(base + REG_PRECOMP, cmd->precomp);
10797 out_byte(base + REG_COUNT, cmd->count);
10798 out_byte(base + REG_SECTOR, cmd->sector);
10799 out_byte(base + REG_CYL_LO, cmd->cyl_lo);
10800 out_byte(base + REG_CYL_HI, cmd->cyl_hi);
10801 lock();
10802 out_byte(base + REG_COMMAND, cmd->command);
10803 w_command = cmd->command;
10804 w_status = STATUS_BSY;
10805 unlock();
10806 return(OK);
10807 }
10810 /*===========================================================================*
10811 * w_need_reset *
10812 *===========================================================================*/
10813 PRIVATE void w_need_reset()
10814 {
10815 /* The controller needs to be reset. */
10816 struct wini *wn;
10817
10818 for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
10819 wn->state |= DEAF;
10820 wn->state &= ~INITIALIZED;
10821 }
10822 }
10825 /*============================================================================*
10826 * w_do_close *
10827 *============================================================================*/
10828 PRIVATE int w_do_close(dp, m_ptr)
10829 struct driver *dp;
10830 message *m_ptr;
10831 {
10832 /* Device close: Release a device. */
10833
10834 if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
10835 w_wn->open_ct--;
10836 return(OK);
10837 }
10840 /*============================================================================*
10841 * com_simple *
10842 *============================================================================*/
10843 PRIVATE int com_simple(cmd)
10844 struct command *cmd; /* Command block */
10845 {
10846 /* A simple controller command, only one interrupt and no data-out phase. */
10847 int r;
10848
10849 if ((r = com_out(cmd)) == OK) r = w_intr_wait();
10850 w_command = CMD_IDLE;
10851 return(r);
10852 }
10855 /*===========================================================================*
10856 * w_timeout *
10857 *===========================================================================*/
10858 PRIVATE void w_timeout()
10859 {
10860 struct wini *wn = w_wn;
10861
10862 switch (w_command) {
10863 case CMD_IDLE:
10864 break; /* fine */
10865 case CMD_READ:
10866 case CMD_WRITE:
10867 /* Impossible, but not on PC's: The controller does not respond. */
10868
10869 /* Limiting multisector I/O seems to help. */
10870 if (wn->max_count > 8 * SECTOR_SIZE) {
10871 wn->max_count = 8 * SECTOR_SIZE;
10872 } else {
10873 wn->max_count = SECTOR_SIZE;
10874 }
10875 /*FALL THROUGH*/
10876 default:
10877 /* Some other command. */
10878 printf("%s: timeout on command %02x\n", w_name(), w_command);
10879 w_need_reset();
10880 w_status = 0;
10881 interrupt(WINCHESTER);
10882 }
10883 }
10886 /*===========================================================================*
10887 * w_reset *
10888 *===========================================================================*/
10889 PRIVATE int w_reset()
10890 {
10891 /* Issue a reset to the controller. This is done after any catastrophe,
10892 * like the controller refusing to respond.
10893 */
10894
10895 struct wini *wn;
10896 int err;
10897
10898 /* Wait for any internal drive recovery. */
10899 milli_delay(RECOVERYTIME);
10900
10901 /* Strobe reset bit */
10902 out_byte(w_wn->base + REG_CTL, CTL_RESET);
10903 milli_delay(1);
10904 out_byte(w_wn->base + REG_CTL, 0);
10905 milli_delay(1);
10906
10907 /* Wait for controller ready */
10908 if (!w_waitfor(STATUS_BSY | STATUS_RDY, STATUS_RDY)) {
10909 printf("%s: reset failed, drive busy\n", w_name());
10910 return(ERR);
10911 }
10912
10913 /* The error register should be checked now, but some drives mess it up. */
10914
10915 for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
10916 if (wn->base == w_wn->base) wn->state &= ~DEAF;
10917 }
10918 return(OK);
10919 }
10922 /*============================================================================*
10923 * w_intr_wait *
10924 *============================================================================*/
10925 PRIVATE int w_intr_wait()
10926 {
10927 /* Wait for a task completion interrupt and return results. */
10928
10929 message mess;
10930 int r;
10931
10932 /* Wait for an interrupt that sets w_status to "not busy". */
10933 while (w_status & STATUS_BSY) receive(HARDWARE, &mess);
10934
10935 /* Check status. */
10936 lock();
10937 if ((w_status & (STATUS_BSY | STATUS_RDY | STATUS_WF | STATUS_ERR))
10938 == STATUS_RDY) {
10939 r = OK;
10940 w_status |= STATUS_BSY; /* assume still busy with I/O */
10941 } else
10942 if ((w_status & STATUS_ERR) && (in_byte(w_wn->base + REG_ERROR) & ERROR_BB)) {
10943 r = ERR_BAD_SECTOR; /* sector marked bad, retries won't help */
10944 } else {
10945 r = ERR; /* any other error */
10946 }
10947 unlock();
10948 return(r);
10949 }
10952 /*==========================================================================*
10953 * w_waitfor *
10954 *==========================================================================*/
10955 PRIVATE int w_waitfor(mask, value)
10956 int mask; /* status mask */
10957 int value; /* required status */
10958 {
10959 /* Wait until controller is in the required state. Return zero on timeout. */
10960
10961 struct milli_state ms;
10962
10963 milli_start(&ms);
10964 do {
10965 if ((in_byte(w_wn->base + REG_STATUS) & mask) == value) return 1;
10966 } while (milli_elapsed(&ms) < TIMEOUT);
10967
10968 w_need_reset(); /* Controller gone deaf. */
10969 return(0);
10970 }
10973 /*==========================================================================*
10974 * w_handler *
10975 *==========================================================================*/
10976 PRIVATE int w_handler(irq)
10977 int irq;
10978 {
10979 /* Disk interrupt, send message to winchester task and reenable interrupts. */
10980
10981 w_status = in_byte(w_wn->base + REG_STATUS); /* acknowledge interrupt */
10982 interrupt(WINCHESTER);
10983 return 1;
10984 }
10987 /*============================================================================*
10988 * w_geometry *
10989 *============================================================================*/
10990 PRIVATE void w_geometry(entry)
10991 struct partition *entry;
10992 {
10993 entry->cylinders = w_wn->lcylinders;
10994 entry->heads = w_wn->lheads;
10995 entry->sectors = w_wn->lsectors;
10996 }
10997 #endif /* ENABLE_AT_WINI */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -