📄 sdc.c
字号:
#ifndef lintstatic char *sccsid = "@(#)sdc.c 4.1 ULTRIX 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1986,87,88 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//*********************************************************************** * * Modification History: * Apr-1-91 Matthew Sacks * Changed rx23_type() so that it does a ready check and drive * restore before doing the I/O operation which distinguishes high * density (2880) from double density (1440) floppy disks. * Otherwise, this density test causes Sync errors when * floppy cartridges are interchanged. * * 30-Dec-88 Fred Canter * Added sdreset() to reset ST506 controllers before calling the * VMB boot drive to write out a crash dump. * * 28-Sep-88 Fred Canter * Clean up comments. Use CFGTST regiser bit to determine floopy * drive type, i.e., RX33 or RX23. * * 08-Aug-88 Fred Canter * Make probe fail if not drives present (PVAX only). * The installation will generate a bad config file if the * sdc controller is present with no drives (undefined sdintr). * * 14-Jul-88 George Mathew * Added support for RX23 floppy drive * * 19-May-88 Fred Canter * Changes for operating in either compatibility or * extended I/O mode on CVAXstar/PVAX. * * 15-Feb-88 Fred Canter * Changes for VAX420 (CVAXstar/PVAX) support. * Added RD33 support. * Changed sd_delay from one instruction to a macro. * * 01-Jun-87 George Mathew * Fix the problem with spurious deleted data mark. Check for Write Fault * before Deleted Data Mark! * * 28-Apr-87 George Mathew * DEVIOCGET ioctl reports correctly if the diskette is write preotected * * 23-Apr-97 darrell * Changed the calls to vs_bufctl to pass a pointer to a structure * that contains a pointer to the routine that vs_bufctl is to * call in this driver. * * 12-Mar-87 George Mathew * Fix for the protection fault: if going through bbr code (using * rdwr_poll for read/write) and the no. of bytes to be transferred * from the last sector in the track containing the bad sector is not * 512, transfer the correct no. of bytes. * * 11-Feb-87 gmm (George Mathew) * Removed all the debug stuff related to deleted data mark (undid * most of 01/15/87 work). Included a couple of more delays hoping to * get rid of the spurious deleted data marks. * * 28-Jan-87 gmm (George Mathew) * Restore to track 0 whenever starting on a new diskette (Causes * sync error otherwise). Put the last drive serviced at the end of the * queue for the next round. Made some changes to take care of lint * warning messages * * 15-Jan-87 gmm (George Mathew) * Does not report I/O error if deleted data mark not written by the * driver (through BBR) is reported by the controller. But error * messages are printed. (To be removed before SDC) * * 06-Jan-87 gmm (George Mathew) * Updated BBR code to the latest algorithm (ECO #20). BBR messages * made the same as of uda. Added ioctl support for radisk. Removed * sdreset(). Changes to diskette drive. * * 3-Dec-86 gmm (George Mathew) * Performance enhancements. Changed the way deleted data mark is * reported. First version after field test. * * 8-Oct-86 gmm (George Mathew) * Fix a bug in bbr: if the sector is not bad, but the data * is invalid (Forced error bit set) the block no. is correctly * calculated in sd_rpl() . * * 6-Oct-86 gmm (George Mathew) * Check validity of unit number before status field updated in the * open routine (sdopen()). * * 20-Sep-86 gmm (George Mathew) * BBR bug fix: RCT gets updated correctly even if not the first one. * Some changes for RX50 read/write to be more robust. * DEVIOCGET ioctl updates stat field correctly. * * 9-Sep-86 gmm (George Mathew) * Changed the way presence of RX33 drive is detected in sdslave. * Improved some of the error messages * * 4-Sep-86 gmm (George Mathew) * Improvements, bug fixes, and cleanup. * * 27-Aug-86 gmm (George Mathew) * Many changes: RX50 improved performance, BBR improvements, and * general cleanup. * * 26-Aug-86 -- rsp (Ricky Palmer) * Cleaned up devioctl code to (1) zero out devget structure * upon entry and (2) use strlen instead of fixed storage * for bcopy's. * * 14-Aug-86 gmm (George Mathew) * Several driver improvements and clean out debug messages. * Change slave names from sd to rd/rx. * * 5-Aug-86 gmm (George Mathew) * Extensive rewrite for real VAXstar disk driver. * * 2-Jul-86 gmm (George Mathew) * Added partial devioctl support and many improvements to driver. * * 18-Jun-86 gmm (Geroge Mathew) * Created this VAXstar RD/RX disk driver file. * **********************************************************************/#include "rd.h"#include "rx.h"#if NRX > 0#define NSX 1#else#define NSX 0#endif#define NSD NRD+NSX#if defined(BINARY) || NSD > 0int sdpip; /* DEBUG */int sdnosval; /* DEBUG */extern int cvs_exmode_on;#include "../data/sdc_data.c"int sdprobe(), sdslave(), sdattach(), sdintr(), sdustart();u_short sdstd[] = { 0 };struct uba_driver sdcdriver = { sdprobe, sdslave, sdattach, 0, sdstd, "rd", sddinfo, "sdc", sdminfo, 0 };struct sdspace SD_bufmap[];struct vsdev vsdiskdev = { VS_SDC, 0, sdustart };/* !!! IMPORTANT !!!*//* If any new disk type added to this structure (sdst), make sure the type * number defined in sdcreg.h and the position of the new disk in this * sturcture MATCH. */struct sdst { short nsect; /* no. of sectors(blocks) per track */ short ncyl; /* no. of cylinders */ short nheads; /* no. of heads or tracks per cylinder */ short nspc; /* no. of sectors(blocks) per cylinder */ struct size *sizes;} sdst[] = { NRX50SECT,NRXCYL,NRX50HDS,NRX50SECT*NRX50HDS,sd_rx50_sizes, NRX33SECT,NRXCYL,NRX33HDS,NRX33SECT*NRX33HDS,sd_rx33_sizes, NRX23SECTH,NRXCYL,NRX23HDS,NRX23SECTH*NRX23HDS,sd_rx23h_sizes, NRX23SECTD,NRXCYL,NRX23HDS,NRX23SECTD*NRX23HDS,sd_rx23d_sizes, NRDSECT,NRD31CYL,NRD31HDS,NRDSECT*NRD31HDS,sd_rd31_sizes, NRDSECT,NRD32CYL,NRD32HDS,NRDSECT*NRD32HDS,sd_rd32_sizes, NRDSECT,NRD33CYL,NRD33HDS,NRDSECT*NRD33HDS,sd_rd33_sizes, NRDSECT,NRD53CYL,NRD53HDS,NRDSECT*NRD53HDS,sd_rd53_sizes, NRDSECT,NRD54CYL,NRD54HDS,NRDSECT*NRD54HDS,sd_rd54_sizes,};short rx_table[50] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10, 3, 5, 7, 9, 1, 4, 6, 8, 10, 2, 5, 7, 9, 1, 3, 6, 8, 10, 2, 4, 7, 9, 1, 3, 5, 8, 10, 2, 4, 6, 9, 1, 3, 5, 7, 10, 2, 4, 6, 8 };struct buf sdcbuf; /* Pointer to controller queue */char xbnbuf[SD_SIZE],tmpbuf[SD_SIZE],rct0[SD_SIZE],rct1[SD_SIZE],rct2[SD_SIZE],rct3[SD_SIZE];short xbnflag = 0;short rtr_cnt = 0; /* no. of times read/write retried */short dsket_type = -1; /* type of diskette */int ddm_err = 0; /* Deleted Data Mark error */int rx50blk, rx50nsect; /* starting block no. and no. of sectors for each * transfer for RX50 *//* * HDC 9224 chip register access delay macro. * Must insure a minimum of 700 ns between disk * controller register accesses. * CVAXstar vs VAXstar CPU speed complicates this issue. * Best we can to is make sure delay long enough for faster CPU. */int sd_delay = 0;#define sdc_delay() sd_delay = 1; sd_delay = 1; sd_delay = 1;char *HARD_ERR = "HARD ERROR";char *SOFT_ERR = "SOFT ERROR";char *DEV_ID = "sd";int sd_rx23wakeup();int sd_bbrcount = RTRY_CNT; /* change this to adjust the retry count in * sd_retry() while doing read/write for bbr. sd_bbrcount * should be >= 1 !! */int sddebug = 0;int sdbbrdbug = 0;int rx_reselect = 0;int xbn_sum = 0;int xbn_check = 0;int start_sn ; /* physical starting sector no. in the track on which I/O * * is being done */int sd_poll = 0; /* controller in poll mode */int sd_nodelay = 0; /* NODELAY flag for open */int sd_openerr = 0; /* Error in opening the device */int sd_rxcyl = 0; /* the last cylinder no. for Rx drive, used by STEP */u_char rbn_addr1,rbn_addr2; /*********************** * !!! DO NOT use BBR_TST option unless you are absolutely sure of * what you are doing. It should be used only for debugging bad block * replacement code. !!! ************************/#ifdef BBR_TST int bbr_sleep; int bbr_force; /* setting this to non zero forces bbr on the block * even if found good in STEP 7 of put_rbn() */#endif BBR_TSTextern struct nexus nexus[];#define DELAYTEN 1000#define LOOP_DELAY 1000000 /* for the following macros: i=unit, j=partition */#define BAD_LBN(i) sd_st.sd_blkno-sd_st.ucb[i].lbnbase-sd_st.sd_nsect+sd_st.ucb[i].badsect#define BAD_SECT(i,j) sd_st.sd_blkno-sd_st.ucb[i].lbnbase-sd_st.sd_nsect-sd_part[i].pt_part[j].pi_blkoff+sd_st.ucb[i].badsectextern int cpu;extern int cpu_subtype;sdprobe(reg, cntlr) caddr_t reg; int cntlr;{ register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem; register struct nb_regs *sdiaddr = (struct nb_regs *)nexus; int count = 0;#ifdef lint sdintr(0); reg = reg;#endif /* * ONLY on a VAXstar/TEAMmate * Also CVAXstar/PVAX */ if ((cpu != VAXSTAR) && (cpu != C_VAXSTAR)) return(0); /* * Only if ST506 disk controller configured. * PVAX server uses 2nd SCSI in place of ST506 controller. */ if ((vs_cfgtst & VS_SC_TYPE) != VS_ST506_SCSI) return(0); /* * Don't allow controller to configure if no drives present * (PVAX only). The installation will build a config file * with the sdc0 controller, but no slaves on a PVAX with * the ST506/SCSI controller if no ST506 drives are found. * The causes the kernel build fail (undefined sdintr). */ if ((vs_cfgtst & (VS_DRV0PR | VS_DRV1PR | VS_DRV2PR)) == 0x0700) return(0); sdiaddr->nb_int_msk |= SINT_DC; sdaddr->dkc_cmd = SD_RESET; while(count < DELAYTEN) { if(sdaddr->dkc_stat & DKC_DONE ) break; DELAY(10); count++; } if (count == DELAYTEN){ printf("%s%c:%s: SD_RESET failed in sdprobe\n",DEV_ID,'c',HARD_ERR); return(0); } sdaddr->dkc_cmd = (SD_SETREG | UDC_TERM); sdc_delay(); if((sdaddr->dkc_stat & DKC_DONE) == 0) { printf("%s%c:%s: Set Register Pointer command failed in sdprobe\n",DEV_ID,'c',HARD_ERR); return(0); } sdaddr->dkc_reg = (TERM_CRC | TERM_INT | TERM_DEL | TERM_WRPR | TERM_WRFL); sdc_delay(); sdaddr->dkc_cmd = SD_DESEL; /* just to generate an interrupt */ return(8);}sdslave(ui) struct uba_device *ui;{ register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem; u_char cmd; sdaddr->dkc_cmd = (SD_SETREG | UDC_DHEAD); sdc_delay(); sdaddr->dkc_reg = 0; /* Play safe by using head 0 here */ /* RESET TERM_CODES AGAIN?? */ sdc_delay(); sdaddr->dkc_cmd = (SD_SETREG | UDC_TERM); sdc_delay(); sdaddr->dkc_reg = (TERM_CRC | TERM_INT | TERM_DEL | TERM_WRPR | TERM_WRFL); sdc_delay(); sdaddr->dkc_cmd = (SD_SETREG | UDC_RTCNT); switch(ui->ui_slave) { case 0: case 1: sdaddr->dkc_reg = RT_CNT; /* UDC_RTCNT */ sdc_delay(); sdaddr->dkc_reg = (MOD_HD | MOD_CHKECC | MOD_SRTRDN); /* UDC_MODE */ sd_st.sd_drno = ui->ui_slave; sd_st.sd_type[ui->ui_slave] = -1; cmd = (SD_SELECT | DTRT_HDSK | ui->ui_slave); if(sd_select(cmd,0)) { if(sddebug >=2) cprintf("%s%d:%s: Not selected\n",DEV_ID,ui->ui_slave,HARD_ERR); sd_st.sd_type[ui->ui_slave] = -1; return(0); } if(sd_rdfmt(ui->ui_slave)){ printf("%s%d:%s:cannot read XBN\n",DEV_ID,ui->ui_slave,HARD_ERR); sd_st.sd_type[ui->ui_slave] = -1; return(0); } /* media type (sd_st.sd_type[]) updated in sd_rdfmt() */ /* Sanity check on RCT to see if bbr was stopped in the middle */ if(put_rbn(-1)) { /* Sanity check on RCT to see if bbr was stopped in the middel */ printf("%s%d:%s: CANNOT RECOVER FROM PREVIOUS BBR\n",DEV_ID,ui->ui_slave,HARD_ERR); } sd_st.sd_cyl.sd_word = -1; sd_st.sd_drno = -1; ui->ui_type = sd_st.sd_type[ui->ui_slave]; return(1); /* break; */ case 2: sd_st.sd_drno = ui->ui_slave; sdaddr->dkc_reg = (RT_CNT | RT_INVRDY |RT_MOTOR); /* UDC_RTCNT */ sdc_delay(); sdaddr->dkc_reg = (MOD_HD | MOD_CHKCRC | MOD_SRTRXH); /* UDC_MODE */ rx_reselect = 1; cmd = (SD_SELECT | DTRT_RX50 | DRV_NUM2); if(sd_select(cmd,1)) { /* Select again to set READY in UDC_DSTAT */ sdaddr->dkc_cmd = (SD_SETREG | UDC_RTCNT); sdc_delay(); sdaddr->dkc_reg = (RT_CNT | RT_MOTOR); rx_reselect = 1; if(sd_select(cmd,1)) { if(sddebug >=2) cprintf("%s%d:%s: Not selected \n",DEV_ID,ui->ui_slave,HARD_ERR); return(0); } /* if a diskette drive is present, TRK0 should be * set when RESTORE issued */ if( sd_restore(1)) { if(sddebug >=2) cprintf("%s%d:%s: Not selected\n",DEV_ID,ui->ui_slave,HARD_ERR); return(0); } } /* Even if there is no diskette drive, READY bit in * UDC_DSTAT is 1 !!. So restore to see if drive * really present */ else { if(sd_restore(1)) { if(sddebug >=2) cprintf("%s%d:%s: Not selected\n",DEV_ID,ui->ui_slave,HARD_ERR); return(0); } } sd_st.sd_cyl.sd_word = -1; sd_st.sd_drno = -1; sd_rxtype(ui->ui_slave); /* On PVAX, CFGTST reg bit for floppy type (RX23 or RX33) */ if ((cpu == C_VAXSTAR) && ((vs_cfgtst&VS_DRV2RX33) == 0)) { sd_rx23htype(ui->ui_slave); ui->ui_type = DT_RX23H; sd_st.sd_type[ui->ui_slave] = DT_RX23H; } else { sd_rx33type(ui->ui_slave); ui->ui_type = DT_RX33; sd_st.sd_type[ui->ui_slave] = DT_RX33; } return(1); /* break; */ default: mprintf("%s%d:%s: wrong unit number for sdslave\n",DEV_ID,ui->ui_slave,SOFT_ERR); return(0); }}sdattach(ui) register struct uba_device *ui;{ /* Initialize iostat values */ if(ui->ui_dk >= 0) { dk_mspw[ui->ui_dk] = .0000032; /* 16bit transfer time */ } sd_st.sd_softcnt[ui->ui_slave] = 0; /* initialize soft error count */ sd_st.sd_hardcnt[ui->ui_slave] = 0; /* initialize hard error count */ ui->ui_flags = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -