1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#ifndef _AIC79XX_INLINE_H_
46#define _AIC79XX_INLINE_H_
47
48
49static __inline char *ahd_name(struct ahd_softc *ahd);
50
51static __inline char *
52ahd_name(struct ahd_softc *ahd)
53{
54 return (ahd->name);
55}
56
57
58static __inline void ahd_known_modes(struct ahd_softc *ahd,
59 ahd_mode src, ahd_mode dst);
60static __inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd,
61 ahd_mode src,
62 ahd_mode dst);
63static __inline void ahd_extract_mode_state(struct ahd_softc *ahd,
64 ahd_mode_state state,
65 ahd_mode *src, ahd_mode *dst);
66static __inline void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src,
67 ahd_mode dst);
68static __inline void ahd_update_modes(struct ahd_softc *ahd);
69static __inline void ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
70 ahd_mode dstmode, const char *file,
71 int line);
72static __inline ahd_mode_state ahd_save_modes(struct ahd_softc *ahd);
73static __inline void ahd_restore_modes(struct ahd_softc *ahd,
74 ahd_mode_state state);
75static __inline int ahd_is_paused(struct ahd_softc *ahd);
76static __inline void ahd_pause(struct ahd_softc *ahd);
77static __inline void ahd_unpause(struct ahd_softc *ahd);
78
79static __inline void
80ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
81{
82 ahd->src_mode = src;
83 ahd->dst_mode = dst;
84 ahd->saved_src_mode = src;
85 ahd->saved_dst_mode = dst;
86}
87
88static __inline ahd_mode_state
89ahd_build_mode_state(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
90{
91 return ((src << SRC_MODE_SHIFT) | (dst << DST_MODE_SHIFT));
92}
93
94static __inline void
95ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state,
96 ahd_mode *src, ahd_mode *dst)
97{
98 *src = (state & SRC_MODE) >> SRC_MODE_SHIFT;
99 *dst = (state & DST_MODE) >> DST_MODE_SHIFT;
100}
101
102static __inline void
103ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
104{
105 if (ahd->src_mode == src && ahd->dst_mode == dst)
106 return;
107#ifdef AHD_DEBUG
108 if (ahd->src_mode == AHD_MODE_UNKNOWN
109 || ahd->dst_mode == AHD_MODE_UNKNOWN)
110 panic("Setting mode prior to saving it.\n");
111 if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
112 printf("%s: Setting mode 0x%x\n", ahd_name(ahd),
113 ahd_build_mode_state(ahd, src, dst));
114#endif
115 ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst));
116 ahd->src_mode = src;
117 ahd->dst_mode = dst;
118}
119
120static __inline void
121ahd_update_modes(struct ahd_softc *ahd)
122{
123 ahd_mode_state mode_ptr;
124 ahd_mode src;
125 ahd_mode dst;
126
127 mode_ptr = ahd_inb(ahd, MODE_PTR);
128#ifdef AHD_DEBUG
129 if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
130 printf("Reading mode 0x%x\n", mode_ptr);
131#endif
132 ahd_extract_mode_state(ahd, mode_ptr, &src, &dst);
133 ahd_known_modes(ahd, src, dst);
134}
135
136static __inline void
137ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
138 ahd_mode dstmode, const char *file, int line)
139{
140#ifdef AHD_DEBUG
141 if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0
142 || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) {
143 panic("%s:%s:%d: Mode assertion failed.\n",
144 ahd_name(ahd), file, line);
145 }
146#endif
147}
148
149static __inline ahd_mode_state
150ahd_save_modes(struct ahd_softc *ahd)
151{
152 if (ahd->src_mode == AHD_MODE_UNKNOWN
153 || ahd->dst_mode == AHD_MODE_UNKNOWN)
154 ahd_update_modes(ahd);
155
156 return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode));
157}
158
159static __inline void
160ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state)
161{
162 ahd_mode src;
163 ahd_mode dst;
164
165 ahd_extract_mode_state(ahd, state, &src, &dst);
166 ahd_set_modes(ahd, src, dst);
167}
168
169#define AHD_ASSERT_MODES(ahd, source, dest) \
170 ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__);
171
172
173
174
175
176static __inline int
177ahd_is_paused(struct ahd_softc *ahd)
178{
179 return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0);
180}
181
182
183
184
185
186
187
188
189static __inline void
190ahd_pause(struct ahd_softc *ahd)
191{
192 ahd_outb(ahd, HCNTRL, ahd->pause);
193
194
195
196
197
198 while (ahd_is_paused(ahd) == 0)
199 ;
200}
201
202
203
204
205
206
207
208
209
210
211
212static __inline void
213ahd_unpause(struct ahd_softc *ahd)
214{
215
216
217
218
219 if (ahd->saved_src_mode != AHD_MODE_UNKNOWN
220 && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) {
221 if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0)
222 ahd_reset_cmds_pending(ahd);
223 ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
224 }
225
226 if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
227 ahd_outb(ahd, HCNTRL, ahd->unpause);
228
229 ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
230}
231
232
233static __inline void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
234 void *sgptr, bus_addr_t addr,
235 bus_size_t len, int last);
236static __inline void ahd_setup_scb_common(struct ahd_softc *ahd,
237 struct scb *scb);
238static __inline void ahd_setup_data_scb(struct ahd_softc *ahd,
239 struct scb *scb);
240static __inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd,
241 struct scb *scb);
242
243static __inline void *
244ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
245 void *sgptr, bus_addr_t addr, bus_size_t len, int last)
246{
247 scb->sg_count++;
248 if (sizeof(bus_addr_t) > 4
249 && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
250 struct ahd_dma64_seg *sg;
251
252 sg = (struct ahd_dma64_seg *)sgptr;
253 sg->addr = ahd_htole64(addr);
254 sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
255 return (sg + 1);
256 } else {
257 struct ahd_dma_seg *sg;
258
259 sg = (struct ahd_dma_seg *)sgptr;
260 sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
261 sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)
262 | (last ? AHD_DMA_LAST_SEG : 0));
263 return (sg + 1);
264 }
265}
266
267static __inline void
268ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
269{
270
271 scb->crc_retry_count = 0;
272 if ((scb->flags & SCB_PACKETIZED) != 0) {
273
274 scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;
275 } else {
276 if (ahd_get_transfer_length(scb) & 0x01)
277 scb->hscb->task_attribute = SCB_XFERLEN_ODD;
278 else
279 scb->hscb->task_attribute = 0;
280 }
281
282 if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
283 || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)
284 scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =
285 ahd_htole32(scb->sense_busaddr);
286}
287
288static __inline void
289ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
290{
291
292
293
294 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
295 struct ahd_dma64_seg *sg;
296
297 sg = (struct ahd_dma64_seg *)scb->sg_list;
298 scb->hscb->dataptr = sg->addr;
299 scb->hscb->datacnt = sg->len;
300 } else {
301 struct ahd_dma_seg *sg;
302 uint32_t *dataptr_words;
303
304 sg = (struct ahd_dma_seg *)scb->sg_list;
305 dataptr_words = (uint32_t*)&scb->hscb->dataptr;
306 dataptr_words[0] = sg->addr;
307 dataptr_words[1] = 0;
308 if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
309 uint64_t high_addr;
310
311 high_addr = ahd_le32toh(sg->len) & 0x7F000000;
312 scb->hscb->dataptr |= ahd_htole64(high_addr << 8);
313 }
314 scb->hscb->datacnt = sg->len;
315 }
316
317
318
319
320
321
322 scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
323}
324
325static __inline void
326ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)
327{
328 scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL);
329 scb->hscb->dataptr = 0;
330 scb->hscb->datacnt = 0;
331}
332
333
334static __inline size_t ahd_sg_size(struct ahd_softc *ahd);
335static __inline void *
336 ahd_sg_bus_to_virt(struct ahd_softc *ahd,
337 struct scb *scb,
338 uint32_t sg_busaddr);
339static __inline uint32_t
340 ahd_sg_virt_to_bus(struct ahd_softc *ahd,
341 struct scb *scb,
342 void *sg);
343static __inline void ahd_sync_scb(struct ahd_softc *ahd,
344 struct scb *scb, int op);
345static __inline void ahd_sync_sglist(struct ahd_softc *ahd,
346 struct scb *scb, int op);
347static __inline void ahd_sync_sense(struct ahd_softc *ahd,
348 struct scb *scb, int op);
349static __inline uint32_t
350 ahd_targetcmd_offset(struct ahd_softc *ahd,
351 u_int index);
352
353static __inline size_t
354ahd_sg_size(struct ahd_softc *ahd)
355{
356 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
357 return (sizeof(struct ahd_dma64_seg));
358 return (sizeof(struct ahd_dma_seg));
359}
360
361static __inline void *
362ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr)
363{
364 bus_addr_t sg_offset;
365
366
367 sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd));
368 return ((uint8_t *)scb->sg_list + sg_offset);
369}
370
371static __inline uint32_t
372ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)
373{
374 bus_addr_t sg_offset;
375
376
377 sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list)
378 - ahd_sg_size(ahd);
379
380 return (scb->sg_list_busaddr + sg_offset);
381}
382
383static __inline void
384ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)
385{
386 ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,
387 scb->hscb_map->dmamap,
388 (uint8_t*)scb->hscb - scb->hscb_map->vaddr,
389 sizeof(*scb->hscb), op);
390}
391
392static __inline void
393ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
394{
395 if (scb->sg_count == 0)
396 return;
397
398 ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat,
399 scb->sg_map->dmamap,
400 scb->sg_list_busaddr - ahd_sg_size(ahd),
401 ahd_sg_size(ahd) * scb->sg_count, op);
402}
403
404static __inline void
405ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)
406{
407 ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat,
408 scb->sense_map->dmamap,
409 scb->sense_busaddr,
410 AHD_SENSE_BUFSIZE, op);
411}
412
413static __inline uint32_t
414ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)
415{
416 return (((uint8_t *)&ahd->targetcmds[index])
417 - (uint8_t *)ahd->qoutfifo);
418}
419
420
421static __inline void ahd_complete_scb(struct ahd_softc *ahd,
422 struct scb *scb);
423static __inline void ahd_update_residual(struct ahd_softc *ahd,
424 struct scb *scb);
425static __inline struct ahd_initiator_tinfo *
426 ahd_fetch_transinfo(struct ahd_softc *ahd,
427 char channel, u_int our_id,
428 u_int remote_id,
429 struct ahd_tmode_tstate **tstate);
430static __inline uint16_t
431 ahd_inw(struct ahd_softc *ahd, u_int port);
432static __inline void ahd_outw(struct ahd_softc *ahd, u_int port,
433 u_int value);
434static __inline uint32_t
435 ahd_inl(struct ahd_softc *ahd, u_int port);
436static __inline void ahd_outl(struct ahd_softc *ahd, u_int port,
437 uint32_t value);
438static __inline uint64_t
439 ahd_inq(struct ahd_softc *ahd, u_int port);
440static __inline void ahd_outq(struct ahd_softc *ahd, u_int port,
441 uint64_t value);
442static __inline u_int ahd_get_scbptr(struct ahd_softc *ahd);
443static __inline void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr);
444static __inline u_int ahd_get_hnscb_qoff(struct ahd_softc *ahd);
445static __inline void ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value);
446static __inline u_int ahd_get_hescb_qoff(struct ahd_softc *ahd);
447static __inline void ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value);
448static __inline u_int ahd_get_snscb_qoff(struct ahd_softc *ahd);
449static __inline void ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value);
450static __inline u_int ahd_get_sescb_qoff(struct ahd_softc *ahd);
451static __inline void ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value);
452static __inline u_int ahd_get_sdscb_qoff(struct ahd_softc *ahd);
453static __inline void ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value);
454static __inline u_int ahd_inb_scbram(struct ahd_softc *ahd, u_int offset);
455static __inline u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset);
456static __inline uint32_t
457 ahd_inl_scbram(struct ahd_softc *ahd, u_int offset);
458static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd,
459 struct scb *scb);
460static __inline void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
461static __inline uint8_t *
462 ahd_get_sense_buf(struct ahd_softc *ahd,
463 struct scb *scb);
464static __inline uint32_t
465 ahd_get_sense_bufaddr(struct ahd_softc *ahd,
466 struct scb *scb);
467
468static __inline void
469ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb)
470{
471 uint32_t sgptr;
472
473 sgptr = ahd_le32toh(scb->hscb->sgptr);
474 if ((sgptr & SG_STATUS_VALID) != 0)
475 ahd_handle_scb_status(ahd, scb);
476 else
477 ahd_done(ahd, scb);
478}
479
480
481
482
483
484static __inline void
485ahd_update_residual(struct ahd_softc *ahd, struct scb *scb)
486{
487 uint32_t sgptr;
488
489 sgptr = ahd_le32toh(scb->hscb->sgptr);
490 if ((sgptr & SG_STATUS_VALID) != 0)
491 ahd_calc_residual(ahd, scb);
492}
493
494
495
496
497
498static __inline struct ahd_initiator_tinfo *
499ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id,
500 u_int remote_id, struct ahd_tmode_tstate **tstate)
501{
502
503
504
505
506
507
508 if (channel == 'B')
509 our_id += 8;
510 *tstate = ahd->enabled_targets[our_id];
511 return (&(*tstate)->transinfo[remote_id]);
512}
513
514#define AHD_COPY_COL_IDX(dst, src) \
515do { \
516 dst->hscb->scsiid = src->hscb->scsiid; \
517 dst->hscb->lun = src->hscb->lun; \
518} while (0)
519
520static __inline uint16_t
521ahd_inw(struct ahd_softc *ahd, u_int port)
522{
523 return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));
524}
525
526static __inline void
527ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
528{
529 ahd_outb(ahd, port, value & 0xFF);
530 ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
531}
532
533static __inline uint32_t
534ahd_inl(struct ahd_softc *ahd, u_int port)
535{
536 return ((ahd_inb(ahd, port))
537 | (ahd_inb(ahd, port+1) << 8)
538 | (ahd_inb(ahd, port+2) << 16)
539 | (ahd_inb(ahd, port+3) << 24));
540}
541
542static __inline void
543ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)
544{
545 ahd_outb(ahd, port, (value) & 0xFF);
546 ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);
547 ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);
548 ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);
549}
550
551static __inline uint64_t
552ahd_inq(struct ahd_softc *ahd, u_int port)
553{
554 return ((ahd_inb(ahd, port))
555 | (ahd_inb(ahd, port+1) << 8)
556 | (ahd_inb(ahd, port+2) << 16)
557 | (ahd_inb(ahd, port+3) << 24)
558 | (((uint64_t)ahd_inb(ahd, port+4)) << 32)
559 | (((uint64_t)ahd_inb(ahd, port+5)) << 40)
560 | (((uint64_t)ahd_inb(ahd, port+6)) << 48)
561 | (((uint64_t)ahd_inb(ahd, port+7)) << 56));
562}
563
564static __inline void
565ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)
566{
567 ahd_outb(ahd, port, value & 0xFF);
568 ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
569 ahd_outb(ahd, port+2, (value >> 16) & 0xFF);
570 ahd_outb(ahd, port+3, (value >> 24) & 0xFF);
571 ahd_outb(ahd, port+4, (value >> 32) & 0xFF);
572 ahd_outb(ahd, port+5, (value >> 40) & 0xFF);
573 ahd_outb(ahd, port+6, (value >> 48) & 0xFF);
574 ahd_outb(ahd, port+7, (value >> 56) & 0xFF);
575}
576
577static __inline u_int
578ahd_get_scbptr(struct ahd_softc *ahd)
579{
580 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
581 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
582 return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));
583}
584
585static __inline void
586ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)
587{
588 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
589 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
590 ahd_outb(ahd, SCBPTR, scbptr & 0xFF);
591 ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);
592}
593
594static __inline u_int
595ahd_get_hnscb_qoff(struct ahd_softc *ahd)
596{
597 return (ahd_inw_atomic(ahd, HNSCB_QOFF));
598}
599
600static __inline void
601ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)
602{
603 ahd_outw_atomic(ahd, HNSCB_QOFF, value);
604}
605
606static __inline u_int
607ahd_get_hescb_qoff(struct ahd_softc *ahd)
608{
609 return (ahd_inb(ahd, HESCB_QOFF));
610}
611
612static __inline void
613ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)
614{
615 ahd_outb(ahd, HESCB_QOFF, value);
616}
617
618static __inline u_int
619ahd_get_snscb_qoff(struct ahd_softc *ahd)
620{
621 u_int oldvalue;
622
623 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
624 oldvalue = ahd_inw(ahd, SNSCB_QOFF);
625 ahd_outw(ahd, SNSCB_QOFF, oldvalue);
626 return (oldvalue);
627}
628
629static __inline void
630ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)
631{
632 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
633 ahd_outw(ahd, SNSCB_QOFF, value);
634}
635
636static __inline u_int
637ahd_get_sescb_qoff(struct ahd_softc *ahd)
638{
639 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
640 return (ahd_inb(ahd, SESCB_QOFF));
641}
642
643static __inline void
644ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)
645{
646 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
647 ahd_outb(ahd, SESCB_QOFF, value);
648}
649
650static __inline u_int
651ahd_get_sdscb_qoff(struct ahd_softc *ahd)
652{
653 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
654 return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));
655}
656
657static __inline void
658ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)
659{
660 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
661 ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);
662 ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);
663}
664
665static __inline u_int
666ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
667{
668 u_int value;
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684 value = ahd_inb(ahd, offset);
685 if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0)
686 ahd_inb(ahd, MODE_PTR);
687 return (value);
688}
689
690static __inline u_int
691ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
692{
693 return (ahd_inb_scbram(ahd, offset)
694 | (ahd_inb_scbram(ahd, offset+1) << 8));
695}
696
697static __inline uint32_t
698ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
699{
700 return (ahd_inb_scbram(ahd, offset)
701 | (ahd_inb_scbram(ahd, offset+1) << 8)
702 | (ahd_inb_scbram(ahd, offset+2) << 16)
703 | (ahd_inb_scbram(ahd, offset+3) << 24));
704}
705
706static __inline struct scb *
707ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
708{
709 struct scb* scb;
710
711 if (tag >= AHD_SCB_MAX)
712 return (NULL);
713 scb = ahd->scb_data.scbindex[tag];
714 if (scb != NULL)
715 ahd_sync_scb(ahd, scb,
716 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
717 return (scb);
718}
719
720static __inline void
721ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
722{
723 struct hardware_scb *q_hscb;
724 uint32_t saved_hscb_busaddr;
725
726
727
728
729
730
731
732
733
734
735
736
737
738 q_hscb = ahd->next_queued_hscb;
739 saved_hscb_busaddr = q_hscb->hscb_busaddr;
740 memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
741 q_hscb->hscb_busaddr = saved_hscb_busaddr;
742 q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
743
744
745 ahd->next_queued_hscb = scb->hscb;
746 scb->hscb = q_hscb;
747
748
749 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
750}
751
752
753
754
755static __inline void
756ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
757{
758 ahd_swap_with_next_hscb(ahd, scb);
759
760 if (SCBID_IS_NULL(SCB_GET_TAG(scb)))
761 panic("Attempt to queue invalid SCB tag %x\n",
762 SCB_GET_TAG(scb));
763
764
765
766
767 ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
768 ahd->qinfifonext++;
769
770 if (scb->sg_count != 0)
771 ahd_setup_data_scb(ahd, scb);
772 else
773 ahd_setup_noxfer_scb(ahd, scb);
774 ahd_setup_scb_common(ahd, scb);
775
776
777
778
779
780 ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
781
782#ifdef AHD_DEBUG
783 if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
784 uint64_t host_dataptr;
785
786 host_dataptr = ahd_le64toh(scb->hscb->dataptr);
787 printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
788 ahd_name(ahd),
789 SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr),
790 (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
791 (u_int)(host_dataptr & 0xFFFFFFFF),
792 ahd_le32toh(scb->hscb->datacnt));
793 }
794#endif
795
796 ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
797}
798
799static __inline uint8_t *
800ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb)
801{
802 return (scb->sense_data);
803}
804
805static __inline uint32_t
806ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
807{
808 return (scb->sense_busaddr);
809}
810
811
812static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op);
813static __inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op);
814static __inline u_int ahd_check_cmdcmpltqueues(struct ahd_softc *ahd);
815static __inline int ahd_intr(struct ahd_softc *ahd);
816
817static __inline void
818ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
819{
820 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
821 0, AHC_SCB_MAX * sizeof(uint16_t), op);
822}
823
824static __inline void
825ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
826{
827#ifdef AHD_TARGET_MODE
828 if ((ahd->flags & AHD_TARGETROLE) != 0) {
829 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
830 ahd->shared_data_dmamap,
831 ahd_targetcmd_offset(ahd, 0),
832 sizeof(struct target_cmd) * AHD_TMODE_CMDS,
833 op);
834 }
835#endif
836}
837
838
839
840
841
842#define AHD_RUN_QOUTFIFO 0x1
843#define AHD_RUN_TQINFIFO 0x2
844static __inline u_int
845ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
846{
847 u_int retval;
848
849 retval = 0;
850 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
851 ahd->qoutfifonext, 2,
852 BUS_DMASYNC_POSTREAD);
853 if ((ahd->qoutfifo[ahd->qoutfifonext]
854 & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag)
855 retval |= AHD_RUN_QOUTFIFO;
856#ifdef AHD_TARGET_MODE
857 if ((ahd->flags & AHD_TARGETROLE) != 0
858 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
859 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
860 ahd->shared_data_dmamap,
861 ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
862 sizeof(struct target_cmd),
863 BUS_DMASYNC_POSTREAD);
864 if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)
865 retval |= AHD_RUN_TQINFIFO;
866 }
867#endif
868 return (retval);
869}
870
871
872
873
874static __inline int
875ahd_intr(struct ahd_softc *ahd)
876{
877 u_int intstat;
878
879 if ((ahd->pause & INTEN) == 0) {
880
881
882
883
884
885
886 return (0);
887 }
888
889
890
891
892
893
894
895 if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0
896 && (ahd_check_cmdcmpltqueues(ahd) != 0))
897 intstat = CMDCMPLT;
898 else
899 intstat = ahd_inb(ahd, INTSTAT);
900
901 if ((intstat & INT_PEND) == 0)
902 return (0);
903
904 if (intstat & CMDCMPLT) {
905 ahd_outb(ahd, CLRINT, CLRCMDINT);
906
907
908
909
910
911
912
913
914
915 if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
916 if (ahd_is_paused(ahd)) {
917
918
919
920
921
922 if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)
923 intstat |= SEQINT;
924 }
925 } else {
926 ahd_flush_device_writes(ahd);
927 }
928 ahd_run_qoutfifo(ahd);
929 ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;
930 ahd->cmdcmplt_total++;
931#ifdef AHD_TARGET_MODE
932 if ((ahd->flags & AHD_TARGETROLE) != 0)
933 ahd_run_tqinfifo(ahd, FALSE);
934#endif
935 }
936
937
938
939
940
941 if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {
942
943 } else if (intstat & HWERRINT) {
944 ahd_handle_hwerrint(ahd);
945 } else if ((intstat & (PCIINT|SPLTINT)) != 0) {
946 ahd->bus_intr(ahd);
947 } else {
948
949 if ((intstat & SEQINT) != 0)
950 ahd_handle_seqint(ahd, intstat);
951
952 if ((intstat & SCSIINT) != 0)
953 ahd_handle_scsiint(ahd, intstat);
954 }
955 return (1);
956}
957
958#endif
959