1/* $NetBSD: advlib.c,v 1.27 2010/11/13 13:52:00 uebayasi Exp $ */
2
3/*
4 * Low level routines for the Advanced Systems Inc. SCSI controllers chips
5 *
6 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * Author: Baldassare Dante Profeta <dante@mclink.it>
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39/*
40 * Ported from:
41 */
42/*
43 * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
44 *
45 * Copyright (c) 1995-1998 Advanced System Products, Inc.
46 * All Rights Reserved.
47 *
48 * Redistribution and use in source and binary forms, with or without
49 * modification, are permitted provided that redistributions of source
50 * code retain the above copyright notice and this comment without
51 * modification.
52 *
53 */
54
55#include <sys/cdefs.h>
56__KERNEL_RCSID(0, "$NetBSD: advlib.c,v 1.27 2010/11/13 13:52:00 uebayasi Exp $");
57
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/malloc.h>
61#include <sys/kernel.h>
62#include <sys/queue.h>
63#include <sys/device.h>
64
65#include <sys/bus.h>
66#include <sys/intr.h>
67
68#include <dev/scsipi/scsi_all.h>
69#include <dev/scsipi/scsipi_all.h>
70#include <dev/scsipi/scsiconf.h>
71
72#include <dev/ic/advlib.h>
73#include <dev/ic/adv.h>
74#include <dev/ic/advmcode.h>
75
76
77/* #define ASC_DEBUG */
78
79/******************************************************************************/
80/* Static functions */
81/******************************************************************************/
82
83/* Initialization routines */
84static u_int32_t AscLoadMicroCode(bus_space_tag_t, bus_space_handle_t,
85 u_int16_t, const u_int16_t *, u_int16_t);
86static void AscInitLram(ASC_SOFTC *);
87static void AscInitQLinkVar(ASC_SOFTC *);
88static int AscResetChipAndScsiBus(bus_space_tag_t, bus_space_handle_t);
89static u_int16_t AscGetChipBusType(bus_space_tag_t, bus_space_handle_t);
90#if 0
91static u_int16_t AscGetEisaChipCfg(bus_space_tag_t, bus_space_handle_t);
92#endif
93
94/* Chip register routines */
95static void AscSetBank(bus_space_tag_t, bus_space_handle_t, u_int8_t);
96
97/* RISC Chip routines */
98static int AscStartChip(bus_space_tag_t, bus_space_handle_t);
99static int AscStopChip(bus_space_tag_t, bus_space_handle_t);
100static u_int8_t AscSetChipScsiID(bus_space_tag_t, bus_space_handle_t, u_int8_t);
101static u_int8_t AscGetChipScsiCtrl(bus_space_tag_t, bus_space_handle_t);
102static int AscSetRunChipSynRegAtID(bus_space_tag_t, bus_space_handle_t,
103 u_int8_t, u_int8_t);
104static int AscSetChipSynRegAtID(bus_space_tag_t, bus_space_handle_t,
105 u_int8_t, u_int8_t);
106static int AscHostReqRiscHalt(bus_space_tag_t, bus_space_handle_t);
107static int AscIsChipHalted(bus_space_tag_t, bus_space_handle_t);
108static void AscSetChipIH(bus_space_tag_t, bus_space_handle_t, u_int16_t);
109
110/* Lram routines */
111static u_int8_t AscReadLramByte(bus_space_tag_t, bus_space_handle_t, u_int16_t);
112static void AscWriteLramByte(bus_space_tag_t, bus_space_handle_t,
113 u_int16_t, u_int8_t);
114static u_int16_t AscReadLramWord(bus_space_tag_t, bus_space_handle_t,
115 u_int16_t);
116static void AscWriteLramWord(bus_space_tag_t, bus_space_handle_t,
117 u_int16_t, u_int16_t);
118static u_int32_t AscReadLramDWord(bus_space_tag_t, bus_space_handle_t,
119 u_int16_t);
120static void AscWriteLramDWord(bus_space_tag_t, bus_space_handle_t,
121 u_int16_t, u_int32_t);
122static void AscMemWordSetLram(bus_space_tag_t, bus_space_handle_t,
123 u_int16_t, u_int16_t, int);
124static void AscMemWordCopyToLram(bus_space_tag_t, bus_space_handle_t,
125 u_int16_t, const u_int16_t *, int);
126static void AscMemWordCopyFromLram(bus_space_tag_t, bus_space_handle_t,
127 u_int16_t, u_int16_t *, int);
128static void AscMemDWordCopyToLram(bus_space_tag_t, bus_space_handle_t,
129 u_int16_t, u_int32_t *, int);
130static u_int32_t AscMemSumLramWord(bus_space_tag_t, bus_space_handle_t,
131 u_int16_t, int);
132static int AscTestExternalLram(bus_space_tag_t, bus_space_handle_t);
133
134/* MicroCode routines */
135static u_int16_t AscInitMicroCodeVar(ASC_SOFTC *);
136
137/* EEProm routines */
138static int AscWriteEEPCmdReg(bus_space_tag_t, bus_space_handle_t, u_int8_t);
139static int AscWriteEEPDataReg(bus_space_tag_t, bus_space_handle_t, u_int16_t);
140static void AscWaitEEPRead(void);
141static void AscWaitEEPWrite(void);
142static u_int16_t AscReadEEPWord(bus_space_tag_t, bus_space_handle_t, u_int8_t);
143static u_int16_t AscWriteEEPWord(bus_space_tag_t, bus_space_handle_t,
144 u_int8_t, u_int16_t);
145static u_int16_t AscGetEEPConfig(bus_space_tag_t, bus_space_handle_t,
146 ASCEEP_CONFIG *, u_int16_t);
147static int AscSetEEPConfig(bus_space_tag_t, bus_space_handle_t,
148 ASCEEP_CONFIG *, u_int16_t);
149static int AscSetEEPConfigOnce(bus_space_tag_t, bus_space_handle_t,
150 ASCEEP_CONFIG *, u_int16_t);
151#ifdef ASC_DEBUG
152static void AscPrintEEPConfig(ASCEEP_CONFIG *, u_int16_t);
153#endif
154
155/* Interrupt routines */
156static void AscIsrChipHalted(ASC_SOFTC *);
157static int AscIsrQDone(ASC_SOFTC *);
158static int AscWaitTixISRDone(ASC_SOFTC *, u_int8_t);
159static int AscWaitISRDone(ASC_SOFTC *);
160static u_int8_t _AscCopyLramScsiDoneQ(bus_space_tag_t, bus_space_handle_t,
161 u_int16_t, ASC_QDONE_INFO *, u_int32_t);
162static void AscGetQDoneInfo(bus_space_tag_t, bus_space_handle_t, u_int16_t,
163 ASC_QDONE_INFO *);
164static void AscToggleIRQAct(bus_space_tag_t, bus_space_handle_t);
165static void AscDisableInterrupt(bus_space_tag_t, bus_space_handle_t);
166static void AscEnableInterrupt(bus_space_tag_t, bus_space_handle_t);
167static u_int8_t AscSetChipIRQ(bus_space_tag_t, bus_space_handle_t,
168 u_int8_t, u_int16_t);
169static void AscAckInterrupt(bus_space_tag_t, bus_space_handle_t);
170static u_int32_t AscGetMaxDmaCount(u_int16_t);
171static u_int16_t AscSetIsaDmaChannel(bus_space_tag_t, bus_space_handle_t,
172 u_int16_t);
173static u_int8_t AscGetIsaDmaSpeed(bus_space_tag_t, bus_space_handle_t);
174static u_int8_t AscSetIsaDmaSpeed(bus_space_tag_t, bus_space_handle_t,
175 u_int8_t);
176
177/* Messages routines */
178static void AscHandleExtMsgIn(ASC_SOFTC *, u_int16_t, u_int8_t,
179 ASC_SCSI_BIT_ID_TYPE, int, u_int8_t);
180static u_int8_t AscMsgOutSDTR(ASC_SOFTC *, u_int8_t, u_int8_t);
181
182/* SDTR routines */
183static void AscSetChipSDTR(bus_space_tag_t, bus_space_handle_t,
184 u_int8_t, u_int8_t);
185static u_int8_t AscCalSDTRData(ASC_SOFTC *, u_int8_t, u_int8_t);
186static u_int8_t AscGetSynPeriodIndex(ASC_SOFTC *, u_int8_t);
187
188/* Queue routines */
189static int AscSendScsiQueue(ASC_SOFTC *, ASC_SCSI_Q *, u_int8_t);
190static int AscSgListToQueue(int);
191static u_int AscGetNumOfFreeQueue(ASC_SOFTC *, u_int8_t, u_int8_t);
192static int AscPutReadyQueue(ASC_SOFTC *, ASC_SCSI_Q *, u_int8_t);
193static void AscPutSCSIQ(bus_space_tag_t, bus_space_handle_t,
194 u_int16_t, ASC_SCSI_Q *);
195static int AscPutReadySgListQueue(ASC_SOFTC *, ASC_SCSI_Q *, u_int8_t);
196static u_int8_t AscAllocFreeQueue(bus_space_tag_t, bus_space_handle_t,
197 u_int8_t);
198static u_int8_t AscAllocMultipleFreeQueue(bus_space_tag_t, bus_space_handle_t,
199 u_int8_t, u_int8_t);
200static int AscStopQueueExe(bus_space_tag_t, bus_space_handle_t);
201static void AscStartQueueExe(bus_space_tag_t, bus_space_handle_t);
202static void AscCleanUpBusyQueue(bus_space_tag_t, bus_space_handle_t);
203static int _AscWaitQDone(bus_space_tag_t, bus_space_handle_t,
204 ASC_SCSI_Q *);
205static int AscCleanUpDiscQueue(bus_space_tag_t, bus_space_handle_t);
206
207/* Abort and Reset CCB routines */
208static int AscRiscHaltedAbortCCB(ASC_SOFTC *, ADV_CCB *);
209static int AscRiscHaltedAbortTIX(ASC_SOFTC *, u_int8_t);
210
211/* Error Handling routines */
212static int AscSetLibErrorCode(ASC_SOFTC *, u_int16_t);
213
214/* Handle bugged borads routines */
215static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *);
216static void AscAsyncFix(ASC_SOFTC *, u_int8_t, ASC_SCSI_INQUIRY *);
217
218/* Miscellaneous routines */
219static int AscCompareString(const u_char *, const u_char *, int);
220
221/* Device oriented routines */
222static int DvcEnterCritical(void);
223static void DvcLeaveCritical(int);
224static void DvcSleepMilliSecond(u_int32_t);
225#if 0
226static void DvcDelayMicroSecond(u_int32_t);
227#endif
228static void DvcDelayNanoSecond(u_int32_t);
229
230
231/******************************************************************************/
232/* Initialization routines */
233/******************************************************************************/
234
235/*
236 * This function perform the following steps:
237 * - initialize ASC_SOFTC structure with defaults values.
238 * - inquire board registers to know what kind of board it is.
239 * - keep track of bugged borads.
240 */
241void
242AscInitASC_SOFTC(ASC_SOFTC *sc)
243{
244 bus_space_tag_t iot = sc->sc_iot;
245 bus_space_handle_t ioh = sc->sc_ioh;
246 int i;
247
248
249 ASC_SET_CHIP_CONTROL(iot, ioh, ASC_CC_HALT);
250 ASC_SET_CHIP_STATUS(iot, ioh, 0);
251
252 sc->bug_fix_cntl = 0;
253 sc->pci_fix_asyn_xfer = 0;
254 sc->pci_fix_asyn_xfer_always = 0;
255 sc->sdtr_done = 0;
256 sc->cur_total_qng = 0;
257 sc->last_q_shortage = 0;
258 sc->use_tagged_qng = 0;
259 sc->unit_not_ready = 0;
260 sc->queue_full_or_busy = 0;
261 sc->host_init_sdtr_index = 0;
262 sc->can_tagged_qng = 0;
263 sc->cmd_qng_enabled = 0;
264 sc->dvc_cntl = ASC_DEF_DVC_CNTL;
265 sc->init_sdtr = 0;
266 sc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
267 sc->scsi_reset_wait = 3;
268 sc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
269 sc->max_dma_count = AscGetMaxDmaCount(sc->bus_type);
270 sc->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
271 sc->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
272 sc->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
273 sc->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
274 sc->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | ASC_LIB_VERSION_MINOR;
275 if ((sc->bus_type & ASC_IS_PCI) &&
276 (sc->chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
277 sc->bus_type = ASC_IS_PCI_ULTRA;
278 sc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
279 sc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
280 sc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
281 sc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
282 sc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
283 sc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
284 sc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
285 sc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
286 sc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
287 sc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
288 sc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
289 sc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
290 sc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
291 sc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
292 sc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
293 sc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
294 sc->max_sdtr_index = 15;
295 if (sc->chip_version == ASC_CHIP_VER_PCI_ULTRA_3150)
296 ASC_SET_EXTRA_CONTROL(iot, ioh,
297 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
298 else if (sc->chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050)
299 ASC_SET_EXTRA_CONTROL(iot, ioh,
300 (SEC_ACTIVE_NEGATE | SEC_ENABLE_FILTER));
301 } else {
302 sc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
303 sc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
304 sc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
305 sc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
306 sc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
307 sc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
308 sc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
309 sc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
310 sc->max_sdtr_index = 7;
311 }
312
313 if (sc->bus_type == ASC_IS_PCI)
314 ASC_SET_EXTRA_CONTROL(iot, ioh,
315 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
316
317 sc->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
318 if (AscGetChipBusType(iot, ioh) == ASC_IS_ISAPNP) {
319 ASC_SET_CHIP_IFC(iot, ioh, ASC_IFC_INIT_DEFAULT);
320 sc->bus_type = ASC_IS_ISAPNP;
321 }
322 if ((sc->bus_type & ASC_IS_ISA) != 0)
323 sc->isa_dma_channel = AscGetIsaDmaChannel(iot, ioh);
324
325 for (i = 0; i <= ASC_MAX_TID; i++) {
326 sc->cur_dvc_qng[i] = 0;
327 sc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
328 sc->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
329 }
330}
331
332
333/*
334 * This function initialize some ASC_SOFTC fields with values read from
335 * on-board EEProm.
336 */
337int16_t
338AscInitFromEEP(ASC_SOFTC *sc)
339{
340 bus_space_tag_t iot = sc->sc_iot;
341 bus_space_handle_t ioh = sc->sc_ioh;
342 ASCEEP_CONFIG eep_config_buf;
343 ASCEEP_CONFIG *eep_config;
344 u_int16_t chksum;
345 u_int16_t warn_code;
346 u_int16_t cfg_msw, cfg_lsw;
347 int i;
348 int write_eep = 0;
349
350
351 warn_code = 0;
352 AscWriteLramWord(iot, ioh, ASCV_HALTCODE_W, 0x00FE);
353 AscStopQueueExe(iot, ioh);
354
355 AscStopChip(iot, ioh);
356 AscResetChipAndScsiBus(iot, ioh);
357 DvcSleepMilliSecond(sc->scsi_reset_wait * 1000);
358
359 if ((AscStopChip(iot, ioh) == FALSE) ||
360 (AscGetChipScsiCtrl(iot, ioh) != 0)) {
361 AscResetChipAndScsiBus(iot, ioh);
362 DvcSleepMilliSecond(sc->scsi_reset_wait * 1000);
363 }
364 if (AscIsChipHalted(iot, ioh) == FALSE)
365 return (-1);
366
367 ASC_SET_PC_ADDR(iot, ioh, ASC_MCODE_START_ADDR);
368 if (ASC_GET_PC_ADDR(iot, ioh) != ASC_MCODE_START_ADDR)
369 return (-2);
370
371 eep_config = &eep_config_buf;
372 cfg_msw = ASC_GET_CHIP_CFG_MSW(iot, ioh);
373 cfg_lsw = ASC_GET_CHIP_CFG_LSW(iot, ioh);
374 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
375 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
376 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
377 ASC_SET_CHIP_CFG_MSW(iot, ioh, cfg_msw);
378 }
379 chksum = AscGetEEPConfig(iot, ioh, eep_config, sc->bus_type);
380#ifdef ASC_DEBUG
381 AscPrintEEPConfig(eep_config, chksum);
382#endif
383 if (chksum == 0)
384 chksum = 0xAA55;
385
386 if (ASC_GET_CHIP_STATUS(iot, ioh) & ASC_CSW_AUTO_CONFIG) {
387 warn_code |= ASC_WARN_AUTO_CONFIG;
388 if (sc->chip_version == 3) {
389 if (eep_config->cfg_lsw != cfg_lsw) {
390 warn_code |= ASC_WARN_EEPROM_RECOVER;
391 eep_config->cfg_lsw = ASC_GET_CHIP_CFG_LSW(iot, ioh);
392 }
393 if (eep_config->cfg_msw != cfg_msw) {
394 warn_code |= ASC_WARN_EEPROM_RECOVER;
395 eep_config->cfg_msw = ASC_GET_CHIP_CFG_MSW(iot, ioh);
396 }
397 }
398 }
399 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
400 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
401
402 if (chksum != eep_config->chksum) {
403 if (sc->chip_version == ASC_CHIP_VER_PCI_ULTRA_3050) {
404 eep_config->init_sdtr = 0xFF;
405 eep_config->disc_enable = 0xFF;
406 eep_config->start_motor = 0xFF;
407 eep_config->use_cmd_qng = 0;
408 eep_config->max_total_qng = 0xF0;
409 eep_config->max_tag_qng = 0x20;
410 eep_config->cntl = 0xBFFF;
411 eep_config->chip_scsi_id = 7;
412 eep_config->no_scam = 0;
413 eep_config->adapter_info[0] = 0;
414 eep_config->adapter_info[1] = 0;
415 eep_config->adapter_info[2] = 0;
416 eep_config->adapter_info[3] = 0;
417#if BYTE_ORDER == BIG_ENDIAN
418 eep_config->adapter_info[5] = 0;
419 /* Indicate EEPROM-less board. */
420 eep_config->adapter_info[4] = 0xBB;
421#else
422 eep_config->adapter_info[4] = 0;
423 /* Indicate EEPROM-less board. */
424 eep_config->adapter_info[5] = 0xBB;
425#endif
426 } else {
427 write_eep = 1;
428 warn_code |= ASC_WARN_EEPROM_CHKSUM;
429 }
430 }
431 sc->sdtr_enable = eep_config->init_sdtr;
432 sc->disc_enable = eep_config->disc_enable;
433 sc->cmd_qng_enabled = eep_config->use_cmd_qng;
434 sc->isa_dma_speed = eep_config->isa_dma_speed;
435 sc->start_motor = eep_config->start_motor;
436 sc->dvc_cntl = eep_config->cntl;
437#if BYTE_ORDER == BIG_ENDIAN
438 sc->adapter_info[0] = eep_config->adapter_info[1];
439 sc->adapter_info[1] = eep_config->adapter_info[0];
440 sc->adapter_info[2] = eep_config->adapter_info[3];
441 sc->adapter_info[3] = eep_config->adapter_info[2];
442 sc->adapter_info[4] = eep_config->adapter_info[5];
443 sc->adapter_info[5] = eep_config->adapter_info[4];
444#else
445 sc->adapter_info[0] = eep_config->adapter_info[0];
446 sc->adapter_info[1] = eep_config->adapter_info[1];
447 sc->adapter_info[2] = eep_config->adapter_info[2];
448 sc->adapter_info[3] = eep_config->adapter_info[3];
449 sc->adapter_info[4] = eep_config->adapter_info[4];
450 sc->adapter_info[5] = eep_config->adapter_info[5];
451#endif
452
453 if (!AscTestExternalLram(iot, ioh)) {
454 if (((sc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA)) {
455 eep_config->max_total_qng = ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
456 eep_config->max_tag_qng = ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
457 } else {
458 eep_config->cfg_msw |= 0x0800;
459 cfg_msw |= 0x0800;
460 ASC_SET_CHIP_CFG_MSW(iot, ioh, cfg_msw);
461 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
462 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
463 }
464 }
465 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG)
466 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
467
468 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG)
469 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
470
471 if (eep_config->max_tag_qng > eep_config->max_total_qng)
472 eep_config->max_tag_qng = eep_config->max_total_qng;
473
474 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC)
475 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
476
477 sc->max_total_qng = eep_config->max_total_qng;
478 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
479 eep_config->use_cmd_qng) {
480 eep_config->disc_enable = eep_config->use_cmd_qng;
481 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
482 }
483 if (sc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA))
484 sc->irq_no = AscGetChipIRQ(iot, ioh, sc->bus_type);
485
486 eep_config->chip_scsi_id &= ASC_MAX_TID;
487 sc->chip_scsi_id = eep_config->chip_scsi_id;
488 if (((sc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
489 !(sc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
490 sc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
491 }
492 for (i = 0; i <= ASC_MAX_TID; i++) {
493 sc->max_tag_qng[i] = eep_config->max_tag_qng;
494 sc->sdtr_period_offset[i] = ASC_DEF_SDTR_OFFSET |
495 (sc->host_init_sdtr_index << 4);
496 }
497
498 eep_config->cfg_msw = ASC_GET_CHIP_CFG_MSW(iot, ioh);
499 if (write_eep) {
500 AscSetEEPConfig(iot, ioh, eep_config, sc->bus_type);
501#ifdef ASC_DEBUG
502 AscPrintEEPConfig(eep_config, 0);
503#endif
504 }
505
506 return (warn_code);
507}
508
509
510u_int16_t
511AscInitFromASC_SOFTC(ASC_SOFTC *sc)
512{
513 bus_space_tag_t iot = sc->sc_iot;
514 bus_space_handle_t ioh = sc->sc_ioh;
515 u_int16_t cfg_msw;
516 u_int16_t warn_code;
517 u_int16_t pci_device_id = sc->pci_device_id;
518
519
520 warn_code = 0;
521 cfg_msw = ASC_GET_CHIP_CFG_MSW(iot, ioh);
522
523 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
524 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
525 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
526 ASC_SET_CHIP_CFG_MSW(iot, ioh, cfg_msw);
527 }
528 if ((sc->cmd_qng_enabled & sc->disc_enable) != sc->cmd_qng_enabled) {
529 sc->disc_enable = sc->cmd_qng_enabled;
530 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
531 }
532 if (ASC_GET_CHIP_STATUS(iot, ioh) & ASC_CSW_AUTO_CONFIG) {
533 warn_code |= ASC_WARN_AUTO_CONFIG;
534 }
535 if ((sc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
536 AscSetChipIRQ(iot, ioh, sc->irq_no, sc->bus_type);
537 }
538 if (sc->bus_type & ASC_IS_PCI) {
539 cfg_msw &= 0xFFC0;
540 ASC_SET_CHIP_CFG_MSW(iot, ioh, cfg_msw);
541
542 if ((sc->bus_type & ASC_IS_PCI_ULTRA) != ASC_IS_PCI_ULTRA) {
543 if ((pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
544 (pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
545 sc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
546 sc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
547 }
548 }
549 } else if (sc->bus_type == ASC_IS_ISAPNP) {
550 if (sc->chip_version == ASC_CHIP_VER_ASYN_BUG) {
551 sc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
552 }
553 }
554 AscSetChipScsiID(iot, ioh, sc->chip_scsi_id);
555
556 if (sc->bus_type & ASC_IS_ISA) {
557 AscSetIsaDmaChannel(iot, ioh, sc->isa_dma_channel);
558 AscSetIsaDmaSpeed(iot, ioh, sc->isa_dma_speed);
559 }
560 return (warn_code);
561}
562
563
564/*
565 * - Initialize RISC chip
566 * - Initialize Lram
567 * - Load uCode into Lram
568 * - Enable Interrupts
569 */
570int
571AscInitDriver(ASC_SOFTC *sc)
572{
573 bus_space_tag_t iot = sc->sc_iot;
574 bus_space_handle_t ioh = sc->sc_ioh;
575 u_int32_t chksum;
576
577
578 if (!AscFindSignature(iot, ioh))
579 return (1);
580
581 AscDisableInterrupt(iot, ioh);
582
583 AscInitLram(sc);
584 chksum = AscLoadMicroCode(iot, ioh, 0, (const u_int16_t *) asc_mcode,
585 asc_mcode_size);
586 if (chksum != asc_mcode_chksum)
587 return (2);
588
589 if (AscInitMicroCodeVar(sc) == 0)
590 return (3);
591
592 AscEnableInterrupt(iot, ioh);
593
594 return (0);
595}
596
597
598int
599AscFindSignature(bus_space_tag_t iot, bus_space_handle_t ioh)
600{
601 u_int16_t sig_word;
602
603 if (ASC_GET_CHIP_SIGNATURE_BYTE(iot, ioh) == ASC_1000_ID1B) {
604 sig_word = ASC_GET_CHIP_SIGNATURE_WORD(iot, ioh);
605 if (sig_word == ASC_1000_ID0W ||
606 sig_word == ASC_1000_ID0W_FIX)
607 return (1);
608 }
609 return (0);
610}
611
612
613static void
614AscInitLram(ASC_SOFTC *sc)
615{
616 bus_space_tag_t iot = sc->sc_iot;
617 bus_space_handle_t ioh = sc->sc_ioh;
618 u_int8_t i;
619 u_int16_t s_addr;
620
621
622 AscMemWordSetLram(iot, ioh, ASC_QADR_BEG, 0,
623 (((sc->max_total_qng + 2 + 1) * 64) >> 1));
624
625 i = ASC_MIN_ACTIVE_QNO;
626 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
627 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_FWD, i + 1);
628 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_BWD, sc->max_total_qng);
629 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_QNO, i);
630 i++;
631 s_addr += ASC_QBLK_SIZE;
632 for (; i < sc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
633 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_FWD, i + 1);
634 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_BWD, i - 1);
635 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_QNO, i);
636 }
637 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_FWD, ASC_QLINK_END);
638 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_BWD, sc->max_total_qng - 1);
639 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_QNO, sc->max_total_qng);
640 i++;
641 s_addr += ASC_QBLK_SIZE;
642 for (; i <= (u_int8_t) (sc->max_total_qng + 3); i++, s_addr += ASC_QBLK_SIZE) {
643 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_FWD, i);
644 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_BWD, i);
645 AscWriteLramByte(iot, ioh, s_addr + ASC_SCSIQ_B_QNO, i);
646 }
647}
648
649
650void
651AscReInitLram(ASC_SOFTC *sc)
652{
653
654 AscInitLram(sc);
655 AscInitQLinkVar(sc);
656}
657
658
659static void
660AscInitQLinkVar(ASC_SOFTC *sc)
661{
662 bus_space_tag_t iot = sc->sc_iot;
663 bus_space_handle_t ioh = sc->sc_ioh;
664 u_int8_t i;
665 u_int16_t lram_addr;
666
667
668 ASC_PUT_RISC_VAR_FREE_QHEAD(iot, ioh, 1);
669 ASC_PUT_RISC_VAR_DONE_QTAIL(iot, ioh, sc->max_total_qng);
670 ASC_PUT_VAR_FREE_QHEAD(iot, ioh, 1);
671 ASC_PUT_VAR_DONE_QTAIL(iot, ioh, sc->max_total_qng);
672 AscWriteLramByte(iot, ioh, ASCV_BUSY_QHEAD_B, sc->max_total_qng + 1);
673 AscWriteLramByte(iot, ioh, ASCV_DISC1_QHEAD_B, sc->max_total_qng + 2);
674 AscWriteLramByte(iot, ioh, ASCV_TOTAL_READY_Q_B, sc->max_total_qng);
675 AscWriteLramWord(iot, ioh, ASCV_ASCDVC_ERR_CODE_W, 0);
676 AscWriteLramWord(iot, ioh, ASCV_HALTCODE_W, 0);
677 AscWriteLramByte(iot, ioh, ASCV_STOP_CODE_B, 0);
678 AscWriteLramByte(iot, ioh, ASCV_SCSIBUSY_B, 0);
679 AscWriteLramByte(iot, ioh, ASCV_WTM_FLAG_B, 0);
680 ASC_PUT_QDONE_IN_PROGRESS(iot, ioh, 0);
681 lram_addr = ASC_QADR_BEG;
682 for (i = 0; i < 32; i++, lram_addr += 2)
683 AscWriteLramWord(iot, ioh, lram_addr, 0);
684}
685
686
687static int
688AscResetChipAndScsiBus(bus_space_tag_t iot, bus_space_handle_t ioh)
689{
690 while (ASC_GET_CHIP_STATUS(iot, ioh) & ASC_CSW_SCSI_RESET_ACTIVE);
691
692 AscStopChip(iot, ioh);
693 ASC_SET_CHIP_CONTROL(iot, ioh, ASC_CC_CHIP_RESET | ASC_CC_SCSI_RESET | ASC_CC_HALT);
694
695 DvcDelayNanoSecond(60000);
696
697 AscSetChipIH(iot, ioh, ASC_INS_RFLAG_WTM);
698 AscSetChipIH(iot, ioh, ASC_INS_HALT);
699 ASC_SET_CHIP_CONTROL(iot, ioh, ASC_CC_CHIP_RESET | ASC_CC_HALT);
700 ASC_SET_CHIP_CONTROL(iot, ioh, ASC_CC_HALT);
701
702 DvcSleepMilliSecond(200);
703
704 ASC_SET_CHIP_STATUS(iot, ioh, ASC_CIW_CLR_SCSI_RESET_INT);
705 ASC_SET_CHIP_STATUS(iot, ioh, 0);
706
707 DvcSleepMilliSecond(200);
708
709 return (AscIsChipHalted(iot, ioh));
710}
711
712
713static u_int16_t
714AscGetChipBusType(bus_space_tag_t iot, bus_space_handle_t ioh)
715{
716 u_int16_t chip_ver;
717
718 chip_ver = ASC_GET_CHIP_VER_NO(iot, ioh);
719#if 0
720 if ((chip_ver >= ASC_CHIP_MIN_VER_VL) &&
721 (chip_ver <= ASC_CHIP_MAX_VER_VL)) {
722 if(((ioh & 0x0C30) == 0x0C30) || ((ioh & 0x0C50) == 0x0C50)) {
723 return (ASC_IS_EISA);
724 }
725 else {
726 return (ASC_IS_VL);
727 }
728 }
729#endif
730 if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
731 (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
732 if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP)
733 return (ASC_IS_ISAPNP);
734
735 return (ASC_IS_ISA);
736 } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
737 (chip_ver <= ASC_CHIP_MAX_VER_PCI))
738 return (ASC_IS_PCI);
739
740 return (0);
741}
742
743/*
744static u_int16_t
745AscGetEisaChipCfg(bus_space_tag_t iot, bus_space_handle_t ioh)
746{
747 int eisa_cfg_iop;
748
749 eisa_cfg_iop = ASC_GET_EISA_SLOT(ioh) | (ASC_EISA_CFG_IOP_MASK);
750 return (inw(eisa_cfg_iop));
751}
752*/
753
754/******************************************************************************/
755/* Chip register routines */
756/******************************************************************************/
757
758
759static void
760AscSetBank(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t bank)
761{
762 u_int8_t val;
763
764 val = ASC_GET_CHIP_CONTROL(iot, ioh) &
765 (~(ASC_CC_SINGLE_STEP | ASC_CC_TEST |
766 ASC_CC_DIAG | ASC_CC_SCSI_RESET |
767 ASC_CC_CHIP_RESET));
768
769 switch (bank) {
770 case 1:
771 val |= ASC_CC_BANK_ONE;
772 break;
773
774 case 2:
775 val |= ASC_CC_DIAG | ASC_CC_BANK_ONE;
776 break;
777
778 default:
779 val &= ~ASC_CC_BANK_ONE;
780 }
781
782 ASC_SET_CHIP_CONTROL(iot, ioh, val);
783 return;
784}
785
786
787/******************************************************************************/
788/* Chip routines */
789/******************************************************************************/
790
791
792static int
793AscStartChip(bus_space_tag_t iot, bus_space_handle_t ioh)
794{
795 ASC_SET_CHIP_CONTROL(iot, ioh, 0);
796 if ((ASC_GET_CHIP_STATUS(iot, ioh) & ASC_CSW_HALTED) != 0)
797 return (0);
798
799 return (1);
800}
801
802
803static int
804AscStopChip(bus_space_tag_t iot, bus_space_handle_t ioh)
805{
806 u_int8_t cc_val;
807
808 cc_val = ASC_GET_CHIP_CONTROL(iot, ioh) &
809 (~(ASC_CC_SINGLE_STEP | ASC_CC_TEST | ASC_CC_DIAG));
810 ASC_SET_CHIP_CONTROL(iot, ioh, cc_val | ASC_CC_HALT);
811 AscSetChipIH(iot, ioh, ASC_INS_HALT);
812 AscSetChipIH(iot, ioh, ASC_INS_RFLAG_WTM);
813 if ((ASC_GET_CHIP_STATUS(iot, ioh) & ASC_CSW_HALTED) == 0)
814 return (0);
815
816 return (1);
817}
818
819
820static u_int8_t
821AscSetChipScsiID(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t new_id)
822{
823 u_int16_t cfg_lsw;
824
825 if (ASC_GET_CHIP_SCSI_ID(iot, ioh) == new_id)
826 return (new_id);
827
828 cfg_lsw = ASC_GET_CHIP_SCSI_ID(iot, ioh);
829 cfg_lsw &= 0xF8FF;
830 cfg_lsw |= (new_id & ASC_MAX_TID) << 8;
831 ASC_SET_CHIP_CFG_LSW(iot, ioh, cfg_lsw);
832 return (ASC_GET_CHIP_SCSI_ID(iot, ioh));
833}
834
835
836static u_int8_t
837AscGetChipScsiCtrl(bus_space_tag_t iot, bus_space_handle_t ioh)
838{
839 u_int8_t scsi_ctrl;
840
841 AscSetBank(iot, ioh, 1);
842 scsi_ctrl = bus_space_read_1(iot, ioh, ASC_IOP_REG_SC);
843 AscSetBank(iot, ioh, 0);
844 return (scsi_ctrl);
845}
846
847
848static int
849AscSetRunChipSynRegAtID(bus_space_tag_t iot, bus_space_handle_t ioh,
850 u_int8_t tid_no, u_int8_t sdtr_data)
851{
852 int retval = FALSE;
853
854 if (AscHostReqRiscHalt(iot, ioh)) {
855 retval = AscSetChipSynRegAtID(iot, ioh, tid_no, sdtr_data);
856 AscStartChip(iot, ioh);
857 }
858 return (retval);
859}
860
861
862static int
863AscSetChipSynRegAtID(bus_space_tag_t iot, bus_space_handle_t ioh,
864 u_int8_t id, u_int8_t sdtr_data)
865{
866 ASC_SCSI_BIT_ID_TYPE org_id;
867 int i;
868 int stax = TRUE;
869
870 AscSetBank(iot, ioh, 1);
871 org_id = ASC_READ_CHIP_DVC_ID(iot, ioh);
872 for (i = 0; i <= ASC_MAX_TID; i++)
873 if (org_id == (0x01 << i))
874 break;
875
876 org_id = i;
877 ASC_WRITE_CHIP_DVC_ID(iot, ioh, id);
878 if (ASC_READ_CHIP_DVC_ID(iot, ioh) == (0x01 << id)) {
879 AscSetBank(iot, ioh, 0);
880 ASC_SET_CHIP_SYN(iot, ioh, sdtr_data);
881 if (ASC_GET_CHIP_SYN(iot, ioh) != sdtr_data)
882 stax = FALSE;
883 } else
884 stax = FALSE;
885
886 AscSetBank(iot, ioh, 1);
887 ASC_WRITE_CHIP_DVC_ID(iot, ioh, org_id);
888 AscSetBank(iot, ioh, 0);
889 return (stax);
890}
891
892
893static int
894AscHostReqRiscHalt(bus_space_tag_t iot, bus_space_handle_t ioh)
895{
896 int count = 0;
897 int retval = 0;
898 u_int8_t saved_stop_code;
899
900
901 if (AscIsChipHalted(iot, ioh))
902 return (1);
903 saved_stop_code = AscReadLramByte(iot, ioh, ASCV_STOP_CODE_B);
904 AscWriteLramByte(iot, ioh, ASCV_STOP_CODE_B,
905 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
906
907 do {
908 if (AscIsChipHalted(iot, ioh)) {
909 retval = 1;
910 break;
911 }
912 DvcSleepMilliSecond(100);
913 } while (count++ < 20);
914
915 AscWriteLramByte(iot, ioh, ASCV_STOP_CODE_B, saved_stop_code);
916
917 return (retval);
918}
919
920
921static int
922AscIsChipHalted(bus_space_tag_t iot, bus_space_handle_t ioh)
923{
924 if ((ASC_GET_CHIP_STATUS(iot, ioh) & ASC_CSW_HALTED) != 0)
925 if ((ASC_GET_CHIP_CONTROL(iot, ioh) & ASC_CC_HALT) != 0)
926 return (1);
927
928 return (0);
929}
930
931
932static void
933AscSetChipIH(bus_space_tag_t iot, bus_space_handle_t ioh, u_int16_t ins_code)
934{
935 AscSetBank(iot, ioh, 1);
936 ASC_WRITE_CHIP_IH(iot, ioh, ins_code);
937 AscSetBank(iot, ioh, 0);
938
939 return;
940}
941
942
943/******************************************************************************/
944/* Lram routines */
945/******************************************************************************/
946
947
948static u_int8_t
949AscReadLramByte(bus_space_tag_t iot, bus_space_handle_t ioh, u_int16_t addr)
950{
951 u_int8_t byte_data;
952 u_int16_t word_data;
953
954
955 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, addr & 0xFFFE);
956 word_data = ASC_GET_CHIP_LRAM_DATA(iot, ioh);
957
958 if (addr & 1) {
959 /* odd address */
960 byte_data = (u_int8_t) ((word_data >> 8) & 0xFF);
961 } else {
962 /* even address */
963 byte_data = (u_int8_t) (word_data & 0xFF);
964 }
965
966 return (byte_data);
967}
968
969
970static void
971AscWriteLramByte(bus_space_tag_t iot, bus_space_handle_t ioh,
972 u_int16_t addr, u_int8_t data)
973{
974 u_int16_t word_data;
975
976
977 word_data = AscReadLramWord(iot, ioh, addr & 0xFFFE);
978
979 if (addr & 1) {
980 /* odd address */
981 word_data &= 0x00FF;
982 word_data |= (((u_int16_t) data) << 8) & 0xFF00;
983 } else {
984 /* even address */
985 word_data &= 0xFF00;
986 word_data |= ((u_int16_t) data) & 0x00FF;
987 }
988
989 AscWriteLramWord(iot, ioh, addr & 0xFFFE, word_data);
990}
991
992
993static u_int16_t
994AscReadLramWord(bus_space_tag_t iot, bus_space_handle_t ioh, u_int16_t addr)
995{
996
997 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, addr);
998 return (ASC_GET_CHIP_LRAM_DATA(iot, ioh));
999}
1000
1001
1002static void
1003AscWriteLramWord(bus_space_tag_t iot, bus_space_handle_t ioh,
1004 u_int16_t addr, u_int16_t data)
1005{
1006
1007 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, addr);
1008 ASC_SET_CHIP_LRAM_DATA(iot, ioh, data);
1009}
1010
1011
1012static u_int32_t
1013AscReadLramDWord(bus_space_tag_t iot, bus_space_handle_t ioh, u_int16_t addr)
1014{
1015 u_int16_t low_word, hi_word;
1016
1017
1018 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, addr);
1019 low_word = ASC_GET_CHIP_LRAM_DATA(iot, ioh);
1020 hi_word = ASC_GET_CHIP_LRAM_DATA(iot, ioh);
1021
1022 return ((((u_int32_t) hi_word) << 16) | (u_int32_t) low_word);
1023}
1024
1025
1026static void
1027AscWriteLramDWord(bus_space_tag_t iot, bus_space_handle_t ioh,
1028 u_int16_t addr, u_int32_t data)
1029{
1030
1031 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, addr);
1032 ASC_SET_CHIP_LRAM_DATA(iot, ioh, (u_int16_t) (data & 0x0000FFFF));
1033 ASC_SET_CHIP_LRAM_DATA(iot, ioh, (u_int16_t) (data >> 16));
1034}
1035
1036
1037static void
1038AscMemWordSetLram(bus_space_tag_t iot, bus_space_handle_t ioh,
1039 u_int16_t s_addr, u_int16_t s_words, int count)
1040{
1041 int i;
1042
1043 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, s_addr);
1044 for (i = 0; i < count; i++)
1045 ASC_SET_CHIP_LRAM_DATA(iot, ioh, s_words);
1046}
1047
1048
1049static void
1050AscMemWordCopyToLram(bus_space_tag_t iot, bus_space_handle_t ioh,
1051 u_int16_t s_addr, const u_int16_t *s_buffer, int words)
1052{
1053 int i;
1054
1055 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, s_addr);
1056 for (i = 0; i < words; i++, s_buffer++)
1057 ASC_SET_CHIP_LRAM_DATA_NO_SWAP(iot, ioh, *s_buffer);
1058}
1059
1060
1061static void
1062AscMemWordCopyFromLram(bus_space_tag_t iot, bus_space_handle_t ioh,
1063 u_int16_t s_addr, u_int16_t *s_buffer, int words)
1064{
1065 int i;
1066
1067 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, s_addr);
1068 for (i = 0; i < words; i++, s_buffer++)
1069 *s_buffer = ASC_GET_CHIP_LRAM_DATA_NO_SWAP(iot, ioh);
1070}
1071
1072
1073static void
1074AscMemDWordCopyToLram(bus_space_tag_t iot, bus_space_handle_t ioh,
1075 u_int16_t s_addr, u_int32_t *s_buffer, int dwords)
1076{
1077 int i;
1078 u_int32_t *pw;
1079
1080 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, s_addr);
1081
1082 pw = s_buffer;
1083 for (i = 0; i < dwords; i++, pw++) {
1084 ASC_SET_CHIP_LRAM_DATA(iot, ioh, LO_WORD(*pw));
1085 DELAY(1);
1086 ASC_SET_CHIP_LRAM_DATA(iot, ioh, HI_WORD(*pw));
1087 }
1088}
1089
1090
1091static u_int32_t
1092AscMemSumLramWord(bus_space_tag_t iot, bus_space_handle_t ioh,
1093 u_int16_t s_addr, int words)
1094{
1095 u_int32_t sum = 0L;
1096 u_int16_t i;
1097
1098
1099 for (i = 0; i < words; i++, s_addr += 2)
1100 sum += AscReadLramWord(iot, ioh, s_addr);
1101
1102 return (sum);
1103}
1104
1105
1106static int
1107AscTestExternalLram(bus_space_tag_t iot, bus_space_handle_t ioh)
1108{
1109 u_int16_t q_addr;
1110 u_int16_t saved_word;
1111 int retval;
1112
1113
1114 retval = 0;
1115 q_addr = ASC_QNO_TO_QADDR(241);
1116 saved_word = AscReadLramWord(iot, ioh, q_addr);
1117 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, q_addr);
1118 ASC_SET_CHIP_LRAM_DATA(iot, ioh, 0x55AA);
1119 DvcSleepMilliSecond(10);
1120 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, q_addr);
1121
1122 if (ASC_GET_CHIP_LRAM_DATA(iot, ioh) == 0x55AA) {
1123 retval = 1;
1124 AscWriteLramWord(iot, ioh, q_addr, saved_word);
1125 }
1126 return (retval);
1127}
1128
1129
1130/******************************************************************************/
1131/* MicroCode routines */
1132/******************************************************************************/
1133
1134
1135static u_int16_t
1136AscInitMicroCodeVar(ASC_SOFTC *sc)
1137{
1138 bus_space_tag_t iot = sc->sc_iot;
1139 bus_space_handle_t ioh = sc->sc_ioh;
1140 u_int32_t phy_addr;
1141 int i;
1142
1143
1144 for (i = 0; i <= ASC_MAX_TID; i++)
1145 ASC_PUT_MCODE_INIT_SDTR_AT_ID(iot, ioh, i,
1146 sc->sdtr_period_offset[i]);
1147
1148 AscInitQLinkVar(sc);
1149 AscWriteLramByte(iot, ioh, ASCV_DISC_ENABLE_B, sc->disc_enable);
1150 AscWriteLramByte(iot, ioh, ASCV_HOSTSCSI_ID_B,
1151 ASC_TID_TO_TARGET_ID(sc->chip_scsi_id));
1152
1153 phy_addr = (sc->overrun_buf & 0xfffffff8) + 8;
1154 AscWriteLramDWord(iot, ioh, ASCV_OVERRUN_PADDR_D, phy_addr);
1155 AscWriteLramDWord(iot, ioh, ASCV_OVERRUN_BSIZE_D,
1156 ASC_OVERRUN_BSIZE - 8);
1157
1158 sc->mcode_date = AscReadLramWord(iot, ioh, ASCV_MC_DATE_W);
1159 sc->mcode_version = AscReadLramWord(iot, ioh, ASCV_MC_VER_W);
1160 ASC_SET_PC_ADDR(iot, ioh, ASC_MCODE_START_ADDR);
1161
1162 if (ASC_GET_PC_ADDR(iot, ioh) != ASC_MCODE_START_ADDR) {
1163 return (0);
1164 }
1165 if (AscStartChip(iot, ioh) != 1) {
1166 return (0);
1167 }
1168 return (1);
1169}
1170
1171
1172static u_int32_t
1173AscLoadMicroCode(bus_space_tag_t iot, bus_space_handle_t ioh,
1174 u_int16_t s_addr, const u_int16_t *mcode_buf, u_int16_t mcode_size)
1175{
1176 u_int32_t chksum;
1177 u_int16_t mcode_word_size;
1178 u_int16_t mcode_chksum;
1179
1180 mcode_word_size = mcode_size >> 1;
1181 /* clear board memory */
1182 AscMemWordSetLram(iot, ioh, s_addr, 0, mcode_word_size);
1183 /* copy uCode to board memory */
1184 AscMemWordCopyToLram(iot, ioh, s_addr, mcode_buf, mcode_word_size);
1185 chksum = AscMemSumLramWord(iot, ioh, s_addr, mcode_word_size);
1186 mcode_chksum = AscMemSumLramWord(iot, ioh, ASC_CODE_SEC_BEG,
1187 ((mcode_size - s_addr - ASC_CODE_SEC_BEG) >> 1));
1188 AscWriteLramWord(iot, ioh, ASCV_MCODE_CHKSUM_W, mcode_chksum);
1189 AscWriteLramWord(iot, ioh, ASCV_MCODE_SIZE_W, mcode_size);
1190
1191 return (chksum);
1192}
1193
1194
1195/******************************************************************************/
1196/* EEProm routines */
1197/******************************************************************************/
1198
1199
1200static int
1201AscWriteEEPCmdReg(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t cmd_reg)
1202{
1203 u_int8_t read_back;
1204 int retry;
1205
1206 retry = 0;
1207
1208 while (TRUE) {
1209 ASC_SET_CHIP_EEP_CMD(iot, ioh, cmd_reg);
1210 DvcSleepMilliSecond(1);
1211 read_back = ASC_GET_CHIP_EEP_CMD(iot, ioh);
1212 if (read_back == cmd_reg)
1213 return (1);
1214
1215 if (retry++ > ASC_EEP_MAX_RETRY)
1216 return (0);
1217 }
1218}
1219
1220
1221static int
1222AscWriteEEPDataReg(bus_space_tag_t iot, bus_space_handle_t ioh,
1223 u_int16_t data_reg)
1224{
1225 u_int16_t read_back;
1226 int retry;
1227
1228 retry = 0;
1229 while (TRUE) {
1230 ASC_SET_CHIP_EEP_DATA(iot, ioh, data_reg);
1231 DvcSleepMilliSecond(1);
1232 read_back = ASC_GET_CHIP_EEP_DATA(iot, ioh);
1233 if (read_back == data_reg)
1234 return (1);
1235
1236 if (retry++ > ASC_EEP_MAX_RETRY)
1237 return (0);
1238 }
1239}
1240
1241
1242static void
1243AscWaitEEPRead(void)
1244{
1245
1246 DvcSleepMilliSecond(1);
1247}
1248
1249
1250static void
1251AscWaitEEPWrite(void)
1252{
1253
1254 DvcSleepMilliSecond(1);
1255}
1256
1257
1258static u_int16_t
1259AscReadEEPWord(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t addr)
1260{
1261 u_int16_t read_wval;
1262 u_int8_t cmd_reg;
1263
1264 AscWriteEEPCmdReg(iot, ioh, ASC_EEP_CMD_WRITE_DISABLE);
1265 AscWaitEEPRead();
1266 cmd_reg = addr | ASC_EEP_CMD_READ;
1267 AscWriteEEPCmdReg(iot, ioh, cmd_reg);
1268 AscWaitEEPRead();
1269 read_wval = ASC_GET_CHIP_EEP_DATA(iot, ioh);
1270 AscWaitEEPRead();
1271
1272 return (read_wval);
1273}
1274
1275
1276static u_int16_t
1277AscWriteEEPWord(bus_space_tag_t iot, bus_space_handle_t ioh,
1278 u_int8_t addr, u_int16_t word_val)
1279{
1280 u_int16_t read_wval;
1281
1282 read_wval = AscReadEEPWord(iot, ioh, addr);
1283 if (read_wval != word_val) {
1284 AscWriteEEPCmdReg(iot, ioh, ASC_EEP_CMD_WRITE_ABLE);
1285 AscWaitEEPRead();
1286 AscWriteEEPDataReg(iot, ioh, word_val);
1287 AscWaitEEPRead();
1288 AscWriteEEPCmdReg(iot, ioh, ASC_EEP_CMD_WRITE | addr);
1289 AscWaitEEPWrite();
1290 AscWriteEEPCmdReg(iot, ioh, ASC_EEP_CMD_WRITE_DISABLE);
1291 AscWaitEEPRead();
1292 return (AscReadEEPWord(iot, ioh, addr));
1293 }
1294 return (read_wval);
1295}
1296
1297
1298static u_int16_t
1299AscGetEEPConfig(bus_space_tag_t iot, bus_space_handle_t ioh,
1300 ASCEEP_CONFIG *cfg_buf, u_int16_t bus_type)
1301{
1302 u_int16_t wval;
1303 u_int16_t sum;
1304 u_int16_t *wbuf;
1305 int cfg_beg;
1306 int cfg_end;
1307 int s_addr;
1308 int isa_pnp_wsize;
1309
1310
1311 wbuf = (u_int16_t *) cfg_buf;
1312 sum = 0;
1313 isa_pnp_wsize = 0;
1314
1315 for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) {
1316 wval = AscReadEEPWord(iot, ioh, s_addr);
1317 sum += wval;
1318 *wbuf = wval;
1319 }
1320
1321 if (bus_type & ASC_IS_VL) {
1322 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
1323 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
1324 } else {
1325 cfg_beg = ASC_EEP_DVC_CFG_BEG;
1326 cfg_end = ASC_EEP_MAX_DVC_ADDR;
1327 }
1328
1329 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
1330 wval = AscReadEEPWord(iot, ioh, s_addr);
1331 sum += wval;
1332 *wbuf = wval;
1333 }
1334
1335 *wbuf = AscReadEEPWord(iot, ioh, s_addr);
1336
1337 return (sum);
1338}
1339
1340
1341static int
1342AscSetEEPConfig(bus_space_tag_t iot, bus_space_handle_t ioh,
1343 ASCEEP_CONFIG *cfg_buf, u_int16_t bus_type)
1344{
1345 int retry;
1346 int n_error;
1347
1348 retry = 0;
1349 while (TRUE) {
1350 if ((n_error = AscSetEEPConfigOnce(iot, ioh, cfg_buf, bus_type)) == 0)
1351 break;
1352
1353 if (++retry > ASC_EEP_MAX_RETRY)
1354 break;
1355 }
1356
1357 return (n_error);
1358}
1359
1360
1361static int
1362AscSetEEPConfigOnce(bus_space_tag_t iot, bus_space_handle_t ioh,
1363 ASCEEP_CONFIG *cfg_buf, u_int16_t bus_type)
1364{
1365 int n_error;
1366 u_int16_t *wbuf;
1367 u_int16_t sum;
1368 int s_addr;
1369 int cfg_beg;
1370 int cfg_end;
1371
1372 wbuf = (u_int16_t *) cfg_buf;
1373 n_error = 0;
1374 sum = 0;
1375
1376 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
1377 sum += *wbuf;
1378 if (*wbuf != AscWriteEEPWord(iot, ioh, s_addr, *wbuf))
1379 n_error++;
1380 }
1381
1382 if (bus_type & ASC_IS_VL) {
1383 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
1384 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
1385 } else {
1386 cfg_beg = ASC_EEP_DVC_CFG_BEG;
1387 cfg_end = ASC_EEP_MAX_DVC_ADDR;
1388 }
1389
1390 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
1391 sum += *wbuf;
1392 if (*wbuf != AscWriteEEPWord(iot, ioh, s_addr, *wbuf))
1393 n_error++;
1394 }
1395
1396 *wbuf = sum;
1397 if (sum != AscWriteEEPWord(iot, ioh, s_addr, sum))
1398 n_error++;
1399
1400 wbuf = (u_int16_t *) cfg_buf;
1401 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
1402 if (*wbuf != AscReadEEPWord(iot, ioh, s_addr))
1403 n_error++;
1404 }
1405
1406 for (s_addr = cfg_beg; s_addr <= cfg_end; s_addr++, wbuf++) {
1407 if (*wbuf != AscReadEEPWord(iot, ioh, s_addr))
1408 n_error++;
1409 }
1410
1411 return (n_error);
1412}
1413
1414
1415#ifdef ASC_DEBUG
1416static void
1417AscPrintEEPConfig(ASCEEP_CONFIG *eep_config, u_int16_t chksum)
1418{
1419 printf("---- ASC EEprom settings ----\n");
1420 printf("cfg_lsw = 0x%x\n", eep_config->cfg_lsw);
1421 printf("cfg_msw = 0x%x\n", eep_config->cfg_msw);
1422 printf("init_sdtr = 0x%x\n", eep_config->init_sdtr);
1423 printf("disc_enable = 0x%x\n", eep_config->disc_enable);
1424 printf("use_cmd_qng = %d\n", eep_config->use_cmd_qng);
1425 printf("start_motor = 0x%x\n", eep_config->start_motor);
1426 printf("max_total_qng = 0x%x\n", eep_config->max_total_qng);
1427 printf("max_tag_qng = 0x%x\n", eep_config->max_tag_qng);
1428 printf("bios_scan = 0x%x\n", eep_config->bios_scan);
1429 printf("power_up_wait = 0x%x\n", eep_config->power_up_wait);
1430 printf("no_scam = %d\n", eep_config->no_scam);
1431 printf("chip_scsi_id = %d\n", eep_config->chip_scsi_id);
1432 printf("isa_dma_speed = %d\n", eep_config->isa_dma_speed);
1433 printf("cntl = 0x%x\n", eep_config->cntl);
1434#if BYTE_ORDER == BIG_ENDIAN
1435 printf("adapter_info[0] = 0x%x\n", eep_config->adapter_info[1]);
1436 printf("adapter_info[1] = 0x%x\n", eep_config->adapter_info[0]);
1437 printf("adapter_info[2] = 0x%x\n", eep_config->adapter_info[3]);
1438 printf("adapter_info[3] = 0x%x\n", eep_config->adapter_info[2]);
1439 printf("adapter_info[4] = 0x%x\n", eep_config->adapter_info[5]);
1440 printf("adapter_info[5] = 0x%x\n", eep_config->adapter_info[4]);
1441#else
1442 printf("adapter_info[0] = 0x%x\n", eep_config->adapter_info[0]);
1443 printf("adapter_info[1] = 0x%x\n", eep_config->adapter_info[1]);
1444 printf("adapter_info[2] = 0x%x\n", eep_config->adapter_info[2]);
1445 printf("adapter_info[3] = 0x%x\n", eep_config->adapter_info[3]);
1446 printf("adapter_info[4] = 0x%x\n", eep_config->adapter_info[4]);
1447 printf("adapter_info[5] = 0x%x\n", eep_config->adapter_info[5]);
1448#endif
1449 printf("checksum = 0x%x\n", eep_config->chksum);
1450 printf("calculated checksum = 0x%x\n", chksum);
1451 printf("-----------------------------\n");
1452}
1453#endif
1454
1455
1456/******************************************************************************/
1457/* Interrupt routines */
1458/******************************************************************************/
1459
1460
1461int
1462AscISR(ASC_SOFTC *sc)
1463{
1464 bus_space_tag_t iot = sc->sc_iot;
1465 bus_space_handle_t ioh = sc->sc_ioh;
1466 u_int16_t chipstat;
1467 u_int16_t saved_ram_addr;
1468 u_int8_t ctrl_reg;
1469 u_int8_t saved_ctrl_reg;
1470 int int_pending;
1471 int status;
1472 u_int8_t host_flag;
1473
1474
1475 int_pending = FALSE;
1476
1477 ctrl_reg = ASC_GET_CHIP_CONTROL(iot, ioh);
1478 saved_ctrl_reg = ctrl_reg & (~(ASC_CC_SCSI_RESET | ASC_CC_CHIP_RESET |
1479 ASC_CC_SINGLE_STEP | ASC_CC_DIAG | ASC_CC_TEST));
1480 chipstat = ASC_GET_CHIP_STATUS(iot, ioh);
1481 if (chipstat & ASC_CSW_SCSI_RESET_LATCH) {
1482 if (!(sc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
1483 int_pending = TRUE;
1484 sc->sdtr_done = 0;
1485 saved_ctrl_reg &= (u_int8_t) (~ASC_CC_HALT);
1486
1487 while (ASC_GET_CHIP_STATUS(iot, ioh) & ASC_CSW_SCSI_RESET_ACTIVE);
1488
1489 ASC_SET_CHIP_CONTROL(iot, ioh, (ASC_CC_CHIP_RESET | ASC_CC_HALT));
1490 ASC_SET_CHIP_CONTROL(iot, ioh, ASC_CC_HALT);
1491 ASC_SET_CHIP_STATUS(iot, ioh, ASC_CIW_CLR_SCSI_RESET_INT);
1492 ASC_SET_CHIP_STATUS(iot, ioh, 0);
1493 chipstat = ASC_GET_CHIP_STATUS(iot, ioh);
1494 }
1495 }
1496 saved_ram_addr = ASC_GET_CHIP_LRAM_ADDR(iot, ioh);
1497 host_flag = AscReadLramByte(iot, ioh, ASCV_HOST_FLAG_B) &
1498 (u_int8_t) (~ASC_HOST_FLAG_IN_ISR);
1499 AscWriteLramByte(iot, ioh, ASCV_HOST_FLAG_B,
1500 (host_flag | ASC_HOST_FLAG_IN_ISR));
1501
1502 if ((chipstat & ASC_CSW_INT_PENDING) || (int_pending)) {
1503 AscAckInterrupt(iot, ioh);
1504 int_pending = TRUE;
1505
1506 if ((chipstat & ASC_CSW_HALTED) &&
1507 (ctrl_reg & ASC_CC_SINGLE_STEP)) {
1508 AscIsrChipHalted(sc);
1509 saved_ctrl_reg &= ~ASC_CC_HALT;
1510 } else {
1511 if (sc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) {
1512 while (((status = AscIsrQDone(sc)) & 0x01) != 0);
1513 } else {
1514 do {
1515 if ((status = AscIsrQDone(sc)) == 1)
1516 break;
1517 } while (status == 0x11);
1518 }
1519
1520 if (status & 0x80)
1521 int_pending = -1;
1522 }
1523 }
1524 AscWriteLramByte(iot, ioh, ASCV_HOST_FLAG_B, host_flag);
1525 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, saved_ram_addr);
1526 ASC_SET_CHIP_CONTROL(iot, ioh, saved_ctrl_reg);
1527
1528 return (1);
1529 /* return(int_pending); */
1530}
1531
1532
1533static int
1534AscIsrQDone(ASC_SOFTC *sc)
1535{
1536 u_int8_t next_qp;
1537 u_int8_t n_q_used;
1538 u_int8_t sg_list_qp;
1539 u_int8_t sg_queue_cnt;
1540 u_int8_t q_cnt;
1541 u_int8_t done_q_tail;
1542 u_int8_t tid_no;
1543 ASC_SCSI_BIT_ID_TYPE scsi_busy;
1544 ASC_SCSI_BIT_ID_TYPE target_id;
1545 bus_space_tag_t iot = sc->sc_iot;
1546 bus_space_handle_t ioh = sc->sc_ioh;
1547 u_int16_t q_addr;
1548 u_int16_t sg_q_addr;
1549 u_int8_t cur_target_qng;
1550 ASC_QDONE_INFO scsiq_buf;
1551 ASC_QDONE_INFO *scsiq;
1552 ASC_ISR_CALLBACK asc_isr_callback;
1553
1554
1555 asc_isr_callback = (ASC_ISR_CALLBACK) sc->isr_callback;
1556 n_q_used = 1;
1557 scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
1558 done_q_tail = ASC_GET_VAR_DONE_QTAIL(iot, ioh);
1559 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
1560 next_qp = AscReadLramByte(iot, ioh, (q_addr + ASC_SCSIQ_B_FWD));
1561
1562 if (next_qp != ASC_QLINK_END) {
1563 ASC_PUT_VAR_DONE_QTAIL(iot, ioh, next_qp);
1564 q_addr = ASC_QNO_TO_QADDR(next_qp);
1565 sg_queue_cnt = _AscCopyLramScsiDoneQ(iot, ioh, q_addr, scsiq,
1566 sc->max_dma_count);
1567 AscWriteLramByte(iot, ioh, (q_addr + ASC_SCSIQ_B_STATUS),
1568 (scsiq->q_status & ~(ASC_QS_READY | ASC_QS_ABORTED)));
1569 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
1570 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
1571 if ((scsiq->cntl & ASC_QC_SG_HEAD) != 0) {
1572 sg_q_addr = q_addr;
1573 sg_list_qp = next_qp;
1574 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
1575 sg_list_qp = AscReadLramByte(iot, ioh,
1576 sg_q_addr + ASC_SCSIQ_B_FWD);
1577 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
1578 if (sg_list_qp == ASC_QLINK_END) {
1579 AscSetLibErrorCode(sc, ASCQ_ERR_SG_Q_LINKS);
1580 scsiq->d3.done_stat = ASC_QD_WITH_ERROR;
1581 scsiq->d3.host_stat = ASC_QHSTA_D_QDONE_SG_LIST_CORRUPTED;
1582 panic("AscIsrQDone: Corrupted SG list encountered");
1583 }
1584 AscWriteLramByte(iot, ioh,
1585 sg_q_addr + ASC_SCSIQ_B_STATUS, ASC_QS_FREE);
1586 }
1587 n_q_used = sg_queue_cnt + 1;
1588 ASC_PUT_VAR_DONE_QTAIL(iot, ioh, sg_list_qp);
1589 }
1590 if (sc->queue_full_or_busy & target_id) {
1591 cur_target_qng = AscReadLramByte(iot, ioh,
1592 ASC_QADR_BEG + scsiq->d2.target_ix);
1593
1594 if (cur_target_qng < sc->max_dvc_qng[tid_no]) {
1595 scsi_busy = AscReadLramByte(iot, ioh, ASCV_SCSIBUSY_B);
1596 scsi_busy &= ~target_id;
1597 AscWriteLramByte(iot, ioh, ASCV_SCSIBUSY_B, scsi_busy);
1598 sc->queue_full_or_busy &= ~target_id;
1599 }
1600 }
1601 if (sc->cur_total_qng >= n_q_used) {
1602 sc->cur_total_qng -= n_q_used;
1603 if (sc->cur_dvc_qng[tid_no] != 0) {
1604 sc->cur_dvc_qng[tid_no]--;
1605 }
1606 } else {
1607 AscSetLibErrorCode(sc, ASCQ_ERR_CUR_QNG);
1608 scsiq->d3.done_stat = ASC_QD_WITH_ERROR;
1609 panic("AscIsrQDone: Attempting to free more queues than are active");
1610 }
1611
1612 if ((adv_ccb_phys_kv(sc, scsiq->d2.ccb_ptr) == 0UL) ||
1613 ((scsiq->q_status & ASC_QS_ABORTED) != 0)) {
1614 return (0x11);
1615 } else if (scsiq->q_status == ASC_QS_DONE) {
1616 scsiq->remain_bytes += scsiq->extra_bytes;
1617
1618 if (scsiq->d3.done_stat == ASC_QD_WITH_ERROR) {
1619 if (scsiq->d3.host_stat == ASC_QHSTA_M_DATA_OVER_RUN) {
1620 if ((scsiq->cntl & (ASC_QC_DATA_IN | ASC_QC_DATA_OUT)) == 0) {
1621 scsiq->d3.done_stat = ASC_QD_NO_ERROR;
1622 scsiq->d3.host_stat = ASC_QHSTA_NO_ERROR;
1623 }
1624 } else if (scsiq->d3.host_stat == ASC_QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
1625 AscStopChip(iot, ioh);
1626 ASC_SET_CHIP_CONTROL(iot, ioh, (ASC_CC_SCSI_RESET | ASC_CC_HALT));
1627 DvcDelayNanoSecond(60000);
1628 ASC_SET_CHIP_CONTROL(iot, ioh, ASC_CC_HALT);
1629 ASC_SET_CHIP_STATUS(iot, ioh, ASC_CIW_CLR_SCSI_RESET_INT);
1630 ASC_SET_CHIP_STATUS(iot, ioh, 0);
1631 ASC_SET_CHIP_CONTROL(iot, ioh, 0);
1632 }
1633 }
1634 (*asc_isr_callback) (sc, scsiq);
1635
1636 return (1);
1637 } else {
1638 AscSetLibErrorCode(sc, ASCQ_ERR_Q_STATUS);
1639 panic("AscIsrQDone: completed scsiq with unknown status");
1640
1641 return (0x80);
1642 }
1643 }
1644 return (0);
1645}
1646
1647
1648/*
1649 * handle all the conditions that may halt the board
1650 * waiting us to intervene
1651 */
1652static void
1653AscIsrChipHalted(ASC_SOFTC *sc)
1654{
1655 bus_space_tag_t iot = sc->sc_iot;
1656 bus_space_handle_t ioh = sc->sc_ioh;
1657 EXT_MSG out_msg;
1658 u_int16_t int_halt_code;
1659 u_int16_t halt_q_addr;
1660 u_int8_t halt_qp;
1661 u_int8_t target_ix;
1662 u_int8_t tag_code;
1663 u_int8_t q_status;
1664 u_int8_t q_cntl;
1665 u_int8_t tid_no;
1666 u_int8_t cur_dvc_qng;
1667 u_int8_t asyn_sdtr;
1668 u_int8_t scsi_status;
1669 u_int8_t sdtr_data;
1670 ASC_SCSI_BIT_ID_TYPE scsi_busy;
1671 ASC_SCSI_BIT_ID_TYPE target_id;
1672
1673
1674 int_halt_code = AscReadLramWord(iot, ioh, ASCV_HALTCODE_W);
1675
1676 halt_qp = AscReadLramByte(iot, ioh, ASCV_CURCDB_B);
1677 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
1678 target_ix = AscReadLramByte(iot, ioh, halt_q_addr + ASC_SCSIQ_B_TARGET_IX);
1679 q_cntl = AscReadLramByte(iot, ioh, halt_q_addr + ASC_SCSIQ_B_CNTL);
1680 tid_no = ASC_TIX_TO_TID(target_ix);
1681 target_id = ASC_TID_TO_TARGET_ID(tid_no);
1682
1683 if (sc->pci_fix_asyn_xfer & target_id) {
1684 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
1685 } else {
1686 asyn_sdtr = 0;
1687 }
1688
1689 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
1690 if (sc->pci_fix_asyn_xfer & target_id) {
1691 AscSetChipSDTR(iot, ioh, 0, tid_no);
1692 sc->sdtr_data[tid_no] = 0;
1693 }
1694 AscWriteLramWord(iot, ioh, ASCV_HALTCODE_W, 0);
1695 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
1696 if (sc->pci_fix_asyn_xfer & target_id) {
1697 AscSetChipSDTR(iot, ioh, asyn_sdtr, tid_no);
1698 sc->sdtr_data[tid_no] = asyn_sdtr;
1699 }
1700 AscWriteLramWord(iot, ioh, ASCV_HALTCODE_W, 0);
1701 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
1702 AscHandleExtMsgIn(sc, halt_q_addr, q_cntl, target_id,
1703 tid_no, asyn_sdtr);
1704 AscWriteLramWord(iot, ioh, ASCV_HALTCODE_W, 0);
1705 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
1706 q_cntl |= ASC_QC_REQ_SENSE;
1707
1708 if (sc->init_sdtr & target_id) {
1709 sc->sdtr_done &= ~target_id;
1710
1711 sdtr_data = ASC_GET_MCODE_INIT_SDTR_AT_ID(iot, ioh, tid_no);
1712 q_cntl |= ASC_QC_MSG_OUT;
1713 AscMsgOutSDTR(sc, sc->sdtr_period_tbl[(sdtr_data >> 4) &
1714 (sc->max_sdtr_index - 1)],
1715 (sdtr_data & ASC_SYN_MAX_OFFSET));
1716 }
1717 AscWriteLramByte(iot, ioh, halt_q_addr + ASC_SCSIQ_B_CNTL, q_cntl);
1718
1719 tag_code = AscReadLramByte(iot, ioh, halt_q_addr + ASC_SCSIQ_B_TAG_CODE);
1720 tag_code &= 0xDC;
1721
1722 if ((sc->pci_fix_asyn_xfer & target_id) &&
1723 !(sc->pci_fix_asyn_xfer_always & target_id)) {
1724 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT |
1725 ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
1726 }
1727 AscWriteLramByte(iot, ioh, halt_q_addr + ASC_SCSIQ_B_TAG_CODE, tag_code);
1728
1729 q_status = AscReadLramByte(iot, ioh, halt_q_addr + ASC_SCSIQ_B_STATUS);
1730 q_status |= ASC_QS_READY | ASC_QS_BUSY;
1731
1732 AscWriteLramByte(iot, ioh, halt_q_addr + ASC_SCSIQ_B_STATUS, q_status);
1733
1734 scsi_busy = AscReadLramByte(iot, ioh, ASCV_SCSIBUSY_B);
1735 scsi_busy &= ~target_id;
1736 AscWriteLramByte(iot, ioh, ASCV_SCSIBUSY_B, scsi_busy);
1737
1738 AscWriteLramWord(iot, ioh, ASCV_HALTCODE_W, 0);
1739 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
1740 AscMemWordCopyFromLram(iot, ioh, ASCV_MSGOUT_BEG,
1741 (u_int16_t *) & out_msg, sizeof(EXT_MSG) >> 1);
1742
1743 if ((out_msg.msg_type == MS_EXTEND) &&
1744 (out_msg.msg_len == MS_SDTR_LEN) &&
1745 (out_msg.msg_req == MS_SDTR_CODE)) {
1746 sc->init_sdtr &= ~target_id;
1747 sc->sdtr_done &= ~target_id;
1748 AscSetChipSDTR(iot, ioh, asyn_sdtr, tid_no);
1749 sc->sdtr_data[tid_no] = asyn_sdtr;
1750 }
1751 q_cntl &= ~ASC_QC_MSG_OUT;
1752 AscWriteLramByte(iot, ioh, halt_q_addr + ASC_SCSIQ_B_CNTL, q_cntl);
1753 AscWriteLramWord(iot, ioh, ASCV_HALTCODE_W, 0);
1754 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
1755 scsi_status = AscReadLramByte(iot, ioh,
1756 halt_q_addr + ASC_SCSIQ_SCSI_STATUS);
1757 cur_dvc_qng = AscReadLramByte(iot, ioh, target_ix + ASC_QADR_BEG);
1758
1759 if ((cur_dvc_qng > 0) && (sc->cur_dvc_qng[tid_no] > 0)) {
1760 scsi_busy = AscReadLramByte(iot, ioh, ASCV_SCSIBUSY_B);
1761 scsi_busy |= target_id;
1762 AscWriteLramByte(iot, ioh, ASCV_SCSIBUSY_B, scsi_busy);
1763 sc->queue_full_or_busy |= target_id;
1764
1765 if (scsi_status == SS_QUEUE_FULL) {
1766 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
1767 cur_dvc_qng -= 1;
1768 sc->max_dvc_qng[tid_no] = cur_dvc_qng;
1769
1770 AscWriteLramByte(iot, ioh,
1771 tid_no + ASCV_MAX_DVC_QNG_BEG, cur_dvc_qng);
1772
1773#if ASC_QUEUE_FLOW_CONTROL
1774 if ((sc->device[tid_no] != NULL) &&
1775 (sc->device[tid_no]->queue_curr_depth > cur_dvc_qng)) {
1776 sc->device[tid_no]->queue_curr_depth = cur_dvc_qng;
1777 }
1778#endif /* ASC_QUEUE_FLOW_CONTROL */
1779 }
1780 }
1781 }
1782 AscWriteLramWord(iot, ioh, ASCV_HALTCODE_W, 0);
1783 }
1784 return;
1785}
1786
1787
1788static int
1789AscWaitTixISRDone(ASC_SOFTC *sc, u_int8_t target_ix)
1790{
1791 u_int8_t cur_req;
1792 u_int8_t tid_no;
1793 int i = 0;
1794
1795 tid_no = ASC_TIX_TO_TID(target_ix);
1796 while (i++ < 10) {
1797 if ((cur_req = sc->cur_dvc_qng[tid_no]) == 0)
1798 break;
1799
1800 DvcSleepMilliSecond(1000L);
1801 if (sc->cur_dvc_qng[tid_no] == cur_req)
1802 break;
1803 }
1804 return (1);
1805}
1806
1807static int
1808AscWaitISRDone(ASC_SOFTC *sc)
1809{
1810 int tid;
1811
1812 for (tid = 0; tid <= ASC_MAX_TID; tid++)
1813 AscWaitTixISRDone(sc, ASC_TID_TO_TIX(tid));
1814
1815 return (1);
1816}
1817
1818
1819static u_int8_t
1820_AscCopyLramScsiDoneQ(bus_space_tag_t iot, bus_space_handle_t ioh,
1821 u_int16_t q_addr, ASC_QDONE_INFO *scsiq, u_int32_t max_dma_count)
1822{
1823 u_int16_t _val;
1824 u_int8_t sg_queue_cnt;
1825
1826 AscGetQDoneInfo(iot, ioh, q_addr + ASC_SCSIQ_DONE_INFO_BEG, scsiq);
1827
1828 _val = AscReadLramWord(iot, ioh, q_addr + ASC_SCSIQ_B_STATUS);
1829 scsiq->q_status = LO_BYTE(_val);
1830 scsiq->q_no = HI_BYTE(_val);
1831 _val = AscReadLramWord(iot, ioh, q_addr + ASC_SCSIQ_B_CNTL);
1832 scsiq->cntl = LO_BYTE(_val);
1833 sg_queue_cnt = HI_BYTE(_val);
1834 _val = AscReadLramWord(iot, ioh, q_addr + ASC_SCSIQ_B_SENSE_LEN);
1835 scsiq->sense_len = LO_BYTE(_val);
1836 scsiq->extra_bytes = HI_BYTE(_val);
1837 scsiq->remain_bytes = AscReadLramWord(iot, ioh,
1838 q_addr + ASC_SCSIQ_DW_REMAIN_XFER_CNT);
1839 scsiq->remain_bytes &= max_dma_count;
1840
1841 return (sg_queue_cnt);
1842}
1843
1844
1845static void
1846AscGetQDoneInfo(bus_space_tag_t iot, bus_space_handle_t ioh,
1847 u_int16_t addr, ASC_QDONE_INFO *scsiq)
1848{
1849 u_int16_t val;
1850
1851 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, addr);
1852
1853 val = ASC_GET_CHIP_LRAM_DATA(iot, ioh);
1854 scsiq->d2.ccb_ptr = MAKELONG(val, ASC_GET_CHIP_LRAM_DATA(iot, ioh));
1855 val = ASC_GET_CHIP_LRAM_DATA(iot, ioh);
1856 scsiq->d2.target_ix = LO_BYTE(val);
1857 scsiq->d2.flag = HI_BYTE(val);
1858 val = ASC_GET_CHIP_LRAM_DATA(iot, ioh);
1859 scsiq->d2.cdb_len = LO_BYTE(val);
1860 scsiq->d2.tag_code = HI_BYTE(val);
1861 scsiq->d2.vm_id = ASC_GET_CHIP_LRAM_DATA(iot, ioh);
1862
1863 val = ASC_GET_CHIP_LRAM_DATA(iot, ioh);
1864 scsiq->d3.done_stat = LO_BYTE(val);
1865 scsiq->d3.host_stat = HI_BYTE(val);
1866 val = ASC_GET_CHIP_LRAM_DATA(iot, ioh);
1867 scsiq->d3.scsi_stat = LO_BYTE(val);
1868 scsiq->d3.scsi_msg = HI_BYTE(val);
1869}
1870
1871
1872static void
1873AscToggleIRQAct(bus_space_tag_t iot, bus_space_handle_t ioh)
1874{
1875
1876 ASC_SET_CHIP_STATUS(iot, ioh, ASC_CIW_IRQ_ACT);
1877 ASC_SET_CHIP_STATUS(iot, ioh, 0);
1878}
1879
1880
1881static void
1882AscDisableInterrupt(bus_space_tag_t iot, bus_space_handle_t ioh)
1883{
1884 u_int16_t cfg;
1885
1886 cfg = ASC_GET_CHIP_CFG_LSW(iot, ioh);
1887 ASC_SET_CHIP_CFG_LSW(iot, ioh, cfg & (~ASC_CFG0_HOST_INT_ON));
1888}
1889
1890
1891static void
1892AscEnableInterrupt(bus_space_tag_t iot, bus_space_handle_t ioh)
1893{
1894 u_int16_t cfg;
1895
1896 cfg = ASC_GET_CHIP_CFG_LSW(iot, ioh);
1897 ASC_SET_CHIP_CFG_LSW(iot, ioh, cfg | ASC_CFG0_HOST_INT_ON);
1898}
1899
1900
1901u_int8_t
1902AscGetChipIRQ(bus_space_tag_t iot, bus_space_handle_t ioh, u_int16_t bus_type)
1903{
1904 u_int16_t cfg_lsw;
1905 u_int8_t chip_irq;
1906
1907
1908#if 0
1909 if (bus_type & ASC_IS_EISA) {
1910 cfg_lsw = AscGetEisaChipCfg(iot, ioh);
1911 chip_irq = ((cfg_lsw >> 8) & 0x07) + 10;
1912 if((chip_irq == 13) || (chip_irq > 15))
1913 return (0);
1914 return(chip_irq);
1915 }
1916#endif
1917 if ((bus_type & ASC_IS_VL) != 0) {
1918 cfg_lsw = ASC_GET_CHIP_CFG_LSW(iot, ioh);
1919 chip_irq = (cfg_lsw >> 2) & 0x07;
1920 if ((chip_irq == 0) ||
1921 (chip_irq == 4) ||
1922 (chip_irq == 7)) {
1923 return (0);
1924 }
1925 return (chip_irq + (ASC_MIN_IRQ_NO - 1));
1926 }
1927 cfg_lsw = ASC_GET_CHIP_CFG_LSW(iot, ioh);
1928 chip_irq = (cfg_lsw >> 2) & 0x03;
1929 if (chip_irq == 3)
1930 chip_irq += 2;
1931 return (chip_irq + ASC_MIN_IRQ_NO);
1932}
1933
1934
1935static u_int8_t
1936AscSetChipIRQ(bus_space_tag_t iot, bus_space_handle_t ioh,
1937 u_int8_t irq_no, u_int16_t bus_type)
1938{
1939 u_int16_t cfg_lsw;
1940
1941
1942 if (bus_type & ASC_IS_VL) {
1943 if (irq_no) {
1944 if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO))
1945 irq_no = 0;
1946 else
1947 irq_no -= ASC_MIN_IRQ_NO - 1;
1948 }
1949
1950 cfg_lsw = ASC_GET_CHIP_CFG_LSW(iot, ioh) & 0xFFE3;
1951 cfg_lsw |= 0x0010;
1952 ASC_SET_CHIP_CFG_LSW(iot, ioh, cfg_lsw);
1953 AscToggleIRQAct(iot, ioh);
1954 cfg_lsw = ASC_GET_CHIP_CFG_LSW(iot, ioh) & 0xFFE0;
1955 cfg_lsw |= (irq_no & 0x07) << 2;
1956 ASC_SET_CHIP_CFG_LSW(iot, ioh, cfg_lsw);
1957 AscToggleIRQAct(iot, ioh);
1958
1959 return (AscGetChipIRQ(iot, ioh, bus_type));
1960 }
1961 if (bus_type & ASC_IS_ISA) {
1962 if (irq_no == 15)
1963 irq_no -= 2;
1964 irq_no -= ASC_MIN_IRQ_NO;
1965 cfg_lsw = ASC_GET_CHIP_CFG_LSW(iot, ioh) & 0xFFF3;
1966 cfg_lsw |= (irq_no & 0x03) << 2;
1967 ASC_SET_CHIP_CFG_LSW(iot, ioh, cfg_lsw);
1968
1969 return (AscGetChipIRQ(iot, ioh, bus_type));
1970 }
1971 return (0);
1972}
1973
1974
1975static void
1976AscAckInterrupt(bus_space_tag_t iot, bus_space_handle_t ioh)
1977{
1978 u_int8_t host_flag;
1979 u_int8_t risc_flag;
1980 u_int16_t loop;
1981
1982
1983 loop = 0;
1984 do {
1985 risc_flag = AscReadLramByte(iot, ioh, ASCV_RISC_FLAG_B);
1986 if (loop++ > 0x7FFF)
1987 break;
1988 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
1989
1990 host_flag = AscReadLramByte(iot, ioh, ASCV_HOST_FLAG_B) &
1991 (~ASC_HOST_FLAG_ACK_INT);
1992 AscWriteLramByte(iot, ioh, ASCV_HOST_FLAG_B,
1993 host_flag | ASC_HOST_FLAG_ACK_INT);
1994 ASC_SET_CHIP_STATUS(iot, ioh, ASC_CIW_INT_ACK);
1995
1996 loop = 0;
1997 while (ASC_GET_CHIP_STATUS(iot, ioh) & ASC_CSW_INT_PENDING) {
1998 ASC_SET_CHIP_STATUS(iot, ioh, ASC_CIW_INT_ACK);
1999 if (loop++ > 3)
2000 break;
2001 }
2002
2003 AscWriteLramByte(iot, ioh, ASCV_HOST_FLAG_B, host_flag);
2004}
2005
2006
2007static u_int32_t
2008AscGetMaxDmaCount(u_int16_t bus_type)
2009{
2010 if (bus_type & ASC_IS_ISA)
2011 return (ASC_MAX_ISA_DMA_COUNT);
2012 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
2013 return (ASC_MAX_VL_DMA_COUNT);
2014 return (ASC_MAX_PCI_DMA_COUNT);
2015}
2016
2017
2018u_int16_t
2019AscGetIsaDmaChannel(bus_space_tag_t iot, bus_space_handle_t ioh)
2020{
2021 u_int16_t channel;
2022
2023 channel = ASC_GET_CHIP_CFG_LSW(iot, ioh) & 0x0003;
2024 if (channel == 0x03)
2025 return (0);
2026 else if (channel == 0x00)
2027 return (7);
2028 return (channel + 4);
2029}
2030
2031
2032static u_int16_t
2033AscSetIsaDmaChannel(bus_space_tag_t iot, bus_space_handle_t ioh,
2034 u_int16_t dma_channel)
2035{
2036 u_int16_t cfg_lsw;
2037 u_int8_t value;
2038
2039 if ((dma_channel >= 5) && (dma_channel <= 7)) {
2040 if (dma_channel == 7)
2041 value = 0x00;
2042 else
2043 value = dma_channel - 4;
2044 cfg_lsw = ASC_GET_CHIP_CFG_LSW(iot, ioh) & 0xFFFC;
2045 cfg_lsw |= value;
2046 ASC_SET_CHIP_CFG_LSW(iot, ioh, cfg_lsw);
2047 return (AscGetIsaDmaChannel(iot, ioh));
2048 }
2049 return (0);
2050}
2051
2052
2053static u_int8_t
2054AscGetIsaDmaSpeed(bus_space_tag_t iot, bus_space_handle_t ioh)
2055{
2056 u_int8_t speed_value;
2057
2058 AscSetBank(iot, ioh, 1);
2059 speed_value = ASC_READ_CHIP_DMA_SPEED(iot, ioh);
2060 speed_value &= 0x07;
2061 AscSetBank(iot, ioh, 0);
2062 return (speed_value);
2063}
2064
2065
2066static u_int8_t
2067AscSetIsaDmaSpeed(bus_space_tag_t iot, bus_space_handle_t ioh,
2068 u_int8_t speed_value)
2069{
2070 speed_value &= 0x07;
2071 AscSetBank(iot, ioh, 1);
2072 ASC_WRITE_CHIP_DMA_SPEED(iot, ioh, speed_value);
2073 AscSetBank(iot, ioh, 0);
2074 return (AscGetIsaDmaSpeed(iot, ioh));
2075}
2076
2077
2078/******************************************************************************/
2079/* Messages routines */
2080/******************************************************************************/
2081
2082
2083static void
2084AscHandleExtMsgIn(ASC_SOFTC *sc, u_int16_t halt_q_addr, u_int8_t q_cntl,
2085 ASC_SCSI_BIT_ID_TYPE target_id, int tid_no, u_int8_t asyn_sdtr)
2086{
2087 bus_space_tag_t iot = sc->sc_iot;
2088 bus_space_handle_t ioh = sc->sc_ioh;
2089 EXT_MSG ext_msg;
2090 u_int8_t sdtr_data;
2091 int sdtr_accept;
2092
2093
2094 AscMemWordCopyFromLram(iot, ioh, ASCV_MSGIN_BEG,
2095 (u_int16_t *) & ext_msg, sizeof(EXT_MSG) >> 1);
2096
2097 if (ext_msg.msg_type == MS_EXTEND &&
2098 ext_msg.msg_req == MS_SDTR_CODE &&
2099 ext_msg.msg_len == MS_SDTR_LEN) {
2100 sdtr_accept = TRUE;
2101
2102 if (ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET) {
2103 sdtr_accept = FALSE;
2104 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
2105 }
2106 if ((ext_msg.xfer_period <
2107 sc->sdtr_period_tbl[sc->host_init_sdtr_index]) ||
2108 (ext_msg.xfer_period >
2109 sc->sdtr_period_tbl[sc->max_sdtr_index])) {
2110 sdtr_accept = FALSE;
2111 ext_msg.xfer_period = sc->sdtr_period_tbl[sc->host_init_sdtr_index];
2112 }
2113 if (sdtr_accept) {
2114 sdtr_data = AscCalSDTRData(sc, ext_msg.xfer_period,
2115 ext_msg.req_ack_offset);
2116 if (sdtr_data == 0xFF) {
2117 q_cntl |= ASC_QC_MSG_OUT;
2118 sc->init_sdtr &= ~target_id;
2119 sc->sdtr_done &= ~target_id;
2120 AscSetChipSDTR(iot, ioh, asyn_sdtr, tid_no);
2121 sc->sdtr_data[tid_no] = asyn_sdtr;
2122 }
2123 }
2124 if (ext_msg.req_ack_offset == 0) {
2125 q_cntl &= ~ASC_QC_MSG_OUT;
2126 sc->init_sdtr &= ~target_id;
2127 sc->sdtr_done &= ~target_id;
2128 AscSetChipSDTR(iot, ioh, asyn_sdtr, tid_no);
2129 } else {
2130 if (sdtr_accept && (q_cntl & ASC_QC_MSG_OUT)) {
2131 q_cntl &= ~ASC_QC_MSG_OUT;
2132 sc->sdtr_done |= target_id;
2133 sc->init_sdtr |= target_id;
2134 sc->pci_fix_asyn_xfer &= ~target_id;
2135 sdtr_data = AscCalSDTRData(sc, ext_msg.xfer_period,
2136 ext_msg.req_ack_offset);
2137 AscSetChipSDTR(iot, ioh, sdtr_data, tid_no);
2138 sc->sdtr_data[tid_no] = sdtr_data;
2139 } else {
2140 q_cntl |= ASC_QC_MSG_OUT;
2141 AscMsgOutSDTR(sc, ext_msg.xfer_period,
2142 ext_msg.req_ack_offset);
2143 sc->pci_fix_asyn_xfer &= ~target_id;
2144 sdtr_data = AscCalSDTRData(sc, ext_msg.xfer_period,
2145 ext_msg.req_ack_offset);
2146 AscSetChipSDTR(iot, ioh, sdtr_data, tid_no);
2147 sc->sdtr_data[tid_no] = sdtr_data;
2148 sc->sdtr_done |= target_id;
2149 sc->init_sdtr |= target_id;
2150 }
2151 }
2152 } else if (ext_msg.msg_type == MS_EXTEND &&
2153 ext_msg.msg_req == MS_WDTR_CODE &&
2154 ext_msg.msg_len == MS_WDTR_LEN) {
2155 ext_msg.wdtr_width = 0;
2156 AscMemWordCopyToLram(iot, ioh, ASCV_MSGOUT_BEG,
2157 (const u_int16_t *) & ext_msg, sizeof(EXT_MSG) >> 1);
2158 q_cntl |= ASC_QC_MSG_OUT;
2159 } else {
2160 ext_msg.msg_type = M1_MSG_REJECT;
2161 AscMemWordCopyToLram(iot, ioh, ASCV_MSGOUT_BEG,
2162 (const u_int16_t *) & ext_msg, sizeof(EXT_MSG) >> 1);
2163 q_cntl |= ASC_QC_MSG_OUT;
2164 }
2165
2166 AscWriteLramByte(iot, ioh, halt_q_addr + ASC_SCSIQ_B_CNTL, q_cntl);
2167}
2168
2169
2170static u_int8_t
2171AscMsgOutSDTR(ASC_SOFTC *sc, u_int8_t sdtr_period, u_int8_t sdtr_offset)
2172{
2173 bus_space_tag_t iot = sc->sc_iot;
2174 bus_space_handle_t ioh = sc->sc_ioh;
2175 EXT_MSG sdtr_buf;
2176 u_int8_t sdtr_period_index;
2177
2178
2179 sdtr_buf.msg_type = MS_EXTEND;
2180 sdtr_buf.msg_len = MS_SDTR_LEN;
2181 sdtr_buf.msg_req = MS_SDTR_CODE;
2182 sdtr_buf.xfer_period = sdtr_period;
2183 sdtr_offset &= ASC_SYN_MAX_OFFSET;
2184 sdtr_buf.req_ack_offset = sdtr_offset;
2185 if ((sdtr_period_index = AscGetSynPeriodIndex(sc, sdtr_period)) <=
2186 sc->max_sdtr_index) {
2187 AscMemWordCopyToLram(iot, ioh, ASCV_MSGOUT_BEG,
2188 (const u_int16_t *) & sdtr_buf, sizeof(EXT_MSG) >> 1);
2189 return ((sdtr_period_index << 4) | sdtr_offset);
2190 } else {
2191 sdtr_buf.req_ack_offset = 0;
2192 AscMemWordCopyToLram(iot, ioh, ASCV_MSGOUT_BEG,
2193 (const u_int16_t *) & sdtr_buf, sizeof(EXT_MSG) >> 1);
2194 return (0);
2195 }
2196}
2197
2198
2199/******************************************************************************/
2200/* SDTR routines */
2201/******************************************************************************/
2202
2203
2204static void
2205AscSetChipSDTR(bus_space_tag_t iot, bus_space_handle_t ioh,
2206 u_int8_t sdtr_data, u_int8_t tid_no)
2207{
2208 AscSetChipSynRegAtID(iot, ioh, tid_no, sdtr_data);
2209 AscWriteLramByte(iot, ioh, tid_no + ASCV_SDTR_DONE_BEG, sdtr_data);
2210}
2211
2212
2213static u_int8_t
2214AscCalSDTRData(ASC_SOFTC *sc, u_int8_t sdtr_period, u_int8_t syn_offset)
2215{
2216 u_int8_t byte;
2217 u_int8_t sdtr_period_ix;
2218
2219 sdtr_period_ix = AscGetSynPeriodIndex(sc, sdtr_period);
2220 if (sdtr_period_ix > sc->max_sdtr_index)
2221 return (0xFF);
2222
2223 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
2224 return (byte);
2225}
2226
2227
2228static u_int8_t
2229AscGetSynPeriodIndex(ASC_SOFTC *sc, u_int8_t syn_time)
2230{
2231 u_int8_t *period_table;
2232 int max_index;
2233 int min_index;
2234 int i;
2235
2236 period_table = sc->sdtr_period_tbl;
2237 max_index = sc->max_sdtr_index;
2238 min_index = sc->host_init_sdtr_index;
2239 if ((syn_time <= period_table[max_index])) {
2240 for (i = min_index; i < (max_index - 1); i++) {
2241 if (syn_time <= period_table[i])
2242 return (i);
2243 }
2244
2245 return (max_index);
2246 } else
2247 return (max_index + 1);
2248}
2249
2250
2251/******************************************************************************/
2252/* Queue routines */
2253/******************************************************************************/
2254
2255/*
2256 * Send a command to the board
2257 */
2258int
2259AscExeScsiQueue(ASC_SOFTC *sc, ASC_SCSI_Q *scsiq)
2260{
2261 bus_space_tag_t iot = sc->sc_iot;
2262 bus_space_handle_t ioh = sc->sc_ioh;
2263 ASC_SG_HEAD *sg_head = scsiq->sg_head;
2264 int retval;
2265 int n_q_required;
2266 int disable_syn_offset_one_fix;
2267 int i;
2268 u_int32_t addr;
2269 u_int16_t sg_entry_cnt = 0;
2270 u_int16_t sg_entry_cnt_minus_one = 0;
2271 u_int8_t target_ix;
2272 u_int8_t tid_no;
2273 u_int8_t sdtr_data;
2274 u_int8_t extra_bytes;
2275 u_int8_t scsi_cmd;
2276 u_int32_t data_cnt;
2277
2278
2279 scsiq->q1.q_no = 0;
2280 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0)
2281 scsiq->q1.extra_bytes = 0;
2282
2283 retval = ASC_BUSY;
2284 target_ix = scsiq->q2.target_ix;
2285 tid_no = ASC_TIX_TO_TID(target_ix);
2286 n_q_required = 1;
2287
2288 if (scsiq->cdbptr[0] == SCSICMD_RequestSense)
2289 if ((sc->init_sdtr & scsiq->q1.target_id) != 0) {
2290 sc->sdtr_done &= ~scsiq->q1.target_id;
2291 sdtr_data = ASC_GET_MCODE_INIT_SDTR_AT_ID(iot, ioh, tid_no);
2292 AscMsgOutSDTR(sc, sc->sdtr_period_tbl[(sdtr_data >> 4) &
2293 (sc->max_sdtr_index - 1)],
2294 sdtr_data & ASC_SYN_MAX_OFFSET);
2295 scsiq->q1.cntl |= (ASC_QC_MSG_OUT | ASC_QC_URGENT);
2296 }
2297 /*
2298 * if there is just one segment into S/G list then
2299 * map it as it was a single request, filling
2300 * data_addr and data_cnt of ASC_SCSIQ structure.
2301 */
2302 if ((scsiq->q1.cntl & ASC_QC_SG_HEAD) != 0) {
2303 sg_entry_cnt = sg_head->entry_cnt;
2304
2305 if (sg_entry_cnt < 1)
2306 panic("AscExeScsiQueue: Queue with QC_SG_HEAD set but %d segs.",
2307 sg_entry_cnt);
2308
2309 if (sg_entry_cnt > ASC_MAX_SG_LIST)
2310 panic("AscExeScsiQueue: Queue with too many segs.");
2311
2312 if (sg_entry_cnt == 1) {
2313 scsiq->q1.data_addr = sg_head->sg_list[0].addr;
2314 scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
2315 scsiq->q1.cntl &= ~(ASC_QC_SG_HEAD | ASC_QC_SG_SWAP_QUEUE);
2316 }
2317 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
2318 }
2319 scsi_cmd = scsiq->cdbptr[0];
2320 disable_syn_offset_one_fix = FALSE;
2321 if ((sc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
2322 !(sc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
2323 if (scsiq->q1.cntl & ASC_QC_SG_HEAD) {
2324 data_cnt = 0;
2325 for (i = 0; i < sg_entry_cnt; i++)
2326 data_cnt += sg_head->sg_list[i].bytes;
2327 } else {
2328 data_cnt = scsiq->q1.data_cnt;
2329 }
2330
2331 if (data_cnt != 0ul) {
2332 if (data_cnt < 512ul) {
2333 disable_syn_offset_one_fix = TRUE;
2334 } else {
2335 if (scsi_cmd == SCSICMD_Inquiry ||
2336 scsi_cmd == SCSICMD_RequestSense ||
2337 scsi_cmd == SCSICMD_ReadCapacity ||
2338 scsi_cmd == SCSICMD_ReadTOC ||
2339 scsi_cmd == SCSICMD_ModeSelect6 ||
2340 scsi_cmd == SCSICMD_ModeSense6 ||
2341 scsi_cmd == SCSICMD_ModeSelect10 ||
2342 scsi_cmd == SCSICMD_ModeSense10) {
2343 disable_syn_offset_one_fix = TRUE;
2344 }
2345 }
2346 }
2347 }
2348 if (disable_syn_offset_one_fix) {
2349 scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
2350 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
2351 ASC_TAG_FLAG_DISABLE_DISCONNECT);
2352 } else {
2353 scsiq->q2.tag_code &= 0x23;
2354 }
2355
2356 if ((scsiq->q1.cntl & ASC_QC_SG_HEAD) != 0) {
2357 if (sc->bug_fix_cntl) {
2358 if (sc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
2359 if ((scsi_cmd == SCSICMD_Read6) || (scsi_cmd == SCSICMD_Read10)) {
2360 addr = sg_head->sg_list[sg_entry_cnt_minus_one].addr +
2361 sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
2362 extra_bytes = addr & 0x0003;
2363 if ((extra_bytes != 0) &&
2364 ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0)) {
2365 scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
2366 scsiq->q1.extra_bytes = extra_bytes;
2367 sg_head->sg_list[sg_entry_cnt_minus_one].bytes -=
2368 extra_bytes;
2369 }
2370 }
2371 }
2372 }
2373 sg_head->entry_to_copy = sg_head->entry_cnt;
2374 n_q_required = AscSgListToQueue(sg_entry_cnt);
2375 if ((AscGetNumOfFreeQueue(sc, target_ix, n_q_required) >= n_q_required)
2376 || ((scsiq->q1.cntl & ASC_QC_URGENT) != 0)) {
2377 retval = AscSendScsiQueue(sc, scsiq, n_q_required);
2378 }
2379 } else {
2380 if (sc->bug_fix_cntl) {
2381 if (sc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
2382 if ((scsi_cmd == SCSICMD_Read6) || (scsi_cmd == SCSICMD_Read10)) {
2383 addr = scsiq->q1.data_addr + scsiq->q1.data_cnt;
2384 extra_bytes = addr & 0x0003;
2385 if ((extra_bytes != 0) &&
2386 ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0)) {
2387 if ((scsiq->q1.data_cnt & 0x01FF) == 0) {
2388 scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
2389 scsiq->q1.data_cnt -= extra_bytes;
2390 scsiq->q1.extra_bytes = extra_bytes;
2391 }
2392 }
2393 }
2394 }
2395 }
2396 n_q_required = 1;
2397 if ((AscGetNumOfFreeQueue(sc, target_ix, 1) >= 1) ||
2398 ((scsiq->q1.cntl & ASC_QC_URGENT) != 0)) {
2399 retval = AscSendScsiQueue(sc, scsiq, n_q_required);
2400 }
2401 }
2402
2403 return (retval);
2404}
2405
2406
2407static int
2408AscSendScsiQueue(ASC_SOFTC *sc, ASC_SCSI_Q *scsiq, u_int8_t n_q_required)
2409{
2410 bus_space_tag_t iot = sc->sc_iot;
2411 bus_space_handle_t ioh = sc->sc_ioh;
2412 u_int8_t free_q_head;
2413 u_int8_t next_qp;
2414 u_int8_t tid_no;
2415 u_int8_t target_ix;
2416 int retval;
2417
2418
2419 target_ix = scsiq->q2.target_ix;
2420 tid_no = ASC_TIX_TO_TID(target_ix);
2421 retval = ASC_BUSY;
2422 free_q_head = ASC_GET_VAR_FREE_QHEAD(iot, ioh);
2423
2424 if ((next_qp = AscAllocMultipleFreeQueue(iot, ioh, free_q_head, n_q_required))
2425 != ASC_QLINK_END) {
2426 if (n_q_required > 1) {
2427 sc->last_q_shortage = 0;
2428 scsiq->sg_head->queue_cnt = n_q_required - 1;
2429 }
2430 scsiq->q1.q_no = free_q_head;
2431
2432 if ((retval = AscPutReadySgListQueue(sc, scsiq, free_q_head)) == ASC_NOERROR) {
2433 ASC_PUT_VAR_FREE_QHEAD(iot, ioh, next_qp);
2434 sc->cur_total_qng += n_q_required;
2435 sc->cur_dvc_qng[tid_no]++;
2436 }
2437 }
2438 return (retval);
2439}
2440
2441
2442static int
2443AscPutReadySgListQueue(ASC_SOFTC *sc, ASC_SCSI_Q *scsiq, u_int8_t q_no)
2444{
2445 bus_space_tag_t iot = sc->sc_iot;
2446 bus_space_handle_t ioh = sc->sc_ioh;
2447 int retval;
2448 int i;
2449 ASC_SG_HEAD *sg_head;
2450 ASC_SG_LIST_Q scsi_sg_q;
2451 u_int32_t saved_data_addr;
2452 u_int32_t saved_data_cnt;
2453 u_int16_t sg_list_dwords;
2454 u_int16_t sg_index;
2455 u_int16_t sg_entry_cnt;
2456 u_int16_t q_addr;
2457 u_int8_t next_qp;
2458
2459
2460 saved_data_addr = scsiq->q1.data_addr;
2461 saved_data_cnt = scsiq->q1.data_cnt;
2462
2463 if ((sg_head = scsiq->sg_head) != 0) {
2464 scsiq->q1.data_addr = sg_head->sg_list[0].addr;
2465 scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
2466 sg_entry_cnt = sg_head->entry_cnt - 1;
2467 if (sg_entry_cnt != 0) {
2468 q_addr = ASC_QNO_TO_QADDR(q_no);
2469 sg_index = 1;
2470 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
2471 scsi_sg_q.sg_head_qp = q_no;
2472 scsi_sg_q.cntl = ASC_QCSG_SG_XFER_LIST;
2473
2474 for (i = 0; i < sg_head->queue_cnt; i++) {
2475 scsi_sg_q.seq_no = i + 1;
2476 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
2477 sg_list_dwords = ASC_SG_LIST_PER_Q * 2;
2478 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
2479 if (i == 0) {
2480 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q;
2481 scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q;
2482 } else {
2483 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
2484 scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1;
2485 }
2486 } else {
2487 scsi_sg_q.cntl |= ASC_QCSG_SG_XFER_END;
2488 sg_list_dwords = sg_entry_cnt << 1;
2489 if (i == 0) {
2490 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
2491 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt;
2492 } else {
2493 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
2494 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
2495 }
2496
2497 sg_entry_cnt = 0;
2498 }
2499
2500 next_qp = AscReadLramByte(iot, ioh, q_addr + ASC_SCSIQ_B_FWD);
2501 scsi_sg_q.q_no = next_qp;
2502 q_addr = ASC_QNO_TO_QADDR(next_qp);
2503
2504 /*
2505 * Tell the board how many entries are in the S/G list
2506 */
2507 AscMemWordCopyToLram(iot, ioh, q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
2508 (const u_int16_t *) & scsi_sg_q,
2509 sizeof(ASC_SG_LIST_Q) >> 1);
2510 /*
2511 * Tell the board the addresses of the S/G list segments
2512 */
2513 AscMemDWordCopyToLram(iot, ioh, q_addr + ASC_SGQ_LIST_BEG,
2514 (u_int32_t *) & sg_head->sg_list[sg_index],
2515 sg_list_dwords);
2516 sg_index += ASC_SG_LIST_PER_Q;
2517 }
2518 }
2519 }
2520 retval = AscPutReadyQueue(sc, scsiq, q_no);
2521 scsiq->q1.data_addr = saved_data_addr;
2522 scsiq->q1.data_cnt = saved_data_cnt;
2523 return (retval);
2524}
2525
2526
2527static int
2528AscPutReadyQueue(ASC_SOFTC *sc, ASC_SCSI_Q *scsiq, u_int8_t q_no)
2529{
2530 bus_space_tag_t iot = sc->sc_iot;
2531 bus_space_handle_t ioh = sc->sc_ioh;
2532 u_int16_t q_addr;
2533 u_int8_t tid_no;
2534 u_int8_t sdtr_data;
2535 u_int8_t syn_period_ix;
2536 u_int8_t syn_offset;
2537
2538
2539 if (((sc->init_sdtr & scsiq->q1.target_id) != 0) &&
2540 ((sc->sdtr_done & scsiq->q1.target_id) == 0)) {
2541 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
2542 sdtr_data = ASC_GET_MCODE_INIT_SDTR_AT_ID(iot, ioh, tid_no);
2543 syn_period_ix = (sdtr_data >> 4) & (sc->max_sdtr_index - 1);
2544 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
2545 AscMsgOutSDTR(sc, sc->sdtr_period_tbl[syn_period_ix], syn_offset);
2546 scsiq->q1.cntl |= ASC_QC_MSG_OUT;
2547 }
2548 q_addr = ASC_QNO_TO_QADDR(q_no);
2549
2550 if ((scsiq->q1.target_id & sc->use_tagged_qng) == 0) {
2551 scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
2552 }
2553 scsiq->q1.status = ASC_QS_FREE;
2554 AscMemWordCopyToLram(iot, ioh, q_addr + ASC_SCSIQ_CDB_BEG,
2555 (const u_int16_t *) scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
2556
2557 AscPutSCSIQ(iot, ioh, q_addr + ASC_SCSIQ_CPY_BEG, scsiq);
2558
2559 /*
2560 * Let's start the command
2561 */
2562 AscWriteLramWord(iot, ioh, q_addr + ASC_SCSIQ_B_STATUS,
2563 (scsiq->q1.q_no << 8) | ASC_QS_READY);
2564
2565 return (ASC_NOERROR);
2566}
2567
2568
2569static void
2570AscPutSCSIQ(bus_space_tag_t iot, bus_space_handle_t ioh,
2571 u_int16_t addr, ASC_SCSI_Q *scsiq)
2572{
2573 u_int16_t val;
2574
2575
2576 ASC_SET_CHIP_LRAM_ADDR(iot, ioh, addr);
2577
2578 /* ASC_SCSIQ_1 */
2579 val = MAKEWORD(scsiq->q1.cntl, scsiq->q1.sg_queue_cnt);
2580 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2581 val = MAKEWORD(scsiq->q1.target_id, scsiq->q1.target_lun);
2582 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2583 val = LO_WORD(scsiq->q1.data_addr);
2584 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2585 val = HI_WORD(scsiq->q1.data_addr);
2586 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2587 val = LO_WORD(scsiq->q1.data_cnt);
2588 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2589 val = HI_WORD(scsiq->q1.data_cnt);
2590 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2591 val = LO_WORD(scsiq->q1.sense_addr);
2592 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2593 val = HI_WORD(scsiq->q1.sense_addr);
2594 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2595 val = MAKEWORD(scsiq->q1.sense_len, scsiq->q1.extra_bytes);
2596 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2597
2598 /* ASC_SCSIQ_2 */
2599 val = LO_WORD(scsiq->q2.ccb_ptr);
2600 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2601 val = HI_WORD(scsiq->q2.ccb_ptr);
2602 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2603 val = MAKEWORD(scsiq->q2.target_ix, scsiq->q2.flag);
2604 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2605 val = MAKEWORD(scsiq->q2.cdb_len, scsiq->q2.tag_code);
2606 ASC_SET_CHIP_LRAM_DATA(iot, ioh, val);
2607 ASC_SET_CHIP_LRAM_DATA(iot, ioh, scsiq->q2.vm_id);
2608}
2609
2610
2611static int
2612AscSgListToQueue(int sg_list)
2613{
2614 int n_sg_list_qs;
2615
2616 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
2617 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
2618 n_sg_list_qs++;
2619
2620 return (n_sg_list_qs + 1);
2621}
2622
2623
2624static u_int
2625AscGetNumOfFreeQueue(ASC_SOFTC *sc, u_int8_t target_ix, u_int8_t n_qs)
2626{
2627 u_int cur_used_qs;
2628 u_int cur_free_qs;
2629
2630
2631 if (n_qs == 1) {
2632 cur_used_qs = sc->cur_total_qng +
2633 sc->last_q_shortage +
2634 ASC_MIN_FREE_Q;
2635 } else {
2636 cur_used_qs = sc->cur_total_qng + ASC_MIN_FREE_Q;
2637 }
2638
2639 if ((cur_used_qs + n_qs) <= sc->max_total_qng) {
2640 cur_free_qs = sc->max_total_qng - cur_used_qs;
2641 return (cur_free_qs);
2642 }
2643 if (n_qs > 1)
2644 if ((n_qs > sc->last_q_shortage) &&
2645 (n_qs <= (sc->max_total_qng - ASC_MIN_FREE_Q))) {
2646 sc->last_q_shortage = n_qs;
2647 }
2648 return (0);
2649}
2650
2651
2652static u_int8_t
2653AscAllocFreeQueue(bus_space_tag_t iot, bus_space_handle_t ioh,
2654 u_int8_t free_q_head)
2655{
2656 u_int16_t q_addr;
2657 u_int8_t next_qp;
2658 u_int8_t q_status;
2659
2660
2661 q_addr = ASC_QNO_TO_QADDR(free_q_head);
2662 q_status = AscReadLramByte(iot, ioh, q_addr + ASC_SCSIQ_B_STATUS);
2663 next_qp = AscReadLramByte(iot, ioh, q_addr + ASC_SCSIQ_B_FWD);
2664 if (((q_status & ASC_QS_READY) == 0) && (next_qp != ASC_QLINK_END))
2665 return (next_qp);
2666
2667 return (ASC_QLINK_END);
2668}
2669
2670
2671static u_int8_t
2672AscAllocMultipleFreeQueue(bus_space_tag_t iot, bus_space_handle_t ioh,
2673 u_int8_t free_q_head, u_int8_t n_free_q)
2674{
2675 u_int8_t i;
2676
2677 for (i = 0; i < n_free_q; i++) {
2678 free_q_head = AscAllocFreeQueue(iot, ioh, free_q_head);
2679 if (free_q_head == ASC_QLINK_END)
2680 break;
2681 }
2682
2683 return (free_q_head);
2684}
2685
2686
2687static int
2688AscStopQueueExe(bus_space_tag_t iot, bus_space_handle_t ioh)
2689{
2690 int count = 0;
2691
2692 if (AscReadLramByte(iot, ioh, ASCV_STOP_CODE_B) == 0) {
2693 AscWriteLramByte(iot, ioh, ASCV_STOP_CODE_B, ASC_STOP_REQ_RISC_STOP);
2694 do {
2695 if (AscReadLramByte(iot, ioh, ASCV_STOP_CODE_B) &
2696 ASC_STOP_ACK_RISC_STOP)
2697 return (1);
2698
2699 DvcSleepMilliSecond(100);
2700 } while (count++ < 20);
2701 }
2702 return (0);
2703}
2704
2705
2706static void
2707AscStartQueueExe(bus_space_tag_t iot, bus_space_handle_t ioh)
2708{
2709
2710 if (AscReadLramByte(iot, ioh, ASCV_STOP_CODE_B) != 0)
2711 AscWriteLramByte(iot, ioh, ASCV_STOP_CODE_B, 0);
2712}
2713
2714
2715static void
2716AscCleanUpBusyQueue(bus_space_tag_t iot, bus_space_handle_t ioh)
2717{
2718 int count = 0;
2719 u_int8_t stop_code;
2720
2721
2722 if (AscReadLramByte(iot, ioh, ASCV_STOP_CODE_B) != 0) {
2723 AscWriteLramByte(iot, ioh, ASCV_STOP_CODE_B, ASC_STOP_CLEAN_UP_BUSY_Q);
2724 do {
2725 stop_code = AscReadLramByte(iot, ioh, ASCV_STOP_CODE_B);
2726 if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0)
2727 break;
2728
2729 DvcSleepMilliSecond(100);
2730 } while (count++ < 20);
2731 }
2732}
2733
2734
2735static int
2736_AscWaitQDone(bus_space_tag_t iot, bus_space_handle_t ioh, ASC_SCSI_Q *scsiq)
2737{
2738 u_int16_t q_addr;
2739 u_int8_t q_status;
2740 int count = 0;
2741
2742 while (scsiq->q1.q_no == 0);
2743
2744 q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no);
2745 do {
2746 q_status = AscReadLramByte(iot, ioh, q_addr + ASC_SCSIQ_B_STATUS);
2747 DvcSleepMilliSecond(100L);
2748 if (count++ > 30)
2749 return (0);
2750
2751 } while ((q_status & ASC_QS_READY) != 0);
2752
2753 return (1);
2754}
2755
2756
2757static int
2758AscCleanUpDiscQueue(bus_space_tag_t iot, bus_space_handle_t ioh)
2759{
2760 int count;
2761 u_int8_t stop_code;
2762
2763 count = 0;
2764 if (AscReadLramByte(iot, ioh, ASCV_STOP_CODE_B) != 0) {
2765 AscWriteLramByte(iot, ioh, ASCV_STOP_CODE_B, ASC_STOP_CLEAN_UP_DISC_Q);
2766 do {
2767 stop_code = AscReadLramByte(iot, ioh, ASCV_STOP_CODE_B);
2768 if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0)
2769 break;
2770
2771 DvcSleepMilliSecond(100);
2772 } while (count++ < 20);
2773 }
2774 return (1);
2775}
2776
2777
2778/******************************************************************************/
2779/* Abort and Reset CCB routines */
2780/******************************************************************************/
2781
2782
2783int
2784AscAbortCCB(ASC_SOFTC *sc, ADV_CCB *ccb)
2785{
2786 bus_space_tag_t iot = sc->sc_iot;
2787 bus_space_handle_t ioh = sc->sc_ioh;
2788 int retval;
2789 ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
2790
2791
2792 retval = -1;
2793 saved_unit_not_ready = sc->unit_not_ready;
2794 sc->unit_not_ready = 0xFF;
2795 AscWaitISRDone(sc);
2796 if (AscStopQueueExe(iot, ioh) == 1) {
2797 if (AscRiscHaltedAbortCCB(sc, ccb) == 1) {
2798 retval = 1;
2799 AscCleanUpBusyQueue(iot, ioh);
2800 AscStartQueueExe(iot, ioh);
2801 } else {
2802 retval = 0;
2803 AscStartQueueExe(iot, ioh);
2804 }
2805 }
2806 sc->unit_not_ready = saved_unit_not_ready;
2807
2808 return (retval);
2809}
2810
2811
2812static int
2813AscRiscHaltedAbortCCB(ASC_SOFTC *sc, ADV_CCB *ccb)
2814{
2815 bus_space_tag_t iot = sc->sc_iot;
2816 bus_space_handle_t ioh = sc->sc_ioh;
2817 u_int16_t q_addr;
2818 u_int8_t q_no;
2819 ASC_QDONE_INFO scsiq_buf;
2820 ASC_QDONE_INFO *scsiq;
2821 ASC_ISR_CALLBACK asc_isr_callback;
2822 int last_int_level;
2823
2824
2825 asc_isr_callback = (ASC_ISR_CALLBACK) sc->isr_callback;
2826 last_int_level = DvcEnterCritical();
2827 scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
2828
2829 for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= sc->max_total_qng; q_no++) {
2830 q_addr = ASC_QNO_TO_QADDR(q_no);
2831 scsiq->d2.ccb_ptr = AscReadLramDWord(iot, ioh,
2832 q_addr + ASC_SCSIQ_D_CCBPTR);
2833 if (adv_ccb_phys_kv(sc, scsiq->d2.ccb_ptr) == ccb) {
2834 _AscCopyLramScsiDoneQ(iot, ioh, q_addr, scsiq, sc->max_dma_count);
2835 if (((scsiq->q_status & ASC_QS_READY) != 0)
2836 && ((scsiq->q_status & ASC_QS_ABORTED) == 0)
2837 && ((scsiq->cntl & ASC_QCSG_SG_XFER_LIST) == 0)) {
2838 scsiq->q_status |= ASC_QS_ABORTED;
2839 scsiq->d3.done_stat = ASC_QD_ABORTED_BY_HOST;
2840 AscWriteLramDWord(iot, ioh, q_addr + ASC_SCSIQ_D_CCBPTR, 0L);
2841 AscWriteLramByte(iot, ioh, q_addr + ASC_SCSIQ_B_STATUS,
2842 scsiq->q_status);
2843 (*asc_isr_callback) (sc, scsiq);
2844 return (1);
2845 }
2846 }
2847 }
2848
2849 DvcLeaveCritical(last_int_level);
2850 return (0);
2851}
2852
2853
2854static int
2855AscRiscHaltedAbortTIX(ASC_SOFTC *sc, u_int8_t target_ix)
2856{
2857 bus_space_tag_t iot = sc->sc_iot;
2858 bus_space_handle_t ioh = sc->sc_ioh;
2859 u_int16_t q_addr;
2860 u_int8_t q_no;
2861 ASC_QDONE_INFO scsiq_buf;
2862 ASC_QDONE_INFO *scsiq;
2863 ASC_ISR_CALLBACK asc_isr_callback;
2864 int last_int_level;
2865
2866
2867 asc_isr_callback = (ASC_ISR_CALLBACK) sc->isr_callback;
2868 last_int_level = DvcEnterCritical();
2869 scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
2870 for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= sc->max_total_qng; q_no++) {
2871 q_addr = ASC_QNO_TO_QADDR(q_no);
2872 _AscCopyLramScsiDoneQ(iot, ioh, q_addr, scsiq, sc->max_dma_count);
2873 if (((scsiq->q_status & ASC_QS_READY) != 0) &&
2874 ((scsiq->q_status & ASC_QS_ABORTED) == 0) &&
2875 ((scsiq->cntl & ASC_QCSG_SG_XFER_LIST) == 0)) {
2876 if (scsiq->d2.target_ix == target_ix) {
2877 scsiq->q_status |= ASC_QS_ABORTED;
2878 scsiq->d3.done_stat = ASC_QD_ABORTED_BY_HOST;
2879 AscWriteLramDWord(iot, ioh, q_addr + ASC_SCSIQ_D_CCBPTR, 0L);
2880 AscWriteLramByte(iot, ioh, q_addr + ASC_SCSIQ_B_STATUS,
2881 scsiq->q_status);
2882 (*asc_isr_callback) (sc, scsiq);
2883 }
2884 }
2885 }
2886 DvcLeaveCritical(last_int_level);
2887 return (1);
2888}
2889
2890
2891/*
2892 * AscResetDevice calls _AscWaitQDone which requires interrupt enabled,
2893 * so we cannot use this function with the actual NetBSD SCSI layer
2894 * because at boot time interrupts are disabled.
2895 */
2896int
2897AscResetDevice(ASC_SOFTC *sc, u_char target_ix)
2898{
2899 bus_space_tag_t iot = sc->sc_iot;
2900 bus_space_handle_t ioh = sc->sc_ioh;
2901 int retval;
2902 u_int8_t tid_no;
2903 ASC_SCSI_BIT_ID_TYPE target_id;
2904 int i;
2905 ASC_SCSI_REQ_Q scsiq_buf;
2906 ASC_SCSI_REQ_Q *scsiq;
2907 u_int8_t *buf;
2908 ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
2909
2910
2911 tid_no = ASC_TIX_TO_TID(target_ix);
2912 target_id = ASC_TID_TO_TARGET_ID(tid_no);
2913 saved_unit_not_ready = sc->unit_not_ready;
2914 sc->unit_not_ready = target_id;
2915 retval = ASC_ERROR;
2916
2917 AscWaitTixISRDone(sc, target_ix);
2918
2919 if (AscStopQueueExe(iot, ioh) == 1) {
2920 if (AscRiscHaltedAbortTIX(sc, target_ix) == 1) {
2921 AscCleanUpBusyQueue(iot, ioh);
2922 AscStartQueueExe(iot, ioh);
2923 AscWaitTixISRDone(sc, target_ix);
2924 retval = ASC_NOERROR;
2925 scsiq = (ASC_SCSI_REQ_Q *) & scsiq_buf;
2926 buf = (u_char *) & scsiq_buf;
2927 for (i = 0; i < sizeof(ASC_SCSI_REQ_Q); i++)
2928 *buf++ = 0x00;
2929 scsiq->q1.status = (u_char) ASC_QS_READY;
2930 scsiq->q2.cdb_len = 6;
2931 scsiq->q2.tag_code = M2_QTAG_MSG_SIMPLE;
2932 scsiq->q1.target_id = target_id;
2933 scsiq->q2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0);
2934 scsiq->cdbptr = scsiq->cdb;
2935 scsiq->q1.cntl = ASC_QC_NO_CALLBACK | ASC_QC_MSG_OUT | ASC_QC_URGENT;
2936 AscWriteLramByte(iot, ioh, ASCV_MSGOUT_BEG, M1_BUS_DVC_RESET);
2937 sc->unit_not_ready &= ~target_id;
2938 sc->sdtr_done |= target_id;
2939 if (AscExeScsiQueue(sc, (ASC_SCSI_Q *) scsiq) == ASC_NOERROR) {
2940 sc->unit_not_ready = target_id;
2941 DvcSleepMilliSecond(1000);
2942 _AscWaitQDone(iot, ioh, (ASC_SCSI_Q *) scsiq);
2943 if (AscStopQueueExe(iot, ioh) == ASC_NOERROR) {
2944 AscCleanUpDiscQueue(iot, ioh);
2945 AscStartQueueExe(iot, ioh);
2946 if (sc->pci_fix_asyn_xfer & target_id)
2947 AscSetRunChipSynRegAtID(iot, ioh, tid_no,
2948 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
2949 AscWaitTixISRDone(sc, target_ix);
2950 }
2951 } else
2952 retval = ASC_BUSY;
2953 sc->sdtr_done &= ~target_id;
2954 } else {
2955 retval = ASC_ERROR;
2956 AscStartQueueExe(iot, ioh);
2957 }
2958 }
2959 sc->unit_not_ready = saved_unit_not_ready;
2960 return (retval);
2961}
2962
2963
2964int
2965AscResetBus(ASC_SOFTC *sc)
2966{
2967 bus_space_tag_t iot = sc->sc_iot;
2968 bus_space_handle_t ioh = sc->sc_ioh;
2969 int retval;
2970 int i;
2971
2972
2973 sc->unit_not_ready = 0xFF;
2974 retval = ASC_NOERROR;
2975
2976 AscWaitISRDone(sc);
2977 AscStopQueueExe(iot, ioh);
2978 sc->sdtr_done = 0;
2979 AscResetChipAndScsiBus(iot, ioh);
2980 DvcSleepMilliSecond((u_long) ((u_int16_t) sc->scsi_reset_wait * 1000));
2981 AscReInitLram(sc);
2982 for (i = 0; i <= ASC_MAX_TID; i++) {
2983 sc->cur_dvc_qng[i] = 0;
2984 if (sc->pci_fix_asyn_xfer & (ASC_SCSI_BIT_ID_TYPE) (0x01 << i))
2985 AscSetChipSynRegAtID(iot, ioh, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB);
2986 }
2987
2988 ASC_SET_PC_ADDR(iot, ioh, ASC_MCODE_START_ADDR);
2989 if (ASC_GET_PC_ADDR(iot, ioh) != ASC_MCODE_START_ADDR)
2990 retval = ASC_ERROR;
2991
2992 if (AscStartChip(iot, ioh) == 0)
2993 retval = ASC_ERROR;
2994
2995 AscStartQueueExe(iot, ioh);
2996 sc->unit_not_ready = 0;
2997 sc->queue_full_or_busy = 0;
2998 return (retval);
2999}
3000
3001
3002/******************************************************************************/
3003/* Error Handling routines */
3004/******************************************************************************/
3005
3006
3007static int
3008AscSetLibErrorCode(ASC_SOFTC *sc, u_int16_t err_code)
3009{
3010 /*
3011 * if(sc->err_code == 0) { sc->err_code = err_code;
3012 */ AscWriteLramWord(sc->sc_iot, sc->sc_ioh, ASCV_ASCDVC_ERR_CODE_W,
3013 err_code);
3014 /*
3015 * }
3016 */
3017 return (err_code);
3018}
3019
3020
3021/******************************************************************************/
3022/* Handle bugged borads routines */
3023/******************************************************************************/
3024
3025
3026void
3027AscInquiryHandling(ASC_SOFTC *sc, u_int8_t tid_no, ASC_SCSI_INQUIRY *inq)
3028{
3029 bus_space_tag_t iot = sc->sc_iot;
3030 bus_space_handle_t ioh = sc->sc_ioh;
3031 ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no);
3032 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng;
3033
3034 orig_init_sdtr = sc->init_sdtr;
3035 orig_use_tagged_qng = sc->use_tagged_qng;
3036
3037 sc->init_sdtr &= ~tid_bit;
3038 sc->can_tagged_qng &= ~tid_bit;
3039 sc->use_tagged_qng &= ~tid_bit;
3040
3041 if (inq->byte3.rsp_data_fmt >= 2 || inq->byte2.ansi_apr_ver >= 2) {
3042 if ((sc->sdtr_enable & tid_bit) && inq->byte7.Sync)
3043 sc->init_sdtr |= tid_bit;
3044
3045 if ((sc->cmd_qng_enabled & tid_bit) && inq->byte7.CmdQue)
3046 if (AscTagQueuingSafe(inq)) {
3047 sc->use_tagged_qng |= tid_bit;
3048 sc->can_tagged_qng |= tid_bit;
3049 }
3050 }
3051 if (orig_use_tagged_qng != sc->use_tagged_qng) {
3052 AscWriteLramByte(iot, ioh, ASCV_DISC_ENABLE_B,
3053 sc->disc_enable);
3054 AscWriteLramByte(iot, ioh, ASCV_USE_TAGGED_QNG_B,
3055 sc->use_tagged_qng);
3056 AscWriteLramByte(iot, ioh, ASCV_CAN_TAGGED_QNG_B,
3057 sc->can_tagged_qng);
3058
3059 sc->max_dvc_qng[tid_no] =
3060 sc->max_tag_qng[tid_no];
3061 AscWriteLramByte(iot, ioh, ASCV_MAX_DVC_QNG_BEG + tid_no,
3062 sc->max_dvc_qng[tid_no]);
3063 }
3064 if (orig_init_sdtr != sc->init_sdtr)
3065 AscAsyncFix(sc, tid_no, inq);
3066}
3067
3068
3069static int
3070AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq)
3071{
3072 if ((inq->add_len >= 32) &&
3073 (AscCompareString(inq->vendor_id, "QUANTUM XP34301", 15) == 0) &&
3074 (AscCompareString(inq->product_rev_level, "1071", 4) == 0)) {
3075 return 0;
3076 }
3077 return 1;
3078}
3079
3080
3081static void
3082AscAsyncFix(ASC_SOFTC *sc, u_int8_t tid_no, ASC_SCSI_INQUIRY *inq)
3083{
3084 u_int8_t dvc_type;
3085 ASC_SCSI_BIT_ID_TYPE tid_bits;
3086
3087
3088 dvc_type = inq->byte0.peri_dvc_type;
3089 tid_bits = ASC_TIX_TO_TARGET_ID(tid_no);
3090
3091 if (sc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
3092 if (!(sc->init_sdtr & tid_bits)) {
3093 if ((dvc_type == SCSI_TYPE_CDROM) &&
3094 (AscCompareString(inq->vendor_id, "HP ", 3) == 0)) {
3095 sc->pci_fix_asyn_xfer_always |= tid_bits;
3096 }
3097 sc->pci_fix_asyn_xfer |= tid_bits;
3098 if ((dvc_type == SCSI_TYPE_PROC) ||
3099 (dvc_type == SCSI_TYPE_SCANNER)) {
3100 sc->pci_fix_asyn_xfer &= ~tid_bits;
3101 }
3102 if ((dvc_type == SCSI_TYPE_SASD) &&
3103 (AscCompareString(inq->vendor_id, "TANDBERG", 8) == 0) &&
3104 (AscCompareString(inq->product_id, " TDC 36", 7) == 0)) {
3105 sc->pci_fix_asyn_xfer &= ~tid_bits;
3106 }
3107 if ((dvc_type == SCSI_TYPE_SASD) &&
3108 (AscCompareString(inq->vendor_id, "WANGTEK ", 8) == 0)) {
3109 sc->pci_fix_asyn_xfer &= ~tid_bits;
3110 }
3111 if ((dvc_type == SCSI_TYPE_CDROM) &&
3112 (AscCompareString(inq->vendor_id, "NEC ", 8) == 0) &&
3113 (AscCompareString(inq->product_id, "CD-ROM DRIVE ", 16) == 0)) {
3114 sc->pci_fix_asyn_xfer &= ~tid_bits;
3115 }
3116 if ((dvc_type == SCSI_TYPE_CDROM) &&
3117 (AscCompareString(inq->vendor_id, "YAMAHA", 6) == 0) &&
3118 (AscCompareString(inq->product_id, "CDR400", 6) == 0)) {
3119 sc->pci_fix_asyn_xfer &= ~tid_bits;
3120 }
3121 if (sc->pci_fix_asyn_xfer & tid_bits) {
3122 AscSetRunChipSynRegAtID(sc->sc_iot, sc->sc_ioh, tid_no,
3123 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
3124 }
3125 }
3126 }
3127}
3128
3129
3130/******************************************************************************/
3131/* Miscellaneous routines */
3132/******************************************************************************/
3133
3134
3135static int
3136AscCompareString(const u_char *str1, const u_char *str2, int len)
3137{
3138 int i;
3139 int diff;
3140
3141 for (i = 0; i < len; i++) {
3142 diff = (int) (str1[i] - str2[i]);
3143 if (diff != 0)
3144 return (diff);
3145 }
3146
3147 return (0);
3148}
3149
3150
3151/******************************************************************************/
3152/* Device oriented routines */
3153/******************************************************************************/
3154
3155
3156static int
3157DvcEnterCritical(void)
3158{
3159 int s;
3160
3161 s = splbio();
3162 return (s);
3163}
3164
3165
3166static void
3167DvcLeaveCritical(int s)
3168{
3169
3170 splx(s);
3171}
3172
3173
3174static void
3175DvcSleepMilliSecond(u_int32_t n)
3176{
3177
3178 DELAY(n * 1000);
3179}
3180
3181#ifdef UNUSED
3182static void
3183DvcDelayMicroSecond(u_int32_t n)
3184{
3185
3186 DELAY(n);
3187}
3188#endif
3189
3190static void
3191DvcDelayNanoSecond(u_int32_t n)
3192{
3193
3194 DELAY((n + 999) / 1000);
3195}
3196