|
|
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.