4 Get cost of insertion Req1 before Req2
9 PHW_LU_EXTENSION LunExt
,
19 // can't insert Req1 before tooooo old Req2
21 return REORDER_COST_TTL
;
22 // check if reorderable
23 flags1
= AtaReq1
->Flags
;
24 flags2
= AtaReq2
->Flags
;
25 if(!((flags2
& flags1
) & REQ_FLAG_REORDERABLE_CMD
))
26 return REORDER_COST_DENIED
;
27 // if at least one Req is WRITE, target areas
29 write1
= (flags1
& REQ_FLAG_RW_MASK
) == REQ_FLAG_WRITE
;
30 write2
= (flags2
& REQ_FLAG_RW_MASK
) == REQ_FLAG_WRITE
;
31 cost
= AtaReq1
->lba
+AtaReq1
->bcount
- AtaReq2
->lba
;
32 if( write1
|| write2
) {
33 // check for intersection
34 if((AtaReq1
->lba
< AtaReq2
->lba
+AtaReq2
->bcount
) &&
35 (AtaReq1
->lba
+AtaReq1
->bcount
> AtaReq2
->lba
)) {
37 return REORDER_COST_INTERSECT
;
41 cost
*= (1-LunExt
->SeekBackMCost
);
43 cost
*= (LunExt
->SeekBackMCost
-1);
45 if( write1
== write2
) {
48 return (cost
* LunExt
->RwSwitchMCost
) + LunExt
->RwSwitchCost
;
49 } // end UniataGetCost()
52 Insert command to proper place of command queue
53 Perform reorder if necessary
59 IN PSCSI_REQUEST_BLOCK Srb
62 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
72 BOOLEAN use_reorder
= chan
->UseReorder
/*EnableReorder*/;
73 #ifdef QUEUE_STATISTICS
74 BOOLEAN reordered
= FALSE
;
75 #endif //QUEUE_STATISTICS
77 PHW_LU_EXTENSION LunExt
= chan
->lun
[GET_LDEV(Srb
) & 1];
83 PrintNtConsole("q: chan = %#x, dev %#x\n", chan, GET_LDEV(Srb));
85 for(i=0; i<1000; i++) {
86 AtapiStallExecution(5*1000);
92 // check if queue is empty
93 if(LunExt
->queue_depth
) {
94 AtaReq
->ttl
= (UCHAR
)(max(LunExt
->queue_depth
, MIN_REQ_TTL
));
98 AtaReq2
= LunExt
->last_req
;
101 (Srb
->SrbFlags
& SRB_FLAGS_QUEUE_ACTION_ENABLE
)) {
102 switch(Srb
->QueueAction
) {
103 case SRB_ORDERED_QUEUE_TAG_REQUEST
:
105 #ifdef QUEUE_STATISTICS
106 chan
->TryReorderTailCount
++;
107 #endif //QUEUE_STATISTICS
109 case SRB_HEAD_OF_QUEUE_TAG_REQUEST
:
110 BestAtaReq1
= LunExt
->first_req
;
111 best_cost
= -REORDER_COST_RESELECT
;
112 #ifdef QUEUE_STATISTICS
113 chan
->TryReorderHeadCount
++;
114 #endif //QUEUE_STATISTICS
116 case SRB_SIMPLE_TAG_REQUEST
:
118 best_cost
= UniataGetCost(LunExt
, BestAtaReq1
, AtaReq
);
123 best_cost
= UniataGetCost(LunExt
, BestAtaReq1
, AtaReq
);
128 #ifdef QUEUE_STATISTICS
129 chan
->TryReorderCount
++;
130 #endif //QUEUE_STATISTICS
132 // walk through command queue and find the best
133 // place for insertion of the command
134 while ((AtaReq1
= AtaReq2
->prev_req
)) {
135 new_cost1
= UniataGetCost(LunExt
, AtaReq1
, AtaReq
);
136 new_cost2
= UniataGetCost(LunExt
, AtaReq
, AtaReq2
);
138 #ifdef QUEUE_STATISTICS
139 if(new_cost1
== REORDER_COST_INTERSECT
||
140 new_cost2
== REORDER_COST_INTERSECT
)
141 chan
->IntersectCount
++;
142 #endif //QUEUE_STATISTICS
144 if(new_cost2
> REORDER_COST_RESELECT
)
147 // for now I see nothing bad in RESELECT here
148 //ASSERT(new_cost1 <= REORDER_COST_RESELECT);
150 new_cost
= UniataGetCost(LunExt
, AtaReq1
, AtaReq2
);
151 new_cost
= new_cost1
+ new_cost2
- new_cost
;
153 // check for Stop Reordering
154 if(new_cost
> REORDER_COST_RESELECT
*3)
157 if(new_cost
< best_cost
) {
158 best_cost
= new_cost
;
159 BestAtaReq1
= AtaReq1
;
160 #ifdef QUEUE_STATISTICS
162 #endif //QUEUE_STATISTICS
166 #ifdef QUEUE_STATISTICS
168 chan
->ReorderCount
++;
169 #endif //QUEUE_STATISTICS
171 // Insert Req between Req2 & Req1
172 AtaReq2
= BestAtaReq1
->next_req
;
174 AtaReq2
->prev_req
= AtaReq
;
175 AtaReq
->next_req
= AtaReq2
;
177 AtaReq
->next_req
= NULL
;
178 LunExt
->last_req
= AtaReq
;
180 // LunExt->last_req->next_req = AtaReq;
181 BestAtaReq1
->next_req
= AtaReq
;
182 // AtaReq->prev_req = LunExt->last_req;
183 AtaReq
->prev_req
= BestAtaReq1
;
186 while((AtaReq1
= AtaReq1
->next_req
)) {
187 //ASSERT(AtaReq1->ttl);
195 AtaReq
->next_req
= NULL
;
197 LunExt
->last_req
= AtaReq
;
199 LunExt
->queue_depth
++;
201 chan
->DeviceExtension
->queue_depth
++;
202 // check if this is the 1st request in queue
203 if(chan
->queue_depth
== 1) {
204 chan
->cur_req
= LunExt
->first_req
;
207 #ifdef QUEUE_STATISTICS
208 //ASSERT(LunExt->queue_depth);
209 chan
->QueueStat
[min(MAX_QUEUE_STAT
, LunExt
->queue_depth
)-1]++;
210 #endif //QUEUE_STATISTICS
212 ASSERT(chan->queue_depth ==
213 (chan->lun[0]->queue_depth + chan->lun[1]->queue_depth));
214 ASSERT(!chan->queue_depth || chan->cur_req);
217 } // end UniataQueueRequest()
220 Remove request from queue and get next request
226 IN PSCSI_REQUEST_BLOCK Srb
234 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
235 //PHW_DEVICE_EXTENSION deviceExtension = chan->DeviceExtension;
237 ULONG cdev
= GET_LDEV(Srb
) & 1;
238 PHW_LU_EXTENSION LunExt
= chan
->lun
[cdev
];
244 ASSERT(chan->queue_depth ==
245 (chan->lun[0]->queue_depth + chan->lun[1]->queue_depth));
246 ASSERT(!chan->queue_depth || chan->cur_req);
248 // check if queue for the device is empty
249 if(!LunExt
->queue_depth
)
252 // check if request is under processing (busy)
253 if(!AtaReq
->ReqState
)
256 // remove reqest from queue
257 if(AtaReq
->prev_req
) {
258 AtaReq
->prev_req
->next_req
=
261 LunExt
->first_req
= AtaReq
->next_req
;
263 if(AtaReq
->next_req
) {
264 AtaReq
->next_req
->prev_req
=
267 LunExt
->last_req
= AtaReq
->prev_req
;
269 LunExt
->queue_depth
--;
271 chan
->DeviceExtension
->queue_depth
--;
272 // set LastWrite flag for Lun
273 LunExt
->last_write
= ((AtaReq
->Flags
& REQ_FLAG_RW_MASK
) == REQ_FLAG_WRITE
);
275 // get request from longest queue to balance load
276 if(chan
->lun
[0]->queue_depth
* (chan
->lun
[0]->LunSelectWaitCount
+1) >
277 chan
->lun
[1]->queue_depth
* (chan
->lun
[1]->LunSelectWaitCount
+1)) {
282 /* // prevent too long wait for actively used device
283 if(chan->lun[cdev ^ 1]->queue_depth &&
284 chan->lun[cdev ^ 1]->LunSelectWaitCount >= chan->lun[cdev]->queue_depth) {
287 // get next request for processing
288 chan
->cur_req
= chan
->lun
[cdev
]->first_req
;
289 chan
->cur_cdev
= cdev
;
290 if(!chan
->lun
[cdev
^ 1]->queue_depth
) {
291 chan
->lun
[cdev
^ 1]->LunSelectWaitCount
=0;
293 chan
->lun
[cdev
^ 1]->LunSelectWaitCount
++;
295 chan
->lun
[cdev
]->LunSelectWaitCount
=0;
297 // chan->first_req->prev_req = NULL;
298 AtaReq
->ReqState
= REQ_STATE_NONE
;
300 ASSERT(chan->queue_depth ==
301 (chan->lun[0]->queue_depth + chan->lun[1]->queue_depth));
302 ASSERT(!chan->queue_depth || chan->cur_req);
305 } // end UniataRemoveRequest()
308 Get currently processed request
309 (from head of the queue)
317 // if(!chan->lun[]->queue_depth) {
318 if(!chan
|| !chan
->cur_req
) {
322 return chan
->cur_req
->Srb
;
323 } // end UniataGetCurRequest()
326 Get next channel to be serviced
327 (used in simplex mode only)
331 UniataGetNextChannel(
336 PHW_DEVICE_EXTENSION deviceExtension
;
340 deviceExtension
= chan
->DeviceExtension
;
342 if(!deviceExtension
->simplexOnly
) {
345 KdPrint2((PRINT_PREFIX
"UniataGetNextChannel:\n"));
348 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
349 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
350 chan
= &deviceExtension
->chan
[c
];
351 if(chan
->queue_depth
&&
352 chan
->queue_depth
* (chan
->ChannelSelectWaitCount
+1) >
355 cost_c
= chan
->queue_depth
* (chan
->ChannelSelectWaitCount
+1);
358 if(best_c
== CHAN_NOT_SPECIFIED
) {
359 KdPrint2((PRINT_PREFIX
" empty queues\n"));
362 deviceExtension
->FirstChannelToCheck
= c
;
363 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
364 chan
= &deviceExtension
->chan
[_c
];
366 chan
->ChannelSelectWaitCount
= 0;
369 chan
->ChannelSelectWaitCount
++;
370 if(!chan
->queue_depth
) {
371 chan
->ChannelSelectWaitCount
= 0;
373 chan
->ChannelSelectWaitCount
++;
376 KdPrint2((PRINT_PREFIX
" select chan %d\n", best_c
));
377 return &deviceExtension
->chan
[best_c
];
378 } // end UniataGetNextChannel()