|
|
1.1 ! root 1: #define KVM_PUNT 1 ! 2: #define REQUIRE_SECT_ALIGN 1 /* */ ! 3: ! 4: static boolean_t fd_setup_rw_req(fd_volume_t fvp, ! 5: boolean_t bad_block_map) /* TRUE = check for remapping */ ! 6: { ! 7: /* input: fvp->start_sect ! 8: * fvp->bytes_to_go ! 9: * fvp->start_addrs ! 10: * fvp->io_flags ! 11: * fvp->dev_ioreq.pmap ! 12: * fvp->dev_ioreq.map ! 13: * fvp->format_info ! 14: * output: fvp->current_sect ! 15: * fvp->current_byte_cnt ! 16: * fvp->current_addrs ! 17: * fvp->dev_ioreq ! 18: * ! 19: * This routine determines the largest "safe" I/O which can be ! 20: * performed starting at fvp->start_sect, up to a max of ! 21: * fvp->bytes_to_go bytes. The bad block table will only be consulted ! 22: * if bad_block_map is also TRUE. ! 23: * ! 24: * No I/O is allowed to go past a track boundary. ! 25: * ! 26: * Short writes (less than one sector) result in user data being ! 27: * copied to *fvp->sect_buf, memory for which is allocated here. ! 28: * DMA occurs out of this buffer. The buffer must be freed upon I/O ! 29: * complete. ! 30: * ! 31: * Parameters describing the resulting "safe" I/O are placed in ! 32: * fvp->current_sect and fvp->current_byte_cnt. An fd_rw_cmd is then ! 33: * generated and placed in fvp->dev_ioreq.cmd_blk[]. ! 34: * ! 35: * Returns TRUE if mapping occurred. ! 36: */ ! 37: struct fd_rw_cmd start_rw_cmd; /* first sector, phys params */ ! 38: struct fd_format_info *fip = &fvp->format_info; ! 39: u_int sect_size = fip->sectsize_info.sect_size; ! 40: int num_sects = howmany(fvp->bytes_to_go, sect_size); ! 41: int bytes_to_xfr; ! 42: caddr_t start_addrs; ! 43: ! 44: XDBG(("fd_setup_rw_req: start_sect = %d\n", fvp->start_sect)); ! 45: /* ! 46: * See if we'll wrap past a track boundary. Max sector number on ! 47: * a track is sects_per_trk, NOT sects_per_trk-1... ! 48: */ ! 49: fd_log_2_phys(fvp, fvp->start_sect, &start_rw_cmd); ! 50: if((start_rw_cmd.sector + num_sects) > ! 51: (fip->sectsize_info.sects_per_trk+1)) { ! 52: num_sects = fip->sectsize_info.sects_per_trk - ! 53: start_rw_cmd.sector + 1; ! 54: bytes_to_xfr = num_sects * sect_size; ! 55: XDBG(("fd_setup_rw_req: track wrap: num_sects = %d\n", ! 56: num_sects)); ! 57: } ! 58: else { ! 59: /* ! 60: * The whole I/O fits on one track. ! 61: */ ! 62: bytes_to_xfr = fvp->bytes_to_go; ! 63: } ! 64: /* ! 65: * See if we have to deal with a partial sector. ! 66: */ ! 67: start_addrs = fvp->start_addrs; ! 68: fvp->padded_byte_cnt = 0; ! 69: #ifdef REQUIRE_SECT_ALIGN ! 70: if(bytes_to_xfr & (sect_size - 1)) { ! 71: printf("fd%d: PARTIAL SECTOR I/O\n", fvp->volume_num); ! 72: } ! 73: short_write_out: ! 74: ! 75: fvp->current_sect = fvp->start_sect; ! 76: fvp->current_byte_cnt = bytes_to_xfr; ! 77: fvp->current_addrs = start_addrs; ! 78: fd_gen_rw_cmd(fvp, ! 79: &fvp->dev_ioreq, ! 80: fvp->current_sect, ! 81: fvp->current_byte_cnt, ! 82: fvp->current_addrs, ! 83: fvp->io_flags & FVIOF_READ); ! 84: return(FALSE); ! 85: ! 86: } /* fd_setup_rw_req() */ ! 87: ! 88: /* ! 89: * generate a write or read command in *fdiop (No I/O). ! 90: */ ! 91: static void fd_gen_rw_cmd(fd_volume_t fvp, ! 92: fd_ioreq_t fdiop, ! 93: u_int sector, ! 94: u_int byte_count, ! 95: caddr_t dma_addrs, ! 96: int read) /* non-zero ==> read */ ! 97: { ! 98: struct fd_rw_cmd *cmdp = (struct fd_rw_cmd *)fdiop->cmd_blk; ! 99: struct fd_format_info *fip = &fvp->format_info; ! 100: ! 101: XADDBG(("fd_gen_rw_cmd: sector 0x%x byte_count 0x%x read = %d\n", ! 102: sector, byte_count, read)); ! 103: bzero(cmdp, SIZEOF_RW_CMD); ! 104: fd_log_2_phys(fvp, sector, cmdp); /* assign track, head, sect */ ! 105: cmdp->mt = 0; /* multitrack - always false */ ! 106: cmdp->mfm = fip->density_info.mfm; ! 107: cmdp->opcode = read ? FCCMD_READ : FCCMD_WRITE; ! 108: cmdp->hds = cmdp->head; ! 109: /* ! 110: * controller thread writes drive_sel. ! 111: */ ! 112: cmdp->sector_size = fip->sectsize_info.n; ! 113: /* ! 114: * eot = the number of the LAST sector to be read/written. ! 115: */ ! 116: cmdp->eot = cmdp->sector + howmany(byte_count, ! 117: fip->sectsize_info.sect_size) - 1; ! 118: cmdp->gap_length = fip->sectsize_info.rw_gap_length; ! 119: cmdp->dtl = 0xff; ! 120: ! 121: fdiop->density = fip->density_info.density; ! 122: fdiop->timeout = TO_RW; ! 123: fdiop->command = FDCMD_CMD_XFR; ! 124: fdiop->num_cmd_bytes = SIZEOF_RW_CMD; ! 125: fdiop->addrs = dma_addrs; ! 126: fdiop->byte_count = byte_count; ! 127: fdiop->num_stat_bytes = SIZEOF_RW_STAT; ! 128: if(read) ! 129: fdiop->flags |= FD_IOF_DMA_RD; ! 130: else ! 131: fdiop->flags &= ~FD_IOF_DMA_RD; ! 132: ! 133: } /* fd_gen_rw_cmd() */ ! 134: ! 135: /* ! 136: * convert logical sector # into cylinder, head, sector. No range checking. ! 137: * Physical parameters are obtained from *fvp->labelp and fvp->sects_per_track. ! 138: * ! 139: * First sector on a track is sector 1. ! 140: */ ! 141: static void fd_log_2_phys(fd_volume_t fvp, ! 142: u_int sector, ! 143: struct fd_rw_cmd *cmdp) ! 144: { ! 145: u_int track; ! 146: struct fd_format_info *fip = &fvp->format_info; ! 147: ! 148: ASSERT((fip->sectsize_info.sects_per_trk != 0) && ! 149: (fip->disk_info.tracks_per_cyl != 0)); ! 150: track = sector / fip->sectsize_info.sects_per_trk; ! 151: cmdp->cylinder = track / fip->disk_info.tracks_per_cyl; ! 152: cmdp->head = track % fip->disk_info.tracks_per_cyl; ! 153: cmdp->sector = sector % fip->sectsize_info.sects_per_trk + 1; ! 154: XADDBG(("fd_log_2_phys: lsect 0x%x; cyl 0x%x head 0x%x sector " ! 155: "0x%x\n", sector, cmdp->cylinder, cmdp->head, cmdp->sector-1)); ! 156: } ! 157: ! 158: ........................ ! 159: ! 160: what we really want: ! 161: ! 162: /* ! 163: * Common r/w routine. The following fdBuf fields are required: ! 164: * block ! 165: * blockCnt ! 166: * buf ! 167: * client ! 168: * pending ! 169: * ! 170: * block and blockCnt are assumed to be already adjusted for overflow. ! 171: */ ! 172: - (ioReturn_t)fdRwCommon : (fdBuf_t *)fdBuf ! 173: { ! 174: int currentBlock = fdBuf->block; ! 175: int blocksToGo = fdBuf->blockCnt; ! 176: char *currentBuf = fdBuf->buf; ! 177: int currentBlockCnt; ! 178: fdIoReq_t fdIoReq; ! 179: ioReturn_t rtn; ! 180: int block_size = [self getBlockSize]; ! 181: boolean_t readFlag = fdBuf->command == FDC_READ ? TRUE : FALSE; ! 182: ! 183: xpr_fd("fdRwCommon: block 0x%x count 0x%x\n", ! 184: fdBuf->block, fdBuf->BlockCnt, 3,4,5); ! 185: ! 186: /* ! 187: * We never cross a track boundary while reading and writing. This ! 188: * loop is executed once for each segment. ! 189: */ ! 190: while(blocksToGo) { ! 191: ! 192: /* ! 193: * Set up controller command block for current segment. ! 194: */ ! 195: currentBlockCnt = [self rwBlockCount:currentBlock ! 196: blocksToGo:blocksToGo]; ! 197: [self fdGenRwCmd:currentBlock ! 198: blockCount:currentBlockCnt ! 199: fdIoReq:&fdIoReq ! 200: read:readFlag]; ! 201: fdIoReq->command = FDCMD_CMD_XFR; ! 202: fdIoReq->addrs = currentBuf; ! 203: fdIoReq->byte_count = currentBlockCnt * block_size; ! 204: rtn = [self fdSendCmd:&fdIoReq]; ! 205: ! 206: /* ! 207: * OK, what happened? ! 208: */ ! 209: } ! 210: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.