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