File: | dev/ic/adwlib.c |
Warning: | line 1720, column 2 Value stored to 'req_size' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: adwlib.c,v 1.29 2022/08/29 06:08:03 jsg Exp $ */ |
2 | /* $NetBSD: adwlib.c,v 1.20 2000/07/04 04:17:03 itojun Exp $ */ |
3 | |
4 | /* |
5 | * Low level routines for the Advanced Systems Inc. SCSI controllers chips |
6 | * |
7 | * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. |
8 | * All rights reserved. |
9 | * |
10 | * Author: Baldassare Dante Profeta <dante@mclink.it> |
11 | * |
12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions |
14 | * are met: |
15 | * 1. Redistributions of source code must retain the above copyright |
16 | * notice, this list of conditions and the following disclaimer. |
17 | * 2. Redistributions in binary form must reproduce the above copyright |
18 | * notice, this list of conditions and the following disclaimer in the |
19 | * documentation and/or other materials provided with the distribution. |
20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 | * POSSIBILITY OF SUCH DAMAGE. |
32 | */ |
33 | /* |
34 | * Ported from: |
35 | */ |
36 | /* |
37 | * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters |
38 | * |
39 | * Copyright (c) 1995-2000 Advanced System Products, Inc. |
40 | * All Rights Reserved. |
41 | * |
42 | * Redistribution and use in source and binary forms, with or without |
43 | * modification, are permitted provided that redistributions of source |
44 | * code retain the above copyright notice and this comment without |
45 | * modification. |
46 | */ |
47 | |
48 | #include <sys/param.h> |
49 | #include <sys/systm.h> |
50 | #include <sys/malloc.h> |
51 | #include <sys/kernel.h> |
52 | #include <sys/queue.h> |
53 | #include <sys/device.h> |
54 | |
55 | #include <machine/bus.h> |
56 | #include <machine/intr.h> |
57 | |
58 | #include <scsi/scsi_all.h> |
59 | #include <scsi/scsiconf.h> |
60 | |
61 | #include <dev/pci/pcidevs.h> |
62 | |
63 | #include <dev/ic/adwlib.h> |
64 | #include <dev/microcode/adw/adwmcode.h> |
65 | #include <dev/ic/adw.h> |
66 | |
67 | |
68 | int AdwRamSelfTest(bus_space_tag_t, bus_space_handle_t, u_int8_t); |
69 | int AdwLoadMCode(bus_space_tag_t, bus_space_handle_t, u_int16_t *, |
70 | u_int8_t); |
71 | int AdwASC3550Cabling(bus_space_tag_t, bus_space_handle_t, ADW_DVC_CFG *); |
72 | int AdwASC38C0800Cabling(bus_space_tag_t, bus_space_handle_t, |
73 | ADW_DVC_CFG *); |
74 | int AdwASC38C1600Cabling(bus_space_tag_t, bus_space_handle_t, |
75 | ADW_DVC_CFG *); |
76 | |
77 | u_int16_t AdwGetEEPROMConfig(bus_space_tag_t, bus_space_handle_t, |
78 | ADW_EEPROM *); |
79 | void AdwSetEEPROMConfig(bus_space_tag_t, bus_space_handle_t, |
80 | ADW_EEPROM *); |
81 | u_int16_t AdwReadEEPWord(bus_space_tag_t, bus_space_handle_t, int); |
82 | void AdwWaitEEPCmd(bus_space_tag_t, bus_space_handle_t); |
83 | |
84 | void AdwInquiryHandling(ADW_SOFTC *, ADW_SCSI_REQ_Q *); |
85 | |
86 | void AdwSleepMilliSecond(u_int32_t); |
87 | void AdwDelayMicroSecond(u_int32_t); |
88 | |
89 | |
90 | /* |
91 | * EEPROM Configuration. |
92 | * |
93 | * All drivers should use this structure to set the default EEPROM |
94 | * configuration. The BIOS now uses this structure when it is built. |
95 | * Additional structure information can be found in adwlib.h where |
96 | * the structure is defined. |
97 | */ |
98 | static const ADW_EEPROM adw_3550_Default_EEPROM = { |
99 | ADW_EEPROM_BIOS_ENABLE0x4000, /* 00 cfg_lsw */ |
100 | 0x0000, /* 01 cfg_msw */ |
101 | 0xFFFF, /* 02 disc_enable */ |
102 | 0xFFFF, /* 03 wdtr_able */ |
103 | { 0xFFFF }, /* 04 sdtr_able */ |
104 | 0xFFFF, /* 05 start_motor */ |
105 | 0xFFFF, /* 06 tagqng_able */ |
106 | 0xFFFF, /* 07 bios_scan */ |
107 | 0, /* 08 scam_tolerant */ |
108 | 7, /* 09 adapter_scsi_id */ |
109 | 0, /* bios_boot_delay */ |
110 | 3, /* 10 scsi_reset_delay */ |
111 | 0, /* bios_id_lun */ |
112 | 0, /* 11 termination */ |
113 | 0, /* reserved1 */ |
114 | 0xFFE7, /* 12 bios_ctrl */ |
115 | { 0xFFFF }, /* 13 ultra_able */ |
116 | { 0 }, /* 14 reserved2 */ |
117 | ADW_DEF_MAX_HOST_QNG0xFD, /* 15 max_host_qng */ |
118 | ADW_DEF_MAX_DVC_QNG0x3F, /* max_dvc_qng */ |
119 | 0, /* 16 dvc_cntl */ |
120 | { 0 }, /* 17 bug_fix */ |
121 | { 0,0,0 }, /* 18-20 serial_number[3] */ |
122 | 0, /* 21 check_sum */ |
123 | { /* 22-29 oem_name[16] */ |
124 | 0,0,0,0,0,0,0,0, |
125 | 0,0,0,0,0,0,0,0 |
126 | }, |
127 | 0, /* 30 dvc_err_code */ |
128 | 0, /* 31 adw_err_code */ |
129 | 0, /* 32 adw_err_addr */ |
130 | 0, /* 33 saved_dvc_err_code */ |
131 | 0, /* 34 saved_adw_err_code */ |
132 | 0 /* 35 saved_adw_err_addr */ |
133 | }; |
134 | |
135 | static const ADW_EEPROM adw_38C0800_Default_EEPROM = { |
136 | ADW_EEPROM_BIOS_ENABLE0x4000, /* 00 cfg_lsw */ |
137 | 0x0000, /* 01 cfg_msw */ |
138 | 0xFFFF, /* 02 disc_enable */ |
139 | 0xFFFF, /* 03 wdtr_able */ |
140 | { 0x4444 }, /* 04 sdtr_speed1 */ |
141 | 0xFFFF, /* 05 start_motor */ |
142 | 0xFFFF, /* 06 tagqng_able */ |
143 | 0xFFFF, /* 07 bios_scan */ |
144 | 0, /* 08 scam_tolerant */ |
145 | 7, /* 09 adapter_scsi_id */ |
146 | 0, /* bios_boot_delay */ |
147 | 3, /* 10 scsi_reset_delay */ |
148 | 0, /* bios_id_lun */ |
149 | 0, /* 11 termination_se */ |
150 | 0, /* termination_lvd */ |
151 | 0xFFE7, /* 12 bios_ctrl */ |
152 | { 0x4444 }, /* 13 sdtr_speed2 */ |
153 | { 0x4444 }, /* 14 sdtr_speed3 */ |
154 | ADW_DEF_MAX_HOST_QNG0xFD, /* 15 max_host_qng */ |
155 | ADW_DEF_MAX_DVC_QNG0x3F, /* max_dvc_qng */ |
156 | 0, /* 16 dvc_cntl */ |
157 | { 0x4444 }, /* 17 sdtr_speed4 */ |
158 | { 0,0,0 }, /* 18-20 serial_number[3] */ |
159 | 0, /* 21 check_sum */ |
160 | { /* 22-29 oem_name[16] */ |
161 | 0,0,0,0,0,0,0,0, |
162 | 0,0,0,0,0,0,0,0 |
163 | }, |
164 | 0, /* 30 dvc_err_code */ |
165 | 0, /* 31 adw_err_code */ |
166 | 0, /* 32 adw_err_addr */ |
167 | 0, /* 33 saved_dvc_err_code */ |
168 | 0, /* 34 saved_adw_err_code */ |
169 | 0, /* 35 saved_adw_err_addr */ |
170 | { /* 36-55 reserved1[16] */ |
171 | 0,0,0,0,0,0,0,0,0,0, |
172 | 0,0,0,0,0,0,0,0,0,0 |
173 | }, |
174 | 0, /* 56 cisptr_lsw */ |
175 | 0, /* 57 cisprt_msw */ |
176 | PCI_VENDOR_ADVSYS0x10cd, /* 58 subsysvid */ |
177 | PCI_PRODUCT_ADVSYS_U2W0x2500, /* 59 subsysid */ |
178 | { 0,0,0,0 } /* 60-63 reserved2[4] */ |
179 | }; |
180 | |
181 | static const ADW_EEPROM adw_38C1600_Default_EEPROM = { |
182 | ADW_EEPROM_BIOS_ENABLE0x4000, /* 00 cfg_lsw */ |
183 | 0x0000, /* 01 cfg_msw */ |
184 | 0xFFFF, /* 02 disc_enable */ |
185 | 0xFFFF, /* 03 wdtr_able */ |
186 | { 0x5555 }, /* 04 sdtr_speed1 */ |
187 | 0xFFFF, /* 05 start_motor */ |
188 | 0xFFFF, /* 06 tagqng_able */ |
189 | 0xFFFF, /* 07 bios_scan */ |
190 | 0, /* 08 scam_tolerant */ |
191 | 7, /* 09 adapter_scsi_id */ |
192 | 0, /* bios_boot_delay */ |
193 | 3, /* 10 scsi_reset_delay */ |
194 | 0, /* bios_id_lun */ |
195 | 0, /* 11 termination_se */ |
196 | 0, /* termination_lvd */ |
197 | 0xFFE7, /* 12 bios_ctrl */ |
198 | { 0x5555 }, /* 13 sdtr_speed2 */ |
199 | { 0x5555 }, /* 14 sdtr_speed3 */ |
200 | ADW_DEF_MAX_HOST_QNG0xFD, /* 15 max_host_qng */ |
201 | ADW_DEF_MAX_DVC_QNG0x3F, /* max_dvc_qng */ |
202 | 0, /* 16 dvc_cntl */ |
203 | { 0x5555 }, /* 17 sdtr_speed4 */ |
204 | { 0,0,0 }, /* 18-20 serial_number[3] */ |
205 | 0, /* 21 check_sum */ |
206 | { /* 22-29 oem_name[16] */ |
207 | 0,0,0,0,0,0,0,0, |
208 | 0,0,0,0,0,0,0,0 |
209 | }, |
210 | 0, /* 30 dvc_err_code */ |
211 | 0, /* 31 adw_err_code */ |
212 | 0, /* 32 adw_err_addr */ |
213 | 0, /* 33 saved_dvc_err_code */ |
214 | 0, /* 34 saved_adw_err_code */ |
215 | 0, /* 35 saved_adw_err_addr */ |
216 | { /* 36-55 reserved1[16] */ |
217 | 0,0,0,0,0,0,0,0,0,0, |
218 | 0,0,0,0,0,0,0,0,0,0 |
219 | }, |
220 | 0, /* 56 cisptr_lsw */ |
221 | 0, /* 57 cisprt_msw */ |
222 | PCI_VENDOR_ADVSYS0x10cd, /* 58 subsysvid */ |
223 | PCI_PRODUCT_ADVSYS_U3W0x2700, /* 59 subsysid */ |
224 | { 0,0,0,0 } /* 60-63 reserved2[4] */ |
225 | }; |
226 | |
227 | |
228 | /* |
229 | * Read the board's EEPROM configuration. Set fields in ADW_SOFTC and |
230 | * ADW_DVC_CFG based on the EEPROM settings. The chip is stopped while |
231 | * all of this is done. |
232 | * |
233 | * For a non-fatal error return a warning code. If there are no warnings |
234 | * then 0 is returned. |
235 | * |
236 | * Note: Chip is stopped on entry. |
237 | */ |
238 | int |
239 | AdwInitFromEEPROM(ADW_SOFTC *sc) |
240 | { |
241 | bus_space_tag_t iot = sc->sc_iot; |
242 | bus_space_handle_t ioh = sc->sc_ioh; |
243 | ADW_EEPROM eep_config; |
244 | u_int16_t warn_code; |
245 | u_int16_t sdtr_speed = 0; |
246 | u_int8_t tid, termination; |
247 | int i, j; |
248 | |
249 | |
250 | warn_code = 0; |
251 | |
252 | /* |
253 | * Read the board's EEPROM configuration. |
254 | * |
255 | * Set default values if a bad checksum is found. |
256 | * |
257 | * XXX - Don't handle big-endian access to EEPROM yet. |
258 | */ |
259 | if (AdwGetEEPROMConfig(iot, ioh, &eep_config) != eep_config.check_sum) { |
260 | warn_code |= ADW_WARN_EEPROM_CHKSUM0x0002; |
261 | |
262 | /* |
263 | * Set EEPROM default values. |
264 | */ |
265 | switch(sc->chip_type) { |
266 | case ADW_CHIP_ASC35500x01: |
267 | eep_config = adw_3550_Default_EEPROM; |
268 | break; |
269 | case ADW_CHIP_ASC38C08000x02: |
270 | eep_config = adw_38C0800_Default_EEPROM; |
271 | break; |
272 | case ADW_CHIP_ASC38C16000x03: |
273 | eep_config = adw_38C1600_Default_EEPROM; |
274 | |
275 | // XXX TODO!!! if (ASC_PCI_ID2FUNC(sc->cfg.pci_slot_info) != 0) { |
276 | if (sc->cfg.pci_slot_info != 0) { |
277 | u_int8_t lsw_msb; |
278 | |
279 | lsw_msb = eep_config.cfg_lsw >> 8; |
280 | /* |
281 | * Set Function 1 EEPROM Word 0 MSB |
282 | * |
283 | * Clear the BIOS_ENABLE (bit 14) and |
284 | * INTAB (bit 11) EEPROM bits. |
285 | * |
286 | * Disable Bit 14 (BIOS_ENABLE) to fix |
287 | * SPARC Ultra 60 and old Mac system booting |
288 | * problem. The Expansion ROM must |
289 | * be disabled in Function 1 for these systems. |
290 | */ |
291 | lsw_msb &= ~(((ADW_EEPROM_BIOS_ENABLE0x4000 | |
292 | ADW_EEPROM_INTAB0x0800) >> 8) & 0xFF); |
293 | /* |
294 | * Set the INTAB (bit 11) if the GPIO 0 input |
295 | * indicates the Function 1 interrupt line is |
296 | * wired to INTA. |
297 | * |
298 | * Set/Clear Bit 11 (INTAB) from |
299 | * the GPIO bit 0 input: |
300 | * 1 - Function 1 intr line wired to INT A. |
301 | * 0 - Function 1 intr line wired to INT B. |
302 | * |
303 | * Note: Adapter boards always have Function 0 |
304 | * wired to INTA. |
305 | * Put all 5 GPIO bits in input mode and then |
306 | * read their input values. |
307 | */ |
308 | ADW_WRITE_BYTE_REGISTER(iot, ioh,(((iot))->write_1(((ioh)), ((0x16)), ((0)))) |
309 | IOPB_GPIO_CNTL, 0)(((iot))->write_1(((ioh)), ((0x16)), ((0)))); |
310 | if (ADW_READ_BYTE_REGISTER(iot, ioh,(((iot))->read_1(((ioh)), ((0x12)))) |
311 | IOPB_GPIO_DATA)(((iot))->read_1(((ioh)), ((0x12)))) & 0x01) { |
312 | /* |
313 | * Function 1 interrupt wired to INTA; |
314 | * Set EEPROM bit. |
315 | */ |
316 | lsw_msb |= (ADW_EEPROM_INTAB0x0800 >> 8) |
317 | & 0xFF; |
318 | } |
319 | eep_config.cfg_lsw &= 0x00FF; |
320 | eep_config.cfg_lsw |= lsw_msb << 8; |
321 | } |
322 | break; |
323 | } |
324 | |
325 | /* |
326 | * Assume the 6 byte board serial number that was read |
327 | * from EEPROM is correct even if the EEPROM checksum |
328 | * failed. |
329 | */ |
330 | for (i = 2, j = 1; i >= 0; i--, j++) { |
331 | eep_config.serial_number[i] = |
332 | AdwReadEEPWord(iot, ioh, ADW_EEP_DVC_CFG_END(0x15) - j); |
333 | } |
334 | |
335 | AdwSetEEPROMConfig(iot, ioh, &eep_config); |
336 | } |
337 | /* |
338 | * Set sc and sc->cfg variables from the EEPROM configuration |
339 | * that was read. |
340 | * |
341 | * This is the mapping of EEPROM fields to Adw Library fields. |
342 | */ |
343 | sc->wdtr_able = eep_config.wdtr_able; |
344 | if (sc->chip_type == ADW_CHIP_ASC35500x01) { |
345 | sc->sdtr_able = eep_config.sdtr1.sdtr_able; |
346 | sc->ultra_able = eep_config.sdtr2.ultra_able; |
347 | } else { |
348 | sc->sdtr_speed1 = eep_config.sdtr1.sdtr_speed1; |
349 | sc->sdtr_speed2 = eep_config.sdtr2.sdtr_speed2; |
350 | sc->sdtr_speed3 = eep_config.sdtr3.sdtr_speed3; |
351 | sc->sdtr_speed4 = eep_config.sdtr4.sdtr_speed4; |
352 | } |
353 | sc->ppr_able = 0; |
354 | sc->tagqng_able = eep_config.tagqng_able; |
355 | sc->cfg.disc_enable = eep_config.disc_enable; |
356 | sc->max_host_qng = eep_config.max_host_qng; |
357 | sc->max_dvc_qng = eep_config.max_dvc_qng; |
358 | sc->chip_scsi_id = (eep_config.adapter_scsi_id & ADW_MAX_TID15); |
359 | sc->start_motor = eep_config.start_motor; |
360 | sc->scsi_reset_wait = eep_config.scsi_reset_delay; |
361 | sc->bios_ctrl = eep_config.bios_ctrl; |
362 | sc->no_scam = eep_config.scam_tolerant; |
363 | sc->cfg.serial1 = eep_config.serial_number[0]; |
364 | sc->cfg.serial2 = eep_config.serial_number[1]; |
365 | sc->cfg.serial3 = eep_config.serial_number[2]; |
366 | |
367 | if (sc->chip_type == ADW_CHIP_ASC38C08000x02 || |
368 | sc->chip_type == ADW_CHIP_ASC38C16000x03) { |
369 | sc->sdtr_able = 0; |
370 | for (tid = 0; tid <= ADW_MAX_TID15; tid++) { |
371 | if (tid == 0) { |
372 | sdtr_speed = sc->sdtr_speed1; |
373 | } else if (tid == 4) { |
374 | sdtr_speed = sc->sdtr_speed2; |
375 | } else if (tid == 8) { |
376 | sdtr_speed = sc->sdtr_speed3; |
377 | } else if (tid == 12) { |
378 | sdtr_speed = sc->sdtr_speed4; |
379 | } |
380 | if (sdtr_speed & ADW_MAX_TID15) { |
381 | sc->sdtr_able |= (1 << tid); |
382 | } |
383 | sdtr_speed >>= 4; |
384 | } |
385 | } |
386 | |
387 | /* |
388 | * Set the host maximum queuing (max. 253, min. 16) and the per device |
389 | * maximum queuing (max. 63, min. 4). |
390 | */ |
391 | if (eep_config.max_host_qng > ADW_DEF_MAX_HOST_QNG0xFD) { |
392 | eep_config.max_host_qng = ADW_DEF_MAX_HOST_QNG0xFD; |
393 | } else if (eep_config.max_host_qng < ADW_DEF_MIN_HOST_QNG0x10) |
394 | { |
395 | /* If the value is zero, assume it is uninitialized. */ |
396 | if (eep_config.max_host_qng == 0) { |
397 | eep_config.max_host_qng = ADW_DEF_MAX_HOST_QNG0xFD; |
398 | } else { |
399 | eep_config.max_host_qng = ADW_DEF_MIN_HOST_QNG0x10; |
400 | } |
401 | } |
402 | |
403 | if (eep_config.max_dvc_qng > ADW_DEF_MAX_DVC_QNG0x3F) { |
404 | eep_config.max_dvc_qng = ADW_DEF_MAX_DVC_QNG0x3F; |
405 | } else if (eep_config.max_dvc_qng < ADW_DEF_MIN_DVC_QNG0x04) { |
406 | /* If the value is zero, assume it is uninitialized. */ |
407 | if (eep_config.max_dvc_qng == 0) { |
408 | eep_config.max_dvc_qng = ADW_DEF_MAX_DVC_QNG0x3F; |
409 | } else { |
410 | eep_config.max_dvc_qng = ADW_DEF_MIN_DVC_QNG0x04; |
411 | } |
412 | } |
413 | |
414 | /* |
415 | * If 'max_dvc_qng' is greater than 'max_host_qng', then |
416 | * set 'max_dvc_qng' to 'max_host_qng'. |
417 | */ |
418 | if (eep_config.max_dvc_qng > eep_config.max_host_qng) { |
419 | eep_config.max_dvc_qng = eep_config.max_host_qng; |
420 | } |
421 | |
422 | /* |
423 | * Set ADW_SOFTC 'max_host_qng' and 'max_dvc_qng' |
424 | * values based on possibly adjusted EEPROM values. |
425 | */ |
426 | sc->max_host_qng = eep_config.max_host_qng; |
427 | sc->max_dvc_qng = eep_config.max_dvc_qng; |
428 | |
429 | |
430 | /* |
431 | * If the EEPROM 'termination' field is set to automatic (0), then set |
432 | * the ADW_SOFTC.cfg 'termination' field to automatic also. |
433 | * |
434 | * If the termination is specified with a non-zero 'termination' |
435 | * value check that a legal value is set and set the ADW_SOFTC.cfg |
436 | * 'termination' field appropriately. |
437 | */ |
438 | |
439 | switch(sc->chip_type) { |
440 | case ADW_CHIP_ASC35500x01: |
441 | sc->cfg.termination = 0; /* auto termination */ |
442 | switch(eep_config.termination_se) { |
443 | case 3: |
444 | /* Enable manual control with low on / high on. */ |
445 | sc->cfg.termination |= ADW_TERM_CTL_L0x0010; |
446 | case 2: |
447 | /* Enable manual control with low off / high on. */ |
448 | sc->cfg.termination |= ADW_TERM_CTL_H0x0020; |
449 | case 1: |
450 | /* Enable manual control with low off / high off. */ |
451 | sc->cfg.termination |= ADW_TERM_CTL_SEL0x0040; |
452 | case 0: |
453 | break; |
454 | default: |
455 | warn_code |= ADW_WARN_EEPROM_TERMINATION0x0004; |
456 | } |
457 | break; |
458 | |
459 | case ADW_CHIP_ASC38C08000x02: |
460 | case ADW_CHIP_ASC38C16000x03: |
461 | switch(eep_config.termination_se) { |
462 | case 0: |
463 | /* auto termination for SE */ |
464 | termination = 0; |
465 | break; |
466 | case 1: |
467 | /* Enable manual control with low off / high off. */ |
468 | termination = 0; |
469 | break; |
470 | case 2: |
471 | /* Enable manual control with low off / high on. */ |
472 | termination = ADW_TERM_SE_HI0x0020; |
473 | break; |
474 | case 3: |
475 | /* Enable manual control with low on / high on. */ |
476 | termination = ADW_TERM_SE0x0030; |
477 | break; |
478 | default: |
479 | /* |
480 | * The EEPROM 'termination_se' field contains a |
481 | * bad value. Use automatic termination instead. |
482 | */ |
483 | termination = 0; |
484 | warn_code |= ADW_WARN_EEPROM_TERMINATION0x0004; |
485 | } |
486 | |
487 | switch(eep_config.termination_lvd) { |
488 | case 0: |
489 | /* auto termination for LVD */ |
490 | sc->cfg.termination = termination; |
491 | break; |
492 | case 1: |
493 | /* Enable manual control with low off / high off. */ |
494 | sc->cfg.termination = termination; |
495 | break; |
496 | case 2: |
497 | /* Enable manual control with low off / high on. */ |
498 | sc->cfg.termination = termination | ADW_TERM_LVD_HI0x0080; |
499 | break; |
500 | case 3: |
501 | /* Enable manual control with low on / high on. */ |
502 | sc->cfg.termination = termination | ADW_TERM_LVD0x00C0; |
503 | break; |
504 | default: |
505 | /* |
506 | * The EEPROM 'termination_lvd' field contains a |
507 | * bad value. Use automatic termination instead. |
508 | */ |
509 | sc->cfg.termination = termination; |
510 | warn_code |= ADW_WARN_EEPROM_TERMINATION0x0004; |
511 | } |
512 | break; |
513 | } |
514 | |
515 | return warn_code; |
516 | } |
517 | |
518 | |
519 | /* |
520 | * Initialize the ASC-3550/ASC-38C0800/ASC-38C1600. |
521 | * |
522 | * On failure return the error code. |
523 | */ |
524 | int |
525 | AdwInitDriver(ADW_SOFTC *sc) |
526 | { |
527 | bus_space_tag_t iot = sc->sc_iot; |
528 | bus_space_handle_t ioh = sc->sc_ioh; |
529 | u_int16_t error_code; |
530 | int word; |
531 | int i; |
532 | u_int16_t bios_mem[ADW_MC_BIOSLEN0x0050/2]; /* BIOS RISC Memory |
533 | 0x40-0x8F. */ |
534 | u_int16_t wdtr_able = 0, sdtr_able, ppr_able, tagqng_able; |
535 | u_int8_t max_cmd[ADW_MAX_TID15 + 1]; |
536 | u_int8_t tid; |
537 | |
538 | |
539 | error_code = 0; |
540 | |
541 | /* |
542 | * Save the RISC memory BIOS region before writing the microcode. |
543 | * The BIOS may already be loaded and using its RISC LRAM region |
544 | * so its region must be saved and restored. |
545 | * |
546 | * Note: This code makes the assumption, which is currently true, |
547 | * that a chip reset does not clear RISC LRAM. |
548 | */ |
549 | for (i = 0; i < ADW_MC_BIOSLEN0x0050/2; i++) { |
550 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_BIOSMEM+(2*i), bios_mem[i])do { (((iot))->write_2(((ioh)), (0x04), ((0x0040 +(2*i)))) ); (bios_mem[i]) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
551 | } |
552 | |
553 | /* |
554 | * Save current per TID negotiated values. |
555 | */ |
556 | switch (sc->chip_type) { |
557 | case ADW_CHIP_ASC35500x01: |
558 | if (bios_mem[(ADW_MC_BIOS_SIGNATURE0x0058-ADW_MC_BIOSMEM0x0040)/2]==0x55AA){ |
559 | |
560 | u_int16_t bios_version, major, minor; |
561 | |
562 | bios_version = bios_mem[(ADW_MC_BIOS_VERSION0x005A - |
563 | ADW_MC_BIOSMEM0x0040) / 2]; |
564 | major = (bios_version >> 12) & 0xF; |
565 | minor = (bios_version >> 8) & 0xF; |
566 | if (major < 3 || (major == 3 && minor == 1)) { |
567 | /* |
568 | * BIOS 3.1 and earlier location of |
569 | * 'wdtr_able' variable. |
570 | */ |
571 | ADW_READ_WORD_LRAM(iot, ioh, 0x120, wdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x120)))); (wdtr_able ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
572 | } else { |
573 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (wdtr_able ) = (((iot))->read_2(((ioh)), (0x06))); } while (0) |
574 | wdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (wdtr_able ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
575 | } |
576 | } |
577 | break; |
578 | |
579 | case ADW_CHIP_ASC38C16000x03: |
580 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_PPR_ABLE, ppr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x017A)))); (ppr_able ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
581 | /* FALLTHROUGH */ |
582 | case ADW_CHIP_ASC38C08000x02: |
583 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE, wdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (wdtr_able ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
584 | break; |
585 | } |
586 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE, sdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x009E)))); (sdtr_able ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
587 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE, tagqng_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A0)))); (tagqng_able ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
588 | for (tid = 0; tid <= ADW_MAX_TID15; tid++) { |
589 | ADW_READ_BYTE_LRAM(iot, ioh, ADW_MC_NUMBER_OF_MAX_CMD + tid,do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (max_cmd[tid]) = (((iot))->read_1(((ioh)), (0x06))); } while (0) |
590 | max_cmd[tid])do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (max_cmd[tid]) = (((iot))->read_1(((ioh)), (0x06))); } while (0); |
591 | } |
592 | |
593 | /* |
594 | * Perform a RAM Built-In Self Test |
595 | */ |
596 | if((error_code = AdwRamSelfTest(iot, ioh, sc->chip_type))) { |
597 | return error_code; |
598 | } |
599 | |
600 | /* |
601 | * Load the Microcode |
602 | */ |
603 | ; |
604 | if((error_code = AdwLoadMCode(iot, ioh, bios_mem, sc->chip_type))) { |
605 | return error_code; |
606 | } |
607 | |
608 | /* |
609 | * Read microcode version and date. |
610 | */ |
611 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_VERSION_DATE, sc->cfg.mcode_date)do { (((iot))->write_2(((ioh)), (0x04), ((0x0038)))); (sc-> cfg.mcode_date) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
612 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_VERSION_NUM, sc->cfg.mcode_version)do { (((iot))->write_2(((ioh)), (0x04), ((0x003A)))); (sc-> cfg.mcode_version) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
613 | |
614 | /* |
615 | * If the PCI Configuration Command Register "Parity Error Response |
616 | * Control" Bit was clear (0), then set the microcode variable |
617 | * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode |
618 | * to ignore DMA parity errors. |
619 | */ |
620 | if (sc->cfg.control_flag & CONTROL_FLAG_IGNORE_PERR0x0001) { |
621 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_CONTROL_FLAG, word)do { (((iot))->write_2(((ioh)), (0x04), ((0x0122)))); (word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
622 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_CONTROL_FLAG,do { (((iot))->write_2(((ioh)), (0x04), ((0x0122)))); (((iot ))->write_2(((ioh)), (0x06), ((word | 0x0001)))); } while ( 0) |
623 | word | CONTROL_FLAG_IGNORE_PERR)do { (((iot))->write_2(((ioh)), (0x04), ((0x0122)))); (((iot ))->write_2(((ioh)), (0x06), ((word | 0x0001)))); } while ( 0); |
624 | } |
625 | |
626 | switch (sc->chip_type) { |
627 | case ADW_CHIP_ASC35500x01: |
628 | /* |
629 | * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a |
630 | * FIFO threshold of 128 bytes. |
631 | * This register is only accessible to the host. |
632 | */ |
633 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_DMA_CFG0,(((iot))->write_1(((ioh)), ((0x20)), ((0x0C | 0x03)))) |
634 | START_CTL_EMFU | READ_CMD_MRM)(((iot))->write_1(((ioh)), ((0x20)), ((0x0C | 0x03)))); |
635 | break; |
636 | |
637 | case ADW_CHIP_ASC38C08000x02: |
638 | /* |
639 | * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. |
640 | * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current |
641 | * cable detection and then we are able to read C_DET[3:0]. |
642 | * |
643 | * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 |
644 | * Microcode Default Value' section below. |
645 | */ |
646 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1,(((iot))->write_2(((ioh)), ((0x0E)), (((((iot))->read_2 (((ioh)), ((0x0E)))) | 0x4000)))) |
647 | ADW_READ_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1)(((iot))->write_2(((ioh)), ((0x0E)), (((((iot))->read_2 (((ioh)), ((0x0E)))) | 0x4000)))) |
648 | | ADW_DIS_TERM_DRV)(((iot))->write_2(((ioh)), ((0x0E)), (((((iot))->read_2 (((ioh)), ((0x0E)))) | 0x4000)))); |
649 | |
650 | /* |
651 | * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and |
652 | * START_CTL_TH [3:2] bits for the default FIFO threshold. |
653 | * |
654 | * Note: ASC-38C0800 FIFO threshold has been changed to |
655 | * 256 bytes. |
656 | * |
657 | * For DMA Errata #4 set the BC_THRESH_ENB bit. |
658 | */ |
659 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_DMA_CFG0,(((iot))->write_1(((ioh)), ((0x20)), ((0x80 | 0x50 | 0x00 | 0x03)))) |
660 | BC_THRESH_ENB | FIFO_THRESH_80B(((iot))->write_1(((ioh)), ((0x20)), ((0x80 | 0x50 | 0x00 | 0x03)))) |
661 | | START_CTL_TH | READ_CMD_MRM)(((iot))->write_1(((ioh)), ((0x20)), ((0x80 | 0x50 | 0x00 | 0x03)))); |
662 | break; |
663 | |
664 | case ADW_CHIP_ASC38C16000x03: |
665 | /* |
666 | * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. |
667 | * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current |
668 | * cable detection and then we are able to read C_DET[3:0]. |
669 | * |
670 | * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 |
671 | * Microcode Default Value' section below. |
672 | */ |
673 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1,(((iot))->write_2(((ioh)), ((0x0E)), (((((iot))->read_2 (((ioh)), ((0x0E)))) | 0x4000)))) |
674 | ADW_READ_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1)(((iot))->write_2(((ioh)), ((0x0E)), (((((iot))->read_2 (((ioh)), ((0x0E)))) | 0x4000)))) |
675 | | ADW_DIS_TERM_DRV)(((iot))->write_2(((ioh)), ((0x0E)), (((((iot))->read_2 (((ioh)), ((0x0E)))) | 0x4000)))); |
676 | |
677 | /* |
678 | * If the BIOS control flag AIPP (Asynchronous Information |
679 | * Phase Protection) disable bit is not set, then set the |
680 | * firmware 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to |
681 | * enable AIPP checking and encoding. |
682 | */ |
683 | if ((sc->bios_ctrl & BIOS_CTRL_AIPP_DIS0x2000) == 0) { |
684 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_CONTROL_FLAG, word)do { (((iot))->write_2(((ioh)), (0x04), ((0x0122)))); (word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
685 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_CONTROL_FLAG,do { (((iot))->write_2(((ioh)), (0x04), ((0x0122)))); (((iot ))->write_2(((ioh)), (0x06), ((word | 0x0002)))); } while ( 0) |
686 | word | CONTROL_FLAG_ENABLE_AIPP)do { (((iot))->write_2(((ioh)), (0x04), ((0x0122)))); (((iot ))->write_2(((ioh)), (0x06), ((word | 0x0002)))); } while ( 0); |
687 | } |
688 | |
689 | /* |
690 | * For ASC-38C1600 use DMA_CFG0 default values: |
691 | * FIFO_THRESH_80B [6:4], and START_CTL_TH [3:2]. |
692 | */ |
693 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_DMA_CFG0,(((iot))->write_1(((ioh)), ((0x20)), ((0x50 | 0x00 | 0x03) ))) |
694 | FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM)(((iot))->write_1(((ioh)), ((0x20)), ((0x50 | 0x00 | 0x03) ))); |
695 | break; |
696 | } |
697 | |
698 | /* |
699 | * Microcode operating variables for WDTR, SDTR, and command tag |
700 | * queuing will be set in AdwInquiryHandling() based on what a |
701 | * device reports it is capable of in Inquiry byte 7. |
702 | * |
703 | * If SCSI Bus Resets have been disabled, then directly set |
704 | * SDTR and WDTR from the EEPROM configuration. This will allow |
705 | * the BIOS and warm boot to work without a SCSI bus hang on |
706 | * the Inquiry caused by host and target mismatched DTR values. |
707 | * Without the SCSI Bus Reset, before an Inquiry a device can't |
708 | * be assumed to be in Asynchronous, Narrow mode. |
709 | */ |
710 | if ((sc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS0x0200) == 0) { |
711 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE, sc->wdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->wdtr_able)))); } while (0); |
712 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE, sc->sdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x009E)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->sdtr_able)))); } while (0); |
713 | } |
714 | |
715 | /* |
716 | * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2, |
717 | * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID |
718 | * bitmask. These values determine the maximum SDTR speed negotiated |
719 | * with a device. |
720 | * |
721 | * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, |
722 | * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them |
723 | * without determining here whether the device supports SDTR. |
724 | */ |
725 | switch (sc->chip_type) { |
726 | case ADW_CHIP_ASC35500x01: |
727 | word = 0; |
728 | for (tid = 0; tid <= ADW_MAX_TID15; tid++) { |
729 | if (ADW_TID_TO_TIDMASK(tid)(0x01 << ((tid) & 15)) & sc->ultra_able) { |
730 | /* Set Ultra speed for TID 'tid'. */ |
731 | word |= (0x3 << (4 * (tid % 4))); |
732 | } else { |
733 | /* Set Fast speed for TID 'tid'. */ |
734 | word |= (0x2 << (4 * (tid % 4))); |
735 | } |
736 | /* Check if done with sdtr_speed1. */ |
737 | if (tid == 3) { |
738 | ADW_WRITE_WORD_LRAM(iot, ioh,do { (((iot))->write_2(((ioh)), (0x04), ((0x0090)))); (((iot ))->write_2(((ioh)), (0x06), ((word)))); } while (0) |
739 | ADW_MC_SDTR_SPEED1, word)do { (((iot))->write_2(((ioh)), (0x04), ((0x0090)))); (((iot ))->write_2(((ioh)), (0x06), ((word)))); } while (0); |
740 | word = 0; |
741 | /* Check if done with sdtr_speed2. */ |
742 | } else if (tid == 7) { |
743 | ADW_WRITE_WORD_LRAM(iot, ioh,do { (((iot))->write_2(((ioh)), (0x04), ((0x0092)))); (((iot ))->write_2(((ioh)), (0x06), ((word)))); } while (0) |
744 | ADW_MC_SDTR_SPEED2, word)do { (((iot))->write_2(((ioh)), (0x04), ((0x0092)))); (((iot ))->write_2(((ioh)), (0x06), ((word)))); } while (0); |
745 | word = 0; |
746 | /* Check if done with sdtr_speed3. */ |
747 | } else if (tid == 11) { |
748 | ADW_WRITE_WORD_LRAM(iot, ioh,do { (((iot))->write_2(((ioh)), (0x04), ((0x0094)))); (((iot ))->write_2(((ioh)), (0x06), ((word)))); } while (0) |
749 | ADW_MC_SDTR_SPEED3, word)do { (((iot))->write_2(((ioh)), (0x04), ((0x0094)))); (((iot ))->write_2(((ioh)), (0x06), ((word)))); } while (0); |
750 | word = 0; |
751 | /* Check if done with sdtr_speed4. */ |
752 | } else if (tid == 15) { |
753 | ADW_WRITE_WORD_LRAM(iot, ioh,do { (((iot))->write_2(((ioh)), (0x04), ((0x0096)))); (((iot ))->write_2(((ioh)), (0x06), ((word)))); } while (0) |
754 | ADW_MC_SDTR_SPEED4, word)do { (((iot))->write_2(((ioh)), (0x04), ((0x0096)))); (((iot ))->write_2(((ioh)), (0x06), ((word)))); } while (0); |
755 | /* End of loop. */ |
756 | } |
757 | } |
758 | |
759 | /* |
760 | * Set microcode operating variable for the |
761 | * disconnect per TID bitmask. |
762 | */ |
763 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DISC_ENABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x00A2)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->cfg.disc_enable)))); } while (0) |
764 | sc->cfg.disc_enable)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A2)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->cfg.disc_enable)))); } while (0); |
765 | break; |
766 | |
767 | case ADW_CHIP_ASC38C08000x02: |
768 | /* FALLTHROUGH */ |
769 | case ADW_CHIP_ASC38C16000x03: |
770 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DISC_ENABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x00A2)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->cfg.disc_enable)))); } while (0) |
771 | sc->cfg.disc_enable)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A2)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->cfg.disc_enable)))); } while (0); |
772 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_SPEED1,do { (((iot))->write_2(((ioh)), (0x04), ((0x0090)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->sdtr_speed1)))); } while (0) |
773 | sc->sdtr_speed1)do { (((iot))->write_2(((ioh)), (0x04), ((0x0090)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->sdtr_speed1)))); } while (0); |
774 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_SPEED2,do { (((iot))->write_2(((ioh)), (0x04), ((0x0092)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->sdtr_speed2)))); } while (0) |
775 | sc->sdtr_speed2)do { (((iot))->write_2(((ioh)), (0x04), ((0x0092)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->sdtr_speed2)))); } while (0); |
776 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_SPEED3,do { (((iot))->write_2(((ioh)), (0x04), ((0x0094)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->sdtr_speed3)))); } while (0) |
777 | sc->sdtr_speed3)do { (((iot))->write_2(((ioh)), (0x04), ((0x0094)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->sdtr_speed3)))); } while (0); |
778 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_SPEED4,do { (((iot))->write_2(((ioh)), (0x04), ((0x0096)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->sdtr_speed4)))); } while (0) |
779 | sc->sdtr_speed4)do { (((iot))->write_2(((ioh)), (0x04), ((0x0096)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->sdtr_speed4)))); } while (0); |
780 | break; |
781 | } |
782 | |
783 | |
784 | /* |
785 | * Set SCSI_CFG0 Microcode Default Value. |
786 | * |
787 | * The microcode will set the SCSI_CFG0 register using this value |
788 | * after it is started below. |
789 | */ |
790 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_SCSI_CFG0,do { (((iot))->write_2(((ioh)), (0x04), ((0x00AC)))); (((iot ))->write_2(((ioh)), (0x06), ((0x2000 | 0x0400 | 0x0040 | 0x0010 | sc->chip_scsi_id)))); } while (0) |
791 | ADW_PARITY_EN | ADW_QUEUE_128 | ADW_SEL_TMO_LONG |do { (((iot))->write_2(((ioh)), (0x04), ((0x00AC)))); (((iot ))->write_2(((ioh)), (0x06), ((0x2000 | 0x0400 | 0x0040 | 0x0010 | sc->chip_scsi_id)))); } while (0) |
792 | ADW_OUR_ID_EN | sc->chip_scsi_id)do { (((iot))->write_2(((ioh)), (0x04), ((0x00AC)))); (((iot ))->write_2(((ioh)), (0x06), ((0x2000 | 0x0400 | 0x0040 | 0x0010 | sc->chip_scsi_id)))); } while (0); |
793 | |
794 | |
795 | switch(sc->chip_type) { |
796 | case ADW_CHIP_ASC35500x01: |
797 | error_code = AdwASC3550Cabling(iot, ioh, &sc->cfg); |
798 | break; |
799 | |
800 | case ADW_CHIP_ASC38C08000x02: |
801 | error_code = AdwASC38C0800Cabling(iot, ioh, &sc->cfg); |
802 | break; |
803 | |
804 | case ADW_CHIP_ASC38C16000x03: |
805 | error_code = AdwASC38C1600Cabling(iot, ioh, &sc->cfg); |
806 | break; |
807 | } |
808 | if(error_code) { |
809 | return error_code; |
810 | } |
811 | |
812 | /* |
813 | * Set SEL_MASK Microcode Default Value |
814 | * |
815 | * The microcode will set the SEL_MASK register using this value |
816 | * after it is started below. |
817 | */ |
818 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_SEL_MASK,do { (((iot))->write_2(((ioh)), (0x04), ((0x00B2)))); (((iot ))->write_2(((ioh)), (0x06), (((0x01 << ((sc->chip_scsi_id ) & 15)))))); } while (0) |
819 | ADW_TID_TO_TIDMASK(sc->chip_scsi_id))do { (((iot))->write_2(((ioh)), (0x04), ((0x00B2)))); (((iot ))->write_2(((ioh)), (0x06), (((0x01 << ((sc->chip_scsi_id ) & 15)))))); } while (0); |
820 | |
821 | /* |
822 | * Create and Initialize Host->RISC Carrier lists |
823 | */ |
824 | sc->carr_freelist = AdwInitCarriers(sc->sc_dmamap_carrier, |
825 | sc->sc_control->carriers); |
826 | |
827 | /* |
828 | * Set-up the Host->RISC Initiator Command Queue (ICQ). |
829 | */ |
830 | |
831 | if ((sc->icq_sp = sc->carr_freelist) == NULL((void *)0)) { |
832 | return ADW_IERR_NO_CARRIER0x0004; |
833 | } |
834 | sc->carr_freelist = ADW_CARRIER_VADDR(sc,((ADW_CARRIER *) (((u_int8_t *)(sc)->sc_control->carriers ) + ((u_long)((sc->icq_sp->next_ba) & 0xFFFFFFF0)) - (sc)->sc_dmamap_carrier->dm_segs[0].ds_addr)) |
835 | ADW_GET_CARRP(sc->icq_sp->next_ba))((ADW_CARRIER *) (((u_int8_t *)(sc)->sc_control->carriers ) + ((u_long)((sc->icq_sp->next_ba) & 0xFFFFFFF0)) - (sc)->sc_dmamap_carrier->dm_segs[0].ds_addr)); |
836 | |
837 | /* |
838 | * The first command issued will be placed in the stopper carrier. |
839 | */ |
840 | sc->icq_sp->next_ba = ADW_CQ_STOPPER0x00000000; |
841 | |
842 | /* |
843 | * Set RISC ICQ physical address start value. |
844 | */ |
845 | ADW_WRITE_DWORD_LRAM(iot, ioh, ADW_MC_ICQ, sc->icq_sp->carr_ba)do { (((iot))->write_2(((ioh)), (0x04), ((0x0160)))); (((iot ))->write_2(((ioh)), (0x06), ((u_int16_t) ((sc->icq_sp-> carr_ba) & 0xFFFF)))); (((iot))->write_2(((ioh)), (0x04 ), ((0x0160) + 2))); (((iot))->write_2(((ioh)), (0x06), (( u_int16_t) ((sc->icq_sp->carr_ba >> 16) & 0xFFFF )))); } while (0); |
846 | |
847 | /* |
848 | * Initialize the COMMA register to the same value otherwise |
849 | * the RISC will prematurely detect a command is available. |
850 | */ |
851 | if(sc->chip_type == ADW_CHIP_ASC38C16000x03) { |
852 | ADW_WRITE_DWORD_REGISTER(iot, ioh, IOPDW_COMMA,(((iot))->write_4(((ioh)), ((0x14)), ((sc->icq_sp->carr_ba )))) |
853 | sc->icq_sp->carr_ba)(((iot))->write_4(((ioh)), ((0x14)), ((sc->icq_sp->carr_ba )))); |
854 | } |
855 | |
856 | /* |
857 | * Set-up the RISC->Host Initiator Response Queue (IRQ). |
858 | */ |
859 | if ((sc->irq_sp = sc->carr_freelist) == NULL((void *)0)) { |
860 | return ADW_IERR_NO_CARRIER0x0004; |
861 | } |
862 | sc->carr_freelist = ADW_CARRIER_VADDR(sc,((ADW_CARRIER *) (((u_int8_t *)(sc)->sc_control->carriers ) + ((u_long)((sc->irq_sp->next_ba) & 0xFFFFFFF0)) - (sc)->sc_dmamap_carrier->dm_segs[0].ds_addr)) |
863 | ADW_GET_CARRP(sc->irq_sp->next_ba))((ADW_CARRIER *) (((u_int8_t *)(sc)->sc_control->carriers ) + ((u_long)((sc->irq_sp->next_ba) & 0xFFFFFFF0)) - (sc)->sc_dmamap_carrier->dm_segs[0].ds_addr)); |
864 | |
865 | /* |
866 | * The first command completed by the RISC will be placed in |
867 | * the stopper. |
868 | * |
869 | * Note: Set 'next_ba' to ADW_CQ_STOPPER. When the request is |
870 | * completed the RISC will set the ADW_RQ_DONE bit. |
871 | */ |
872 | sc->irq_sp->next_ba = ADW_CQ_STOPPER0x00000000; |
873 | |
874 | /* |
875 | * Set RISC IRQ physical address start value. |
876 | */ |
877 | ADW_WRITE_DWORD_LRAM(iot, ioh, ADW_MC_IRQ, sc->irq_sp->carr_ba)do { (((iot))->write_2(((ioh)), (0x04), ((0x0164)))); (((iot ))->write_2(((ioh)), (0x06), ((u_int16_t) ((sc->irq_sp-> carr_ba) & 0xFFFF)))); (((iot))->write_2(((ioh)), (0x04 ), ((0x0164) + 2))); (((iot))->write_2(((ioh)), (0x06), (( u_int16_t) ((sc->irq_sp->carr_ba >> 16) & 0xFFFF )))); } while (0); |
878 | sc->carr_pending_cnt = 0; |
879 | |
880 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_INTR_ENABLES,(((iot))->write_1(((ioh)), ((0x02)), (((0x01 | 0x80))))) |
881 | (ADW_INTR_ENABLE_HOST_INTR | ADW_INTR_ENABLE_GLOBAL_INTR))(((iot))->write_1(((ioh)), ((0x02)), (((0x01 | 0x80))))); |
882 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_CODE_BEGIN_ADDR, word)do { (((iot))->write_2(((ioh)), (0x04), ((0x0028)))); (word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
883 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_PC, word)(((iot))->write_2(((ioh)), ((0x2A)), ((word)))); |
884 | |
885 | /* finally, finally, gentlemen, start your engine */ |
886 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_RISC_CSR, ADW_RISC_CSR_RUN)(((iot))->write_2(((ioh)), ((0x0A)), (((0x4000))))); |
887 | |
888 | /* |
889 | * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus |
890 | * Resets should be performed. The RISC has to be running |
891 | * to issue a SCSI Bus Reset. |
892 | */ |
893 | if (sc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS0x0200) |
894 | { |
895 | /* |
896 | * If the BIOS Signature is present in memory, restore the |
897 | * BIOS Handshake Configuration Table and do not perform |
898 | * a SCSI Bus Reset. |
899 | */ |
900 | if (bios_mem[(ADW_MC_BIOS_SIGNATURE0x0058 - ADW_MC_BIOSMEM0x0040)/2] == |
901 | 0x55AA) { |
902 | /* |
903 | * Restore per TID negotiated values. |
904 | */ |
905 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (((iot ))->write_2(((ioh)), (0x06), ((wdtr_able)))); } while (0) |
906 | wdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (((iot ))->write_2(((ioh)), (0x06), ((wdtr_able)))); } while (0); |
907 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x009E)))); (((iot ))->write_2(((ioh)), (0x06), ((sdtr_able)))); } while (0) |
908 | sdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x009E)))); (((iot ))->write_2(((ioh)), (0x06), ((sdtr_able)))); } while (0); |
909 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x00A0)))); (((iot ))->write_2(((ioh)), (0x06), ((tagqng_able)))); } while (0 ) |
910 | tagqng_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A0)))); (((iot ))->write_2(((ioh)), (0x06), ((tagqng_able)))); } while (0 ); |
911 | for (tid = 0; tid <= ADW_MAX_TID15; tid++) { |
912 | ADW_WRITE_BYTE_LRAM(iot, ioh,do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (((iot))->write_1(((ioh)), (0x06), ((max_cmd[tid])))); } while (0) |
913 | ADW_MC_NUMBER_OF_MAX_CMD + tid,do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (((iot))->write_1(((ioh)), (0x06), ((max_cmd[tid])))); } while (0) |
914 | max_cmd[tid])do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (((iot))->write_1(((ioh)), (0x06), ((max_cmd[tid])))); } while (0); |
915 | } |
916 | } else { |
917 | if (AdwResetCCB(sc) != ADW_TRUE1) { |
918 | error_code = ADW_WARN_BUSRESET_ERROR0x0001; |
919 | } |
920 | } |
921 | } |
922 | |
923 | return error_code; |
924 | } |
925 | |
926 | |
927 | int |
928 | AdwRamSelfTest(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t chip_type) |
929 | { |
930 | int i; |
931 | u_int8_t byte; |
932 | |
933 | |
934 | if ((chip_type == ADW_CHIP_ASC38C08000x02) || |
935 | (chip_type == ADW_CHIP_ASC38C16000x03)) { |
936 | /* |
937 | * RAM BIST (RAM Built-In Self Test) |
938 | * |
939 | * Address : I/O base + offset 0x38h register (byte). |
940 | * Function: Bit 7-6(RW) : RAM mode |
941 | * Normal Mode : 0x00 |
942 | * Pre-test Mode : 0x40 |
943 | * RAM Test Mode : 0x80 |
944 | * Bit 5 : unused |
945 | * Bit 4(RO) : Done bit |
946 | * Bit 3-0(RO) : Status |
947 | * Host Error : 0x08 |
948 | * Int_RAM Error : 0x04 |
949 | * RISC Error : 0x02 |
950 | * SCSI Error : 0x01 |
951 | * No Error : 0x00 |
952 | * |
953 | * Note: RAM BIST code should be put right here, before loading |
954 | * the microcode and after saving the RISC memory BIOS region. |
955 | */ |
956 | |
957 | /* |
958 | * LRAM Pre-test |
959 | * |
960 | * Write PRE_TEST_MODE (0x40) to register and wait for |
961 | * 10 milliseconds. |
962 | * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), |
963 | * return an error. Reset to NORMAL_MODE (0x00) and do again. |
964 | * If cannot reset to NORMAL_MODE, return an error too. |
965 | */ |
966 | for (i = 0; i < 2; i++) { |
967 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST,(((iot))->write_1(((ioh)), ((0x38)), ((0x40)))) |
968 | PRE_TEST_MODE)(((iot))->write_1(((ioh)), ((0x38)), ((0x40)))); |
969 | /* Wait for 10ms before reading back. */ |
970 | AdwSleepMilliSecond(10); |
971 | byte = ADW_READ_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST)(((iot))->read_1(((ioh)), ((0x38)))); |
972 | if ((byte & RAM_TEST_DONE0x10) == 0 || (byte & 0x0F) != |
973 | PRE_TEST_VALUE0x05) { |
974 | return ADW_IERR_BIST_PRE_TEST0x2000; |
975 | } |
976 | |
977 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST,(((iot))->write_1(((ioh)), ((0x38)), ((0x00)))) |
978 | NORMAL_MODE)(((iot))->write_1(((ioh)), ((0x38)), ((0x00)))); |
979 | /* Wait for 10ms before reading back. */ |
980 | AdwSleepMilliSecond(10); |
981 | if (ADW_READ_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST)(((iot))->read_1(((ioh)), ((0x38)))) |
982 | != NORMAL_VALUE0x00) { |
983 | return ADW_IERR_BIST_PRE_TEST0x2000; |
984 | } |
985 | } |
986 | |
987 | /* |
988 | * LRAM Test - It takes about 1.5 ms to run through the test. |
989 | * |
990 | * Write RAM_TEST_MODE (0x80) to register and wait for |
991 | * 10 milliseconds. |
992 | * If Done bit not set or Status not 0, save register byte, |
993 | * set the err_code, and return an error. |
994 | */ |
995 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST, RAM_TEST_MODE)(((iot))->write_1(((ioh)), ((0x38)), ((0x80)))); |
996 | /* Wait for 10ms before checking status. */ |
997 | AdwSleepMilliSecond(10); |
998 | |
999 | byte = ADW_READ_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST)(((iot))->read_1(((ioh)), ((0x38)))); |
1000 | if ((byte & RAM_TEST_DONE0x10)==0 || (byte & RAM_TEST_STATUS0x0F)!=0) { |
1001 | /* Get here if Done bit not set or Status not 0. */ |
1002 | return ADW_IERR_BIST_RAM_TEST0x4000; |
1003 | } |
1004 | |
1005 | /* We need to reset back to normal mode after LRAM test passes*/ |
1006 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST, NORMAL_MODE)(((iot))->write_1(((ioh)), ((0x38)), ((0x00)))); |
1007 | } |
1008 | |
1009 | return 0; |
1010 | } |
1011 | |
1012 | |
1013 | int |
1014 | AdwLoadMCode(bus_space_tag_t iot, bus_space_handle_t ioh, u_int16_t *bios_mem, |
1015 | u_int8_t chip_type) |
1016 | { |
1017 | u_int8_t *mcode_data = NULL((void *)0); |
1018 | u_int32_t mcode_chksum = 0; |
1019 | u_int16_t mcode_size = 0; |
1020 | u_int32_t sum; |
1021 | u_int16_t code_sum; |
1022 | int begin_addr; |
1023 | int end_addr; |
1024 | int word; |
1025 | int adw_memsize = 0; |
1026 | int adw_mcode_expanded_size; |
1027 | int i, j; |
1028 | |
1029 | |
1030 | switch(chip_type) { |
1031 | case ADW_CHIP_ASC35500x01: |
1032 | mcode_data = (u_int8_t *)adw_asc3550_mcode_data.mcode_data; |
1033 | mcode_chksum = (u_int32_t)adw_asc3550_mcode_data.mcode_chksum; |
1034 | mcode_size = (u_int16_t)adw_asc3550_mcode_data.mcode_size; |
1035 | adw_memsize = ADW_3550_MEMSIZE0x2000; |
1036 | break; |
1037 | |
1038 | case ADW_CHIP_ASC38C08000x02: |
1039 | mcode_data = (u_int8_t *)adw_asc38C0800_mcode_data.mcode_data; |
1040 | mcode_chksum =(u_int32_t)adw_asc38C0800_mcode_data.mcode_chksum; |
1041 | mcode_size = (u_int16_t)adw_asc38C0800_mcode_data.mcode_size; |
1042 | adw_memsize = ADW_38C0800_MEMSIZE0x4000; |
1043 | break; |
1044 | |
1045 | case ADW_CHIP_ASC38C16000x03: |
1046 | mcode_data = (u_int8_t *)adw_asc38C1600_mcode_data.mcode_data; |
1047 | mcode_chksum =(u_int32_t)adw_asc38C1600_mcode_data.mcode_chksum; |
1048 | mcode_size = (u_int16_t)adw_asc38C1600_mcode_data.mcode_size; |
1049 | adw_memsize = ADW_38C1600_MEMSIZE0x8000; |
1050 | break; |
1051 | } |
1052 | |
1053 | /* |
1054 | * Write the microcode image to RISC memory starting at address 0. |
1055 | */ |
1056 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_RAM_ADDR, 0)(((iot))->write_2(((ioh)), ((0x04)), ((0)))); |
1057 | |
1058 | /* Assume the following compressed format of the microcode buffer: |
1059 | * |
1060 | * 254 word (508 byte) table indexed by byte code followed |
1061 | * by the following byte codes: |
1062 | * |
1063 | * 1-Byte Code: |
1064 | * 00: Emit word 0 in table. |
1065 | * 01: Emit word 1 in table. |
1066 | * . |
1067 | * FD: Emit word 253 in table. |
1068 | * |
1069 | * Multi-Byte Code: |
1070 | * FE WW WW: (3 byte code) Word to emit is the next word WW WW. |
1071 | * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. |
1072 | */ |
1073 | word = 0; |
1074 | for (i = 253 * 2; i < mcode_size; i++) { |
1075 | if (mcode_data[i] == 0xff) { |
1076 | for (j = 0; j < mcode_data[i + 1]; j++) { |
1077 | ADW_WRITE_WORD_AUTO_INC_LRAM(iot, ioh,(((iot))->write_2(((ioh)), (0x06), (((((u_int16_t)mcode_data [i + 3] << 8) | mcode_data[i + 2]))))) |
1078 | (((u_int16_t)mcode_data[i + 3] << 8) |(((iot))->write_2(((ioh)), (0x06), (((((u_int16_t)mcode_data [i + 3] << 8) | mcode_data[i + 2]))))) |
1079 | mcode_data[i + 2]))(((iot))->write_2(((ioh)), (0x06), (((((u_int16_t)mcode_data [i + 3] << 8) | mcode_data[i + 2]))))); |
1080 | word++; |
1081 | } |
1082 | i += 3; |
1083 | } else if (mcode_data[i] == 0xfe) { |
1084 | ADW_WRITE_WORD_AUTO_INC_LRAM(iot, ioh,(((iot))->write_2(((ioh)), (0x06), (((((u_int16_t)mcode_data [i + 2] << 8) | mcode_data[i + 1]))))) |
1085 | (((u_int16_t)mcode_data[i + 2] << 8) |(((iot))->write_2(((ioh)), (0x06), (((((u_int16_t)mcode_data [i + 2] << 8) | mcode_data[i + 1]))))) |
1086 | mcode_data[i + 1]))(((iot))->write_2(((ioh)), (0x06), (((((u_int16_t)mcode_data [i + 2] << 8) | mcode_data[i + 1]))))); |
1087 | i += 2; |
1088 | word++; |
1089 | } else { |
1090 | ADW_WRITE_WORD_AUTO_INC_LRAM(iot, ioh, (((u_int16_t)(((iot))->write_2(((ioh)), (0x06), (((((u_int16_t) mcode_data [(mcode_data[i] * 2) + 1] <<8) | mcode_data[mcode_data[ i] * 2]))))) |
1091 | mcode_data[(mcode_data[i] * 2) + 1] <<8) |(((iot))->write_2(((ioh)), (0x06), (((((u_int16_t) mcode_data [(mcode_data[i] * 2) + 1] <<8) | mcode_data[mcode_data[ i] * 2]))))) |
1092 | mcode_data[mcode_data[i] * 2]))(((iot))->write_2(((ioh)), (0x06), (((((u_int16_t) mcode_data [(mcode_data[i] * 2) + 1] <<8) | mcode_data[mcode_data[ i] * 2]))))); |
1093 | word++; |
1094 | } |
1095 | } |
1096 | |
1097 | /* |
1098 | * Set 'word' for later use to clear the rest of memory and save |
1099 | * the expanded mcode size. |
1100 | */ |
1101 | word *= 2; |
1102 | adw_mcode_expanded_size = word; |
1103 | |
1104 | /* |
1105 | * Clear the rest of the Internal RAM. |
1106 | */ |
1107 | for (; word < adw_memsize; word += 2) { |
1108 | ADW_WRITE_WORD_AUTO_INC_LRAM(iot, ioh, 0)(((iot))->write_2(((ioh)), (0x06), ((0)))); |
1109 | } |
1110 | |
1111 | /* |
1112 | * Verify the microcode checksum. |
1113 | */ |
1114 | sum = 0; |
1115 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_RAM_ADDR, 0)(((iot))->write_2(((ioh)), ((0x04)), ((0)))); |
1116 | |
1117 | for (word = 0; word < adw_mcode_expanded_size; word += 2) { |
1118 | sum += ADW_READ_WORD_AUTO_INC_LRAM(iot, ioh)(((iot))->read_2(((ioh)), (0x06))); |
1119 | } |
1120 | |
1121 | if (sum != mcode_chksum) { |
1122 | return ADW_IERR_MCODE_CHKSUM0x0002; |
1123 | } |
1124 | |
1125 | /* |
1126 | * Restore the RISC memory BIOS region. |
1127 | */ |
1128 | for (i = 0; i < ADW_MC_BIOSLEN0x0050/2; i++) { |
1129 | if(chip_type == ADW_CHIP_ASC35500x01) { |
1130 | ADW_WRITE_BYTE_LRAM(iot, ioh, ADW_MC_BIOSMEM + (2 * i),do { (((iot))->write_2(((ioh)), (0x04), ((0x0040 + (2 * i) )))); (((iot))->write_1(((ioh)), (0x06), ((bios_mem[i])))) ; } while (0) |
1131 | bios_mem[i])do { (((iot))->write_2(((ioh)), (0x04), ((0x0040 + (2 * i) )))); (((iot))->write_1(((ioh)), (0x06), ((bios_mem[i])))) ; } while (0); |
1132 | } else { |
1133 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_BIOSMEM + (2 * i),do { (((iot))->write_2(((ioh)), (0x04), ((0x0040 + (2 * i) )))); (((iot))->write_2(((ioh)), (0x06), ((bios_mem[i])))) ; } while (0) |
1134 | bios_mem[i])do { (((iot))->write_2(((ioh)), (0x04), ((0x0040 + (2 * i) )))); (((iot))->write_2(((ioh)), (0x06), ((bios_mem[i])))) ; } while (0); |
1135 | } |
1136 | } |
1137 | |
1138 | /* |
1139 | * Calculate and write the microcode code checksum to the microcode |
1140 | * code checksum location ADW_MC_CODE_CHK_SUM (0x2C). |
1141 | */ |
1142 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_CODE_BEGIN_ADDR, begin_addr)do { (((iot))->write_2(((ioh)), (0x04), ((0x0028)))); (begin_addr ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
1143 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_CODE_END_ADDR, end_addr)do { (((iot))->write_2(((ioh)), (0x04), ((0x002A)))); (end_addr ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
1144 | code_sum = 0; |
1145 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_RAM_ADDR, begin_addr)(((iot))->write_2(((ioh)), ((0x04)), ((begin_addr)))); |
1146 | for (word = begin_addr; word < end_addr; word += 2) { |
1147 | code_sum += ADW_READ_WORD_AUTO_INC_LRAM(iot, ioh)(((iot))->read_2(((ioh)), (0x06))); |
1148 | } |
1149 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_CODE_CHK_SUM, code_sum)do { (((iot))->write_2(((ioh)), (0x04), ((0x002C)))); (((iot ))->write_2(((ioh)), (0x06), ((code_sum)))); } while (0); |
1150 | |
1151 | /* |
1152 | * Set the chip type. |
1153 | */ |
1154 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_CHIP_TYPE, chip_type)do { (((iot))->write_2(((ioh)), (0x04), ((0x009A)))); (((iot ))->write_2(((ioh)), (0x06), ((chip_type)))); } while (0); |
1155 | |
1156 | return 0; |
1157 | } |
1158 | |
1159 | |
1160 | int |
1161 | AdwASC3550Cabling(bus_space_tag_t iot, bus_space_handle_t ioh, ADW_DVC_CFG *cfg) |
1162 | { |
1163 | u_int16_t scsi_cfg1; |
1164 | |
1165 | |
1166 | /* |
1167 | * Determine SCSI_CFG1 Microcode Default Value. |
1168 | * |
1169 | * The microcode will set the SCSI_CFG1 register using this value |
1170 | * after it is started below. |
1171 | */ |
1172 | |
1173 | /* Read current SCSI_CFG1 Register value. */ |
1174 | scsi_cfg1 = ADW_READ_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1)(((iot))->read_2(((ioh)), ((0x0E)))); |
1175 | |
1176 | /* |
1177 | * If all three connectors are in use in ASC3550, return an error. |
1178 | */ |
1179 | if ((scsi_cfg1 & CABLE_ILLEGAL_A0x7) == 0 || |
1180 | (scsi_cfg1 & CABLE_ILLEGAL_B0xB) == 0) { |
1181 | return ADW_IERR_ILLEGAL_CONNECTION0x0400; |
1182 | } |
1183 | |
1184 | /* |
1185 | * If the cable is reversed all of the SCSI_CTRL register signals |
1186 | * will be set. Check for and return an error if this condition is |
1187 | * found. |
1188 | */ |
1189 | if ((ADW_READ_WORD_REGISTER(iot,ioh, IOPW_SCSI_CTRL)(((iot))->read_2(((ioh)), ((0x34)))) & 0x3F07)==0x3F07){ |
1190 | return ADW_IERR_REVERSED_CABLE0x1000; |
1191 | } |
1192 | |
1193 | /* |
1194 | * If this is a differential board and a single-ended device |
1195 | * is attached to one of the connectors, return an error. |
1196 | */ |
1197 | if ((scsi_cfg1 & ADW_DIFF_MODE0x0100) && |
1198 | (scsi_cfg1 & ADW_DIFF_SENSE0x0080) == 0) { |
1199 | return ADW_IERR_SINGLE_END_DEVICE0x0800; |
1200 | } |
1201 | |
1202 | /* |
1203 | * If automatic termination control is enabled, then set the |
1204 | * termination value based on a table listed in a_condor.h. |
1205 | * |
1206 | * If manual termination was specified with an EEPROM setting |
1207 | * then 'termination' was set-up in AdwInitFromEEPROM() and |
1208 | * is ready to be 'ored' into SCSI_CFG1. |
1209 | */ |
1210 | if (cfg->termination == 0) { |
1211 | /* |
1212 | * The software always controls termination by setting |
1213 | * TERM_CTL_SEL. |
1214 | * If TERM_CTL_SEL were set to 0, the hardware would set |
1215 | * termination. |
1216 | */ |
1217 | cfg->termination |= ADW_TERM_CTL_SEL0x0040; |
1218 | |
1219 | switch(scsi_cfg1 & ADW_CABLE_DETECT0x000F) { |
1220 | /* TERM_CTL_H: on, TERM_CTL_L: on */ |
1221 | case 0x3: case 0x7: case 0xB: |
1222 | case 0xD: case 0xE: case 0xF: |
1223 | cfg->termination |= |
1224 | (ADW_TERM_CTL_H0x0020 | ADW_TERM_CTL_L0x0010); |
1225 | break; |
1226 | |
1227 | /* TERM_CTL_H: on, TERM_CTL_L: off */ |
1228 | case 0x1: case 0x5: case 0x9: |
1229 | case 0xA: case 0xC: |
1230 | cfg->termination |= ADW_TERM_CTL_H0x0020; |
1231 | break; |
1232 | |
1233 | /* TERM_CTL_H: off, TERM_CTL_L: off */ |
1234 | case 0x2: case 0x6: |
1235 | break; |
1236 | } |
1237 | } |
1238 | |
1239 | /* |
1240 | * Clear any set TERM_CTL_H and TERM_CTL_L bits. |
1241 | */ |
1242 | scsi_cfg1 &= ~ADW_TERM_CTL0x0030; |
1243 | |
1244 | /* |
1245 | * Invert the TERM_CTL_H and TERM_CTL_L bits and then |
1246 | * set 'scsi_cfg1'. The TERM_POL bit does not need to be |
1247 | * referenced, because the hardware internally inverts |
1248 | * the Termination High and Low bits if TERM_POL is set. |
1249 | */ |
1250 | scsi_cfg1 |= (ADW_TERM_CTL_SEL0x0040 | (~cfg->termination & ADW_TERM_CTL0x0030)); |
1251 | |
1252 | /* |
1253 | * Set SCSI_CFG1 Microcode Default Value |
1254 | * |
1255 | * Set filter value and possibly modified termination control |
1256 | * bits in the Microcode SCSI_CFG1 Register Value. |
1257 | * |
1258 | * The microcode will set the SCSI_CFG1 register using this value |
1259 | * after it is started below. |
1260 | */ |
1261 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_SCSI_CFG1,do { (((iot))->write_2(((ioh)), (0x04), ((0x00AE)))); (((iot ))->write_2(((ioh)), (0x06), ((0x0000 | scsi_cfg1)))); } while (0) |
1262 | ADW_FLTR_DISABLE | scsi_cfg1)do { (((iot))->write_2(((ioh)), (0x04), ((0x00AE)))); (((iot ))->write_2(((ioh)), (0x06), ((0x0000 | scsi_cfg1)))); } while (0); |
1263 | |
1264 | /* |
1265 | * Set MEM_CFG Microcode Default Value |
1266 | * |
1267 | * The microcode will set the MEM_CFG register using this value |
1268 | * after it is started below. |
1269 | * |
1270 | * MEM_CFG may be accessed as a word or byte, but only bits 0-7 |
1271 | * are defined. |
1272 | * |
1273 | * ASC-3550 has 8KB internal memory. |
1274 | */ |
1275 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_MEM_CFG,do { (((iot))->write_2(((ioh)), (0x04), ((0x00B0)))); (((iot ))->write_2(((ioh)), (0x06), ((0x40 | 0x08)))); } while (0 ) |
1276 | ADW_BIOS_EN | ADW_RAM_SZ_8KB)do { (((iot))->write_2(((ioh)), (0x04), ((0x00B0)))); (((iot ))->write_2(((ioh)), (0x06), ((0x40 | 0x08)))); } while (0 ); |
1277 | |
1278 | return 0; |
1279 | } |
1280 | |
1281 | |
1282 | int |
1283 | AdwASC38C0800Cabling(bus_space_tag_t iot, bus_space_handle_t ioh, |
1284 | ADW_DVC_CFG *cfg) |
1285 | { |
1286 | u_int16_t scsi_cfg1; |
1287 | |
1288 | |
1289 | /* |
1290 | * Determine SCSI_CFG1 Microcode Default Value. |
1291 | * |
1292 | * The microcode will set the SCSI_CFG1 register using this value |
1293 | * after it is started below. |
1294 | */ |
1295 | |
1296 | /* Read current SCSI_CFG1 Register value. */ |
1297 | scsi_cfg1 = ADW_READ_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1)(((iot))->read_2(((ioh)), ((0x0E)))); |
1298 | |
1299 | /* |
1300 | * If the cable is reversed all of the SCSI_CTRL register signals |
1301 | * will be set. Check for and return an error if this condition is |
1302 | * found. |
1303 | */ |
1304 | if ((ADW_READ_WORD_REGISTER(iot,ioh, IOPW_SCSI_CTRL)(((iot))->read_2(((ioh)), ((0x34)))) & 0x3F07)==0x3F07){ |
1305 | return ADW_IERR_REVERSED_CABLE0x1000; |
1306 | } |
1307 | |
1308 | /* |
1309 | * All kind of combinations of devices attached to one of four |
1310 | * connectors are acceptable except HVD device attached. |
1311 | * For example, LVD device can be attached to SE connector while |
1312 | * SE device attached to LVD connector. |
1313 | * If LVD device attached to SE connector, it only runs up to |
1314 | * Ultra speed. |
1315 | * |
1316 | * If an HVD device is attached to one of LVD connectors, return |
1317 | * an error. |
1318 | * However, there is no way to detect HVD device attached to |
1319 | * SE connectors. |
1320 | */ |
1321 | if (scsi_cfg1 & ADW_HVD0x1000) { |
1322 | return ADW_IERR_HVD_DEVICE0x0100; |
1323 | } |
1324 | |
1325 | /* |
1326 | * If either SE or LVD automatic termination control is enabled, then |
1327 | * set the termination value based on a table listed in a_condor.h. |
1328 | * |
1329 | * If manual termination was specified with an EEPROM setting then |
1330 | * 'termination' was set-up in AdwInitFromEEPROM() and is ready |
1331 | * to be 'ored' into SCSI_CFG1. |
1332 | */ |
1333 | if ((cfg->termination & ADW_TERM_SE0x0030) == 0) { |
1334 | /* SE automatic termination control is enabled. */ |
1335 | switch(scsi_cfg1 & ADW_C_DET_SE0x0003) { |
1336 | /* TERM_SE_HI: on, TERM_SE_LO: on */ |
1337 | case 0x1: case 0x2: case 0x3: |
1338 | cfg->termination |= ADW_TERM_SE0x0030; |
1339 | break; |
1340 | |
1341 | /* TERM_SE_HI: on, TERM_SE_LO: off */ |
1342 | case 0x0: |
1343 | cfg->termination |= ADW_TERM_SE_HI0x0020; |
1344 | break; |
1345 | } |
1346 | } |
1347 | |
1348 | if ((cfg->termination & ADW_TERM_LVD0x00C0) == 0) { |
1349 | /* LVD automatic termination control is enabled. */ |
1350 | switch(scsi_cfg1 & ADW_C_DET_LVD0x000C) { |
1351 | /* TERM_LVD_HI: on, TERM_LVD_LO: on */ |
1352 | case 0x4: case 0x8: case 0xC: |
1353 | cfg->termination |= ADW_TERM_LVD0x00C0; |
1354 | break; |
1355 | |
1356 | /* TERM_LVD_HI: off, TERM_LVD_LO: off */ |
1357 | case 0x0: |
1358 | break; |
1359 | } |
1360 | } |
1361 | |
1362 | /* |
1363 | * Clear any set TERM_SE and TERM_LVD bits. |
1364 | */ |
1365 | scsi_cfg1 &= (~ADW_TERM_SE0x0030 & ~ADW_TERM_LVD0x00C0); |
1366 | |
1367 | /* |
1368 | * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'. |
1369 | */ |
1370 | scsi_cfg1 |= (~cfg->termination & 0xF0); |
1371 | |
1372 | /* |
1373 | * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and |
1374 | * HVD/LVD/SE bits and set possibly modified termination control bits |
1375 | * in the Microcode SCSI_CFG1 Register Value. |
1376 | */ |
1377 | scsi_cfg1 &= (~ADW_BIG_ENDIAN0x8000 & ~ADW_DIS_TERM_DRV0x4000 & |
1378 | ~ADW_TERM_POL0x2000 & ~ADW_HVD_LVD_SE0x1C00); |
1379 | |
1380 | /* |
1381 | * Set SCSI_CFG1 Microcode Default Value |
1382 | * |
1383 | * Set possibly modified termination control and reset DIS_TERM_DRV |
1384 | * bits in the Microcode SCSI_CFG1 Register Value. |
1385 | * |
1386 | * The microcode will set the SCSI_CFG1 register using this value |
1387 | * after it is started below. |
1388 | */ |
1389 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_SCSI_CFG1, scsi_cfg1)do { (((iot))->write_2(((ioh)), (0x04), ((0x00AE)))); (((iot ))->write_2(((ioh)), (0x06), ((scsi_cfg1)))); } while (0); |
1390 | |
1391 | /* |
1392 | * Set MEM_CFG Microcode Default Value |
1393 | * |
1394 | * The microcode will set the MEM_CFG register using this value |
1395 | * after it is started below. |
1396 | * |
1397 | * MEM_CFG may be accessed as a word or byte, but only bits 0-7 |
1398 | * are defined. |
1399 | * |
1400 | * ASC-38C0800 has 16KB internal memory. |
1401 | */ |
1402 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_MEM_CFG,do { (((iot))->write_2(((ioh)), (0x04), ((0x00B0)))); (((iot ))->write_2(((ioh)), (0x06), ((0x40 | 0x0C)))); } while (0 ) |
1403 | ADW_BIOS_EN | ADW_RAM_SZ_16KB)do { (((iot))->write_2(((ioh)), (0x04), ((0x00B0)))); (((iot ))->write_2(((ioh)), (0x06), ((0x40 | 0x0C)))); } while (0 ); |
1404 | |
1405 | return 0; |
1406 | } |
1407 | |
1408 | |
1409 | int |
1410 | AdwASC38C1600Cabling(bus_space_tag_t iot, bus_space_handle_t ioh, |
1411 | ADW_DVC_CFG *cfg) |
1412 | { |
1413 | u_int16_t scsi_cfg1; |
1414 | |
1415 | |
1416 | /* |
1417 | * Determine SCSI_CFG1 Microcode Default Value. |
1418 | * |
1419 | * The microcode will set the SCSI_CFG1 register using this value |
1420 | * after it is started below. |
1421 | * Each ASC-38C1600 function has only two cable detect bits. |
1422 | * The bus mode override bits are in IOPB_SOFT_OVER_WR. |
1423 | */ |
1424 | |
1425 | /* Read current SCSI_CFG1 Register value. */ |
1426 | scsi_cfg1 = ADW_READ_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1)(((iot))->read_2(((ioh)), ((0x0E)))); |
1427 | |
1428 | /* |
1429 | * If the cable is reversed all of the SCSI_CTRL register signals |
1430 | * will be set. Check for and return an error if this condition is |
1431 | * found. |
1432 | */ |
1433 | if ((ADW_READ_WORD_REGISTER(iot,ioh, IOPW_SCSI_CTRL)(((iot))->read_2(((ioh)), ((0x34)))) & 0x3F07)==0x3F07){ |
1434 | return ADW_IERR_REVERSED_CABLE0x1000; |
1435 | } |
1436 | |
1437 | /* |
1438 | * Each ASC-38C1600 function has two connectors. Only an HVD device |
1439 | * cannot be connected to either connector. An LVD device or SE device |
1440 | * may be connected to either connector. If an SE device is connected, |
1441 | * then at most Ultra speed (20 MHz) can be used on both connectors. |
1442 | * |
1443 | * If an HVD device is attached, return an error. |
1444 | */ |
1445 | if (scsi_cfg1 & ADW_HVD0x1000) { |
1446 | return ADW_IERR_HVD_DEVICE0x0100; |
1447 | } |
1448 | |
1449 | /* |
1450 | * Each function in the ASC-38C1600 uses only the SE cable detect and |
1451 | * termination because there are two connectors for each function. |
1452 | * Each function may use either LVD or SE mode. |
1453 | * Corresponding the SE automatic termination control EEPROM bits are |
1454 | * used for each function. |
1455 | * Each function has its own EEPROM. If SE automatic control is enabled |
1456 | * for the function, then set the termination value based on a table |
1457 | * listed in adwlib.h. |
1458 | * |
1459 | * If manual termination is specified in the EEPROM for the function, |
1460 | * then 'termination' was set-up in AdwInitFromEEPROM() and is |
1461 | * ready to be 'ored' into SCSI_CFG1. |
1462 | */ |
1463 | if ((cfg->termination & ADW_TERM_SE0x0030) == 0) { |
1464 | /* SE automatic termination control is enabled. */ |
1465 | switch(scsi_cfg1 & ADW_C_DET_SE0x0003) { |
1466 | /* TERM_SE_HI: on, TERM_SE_LO: on */ |
1467 | case 0x1: case 0x2: case 0x3: |
1468 | cfg->termination |= ADW_TERM_SE0x0030; |
1469 | break; |
1470 | |
1471 | case 0x0: |
1472 | /* !!!!TODO!!!! */ |
1473 | // if (ASC_PCI_ID2FUNC(cfg->pci_slot_info) == 0) { |
1474 | /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */ |
1475 | // } |
1476 | // else |
1477 | // { |
1478 | /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */ |
1479 | cfg->termination |= ADW_TERM_SE_HI0x0020; |
1480 | // } |
1481 | break; |
1482 | } |
1483 | } |
1484 | |
1485 | /* |
1486 | * Clear any set TERM_SE bits. |
1487 | */ |
1488 | scsi_cfg1 &= ~ADW_TERM_SE0x0030; |
1489 | |
1490 | /* |
1491 | * Invert the TERM_SE bits and then set 'scsi_cfg1'. |
1492 | */ |
1493 | scsi_cfg1 |= (~cfg->termination & ADW_TERM_SE0x0030); |
1494 | |
1495 | /* |
1496 | * Clear Big Endian and Terminator Polarity bits and set possibly |
1497 | * modified termination control bits in the Microcode SCSI_CFG1 |
1498 | * Register Value. |
1499 | */ |
1500 | scsi_cfg1 &= (~ADW_BIG_ENDIAN0x8000 & ~ADW_DIS_TERM_DRV0x4000 & ~ADW_TERM_POL0x2000); |
1501 | |
1502 | /* |
1503 | * Set SCSI_CFG1 Microcode Default Value |
1504 | * |
1505 | * Set possibly modified termination control bits in the Microcode |
1506 | * SCSI_CFG1 Register Value. |
1507 | * |
1508 | * The microcode will set the SCSI_CFG1 register using this value |
1509 | * after it is started below. |
1510 | */ |
1511 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_SCSI_CFG1, scsi_cfg1)do { (((iot))->write_2(((ioh)), (0x04), ((0x00AE)))); (((iot ))->write_2(((ioh)), (0x06), ((scsi_cfg1)))); } while (0); |
1512 | |
1513 | /* |
1514 | * Set MEM_CFG Microcode Default Value |
1515 | * |
1516 | * The microcode will set the MEM_CFG register using this value |
1517 | * after it is started below. |
1518 | * |
1519 | * MEM_CFG may be accessed as a word or byte, but only bits 0-7 |
1520 | * are defined. |
1521 | * |
1522 | * ASC-38C1600 has 32KB internal memory. |
1523 | */ |
1524 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_MEM_CFG,do { (((iot))->write_2(((ioh)), (0x04), ((0x00B0)))); (((iot ))->write_2(((ioh)), (0x06), ((0x40 | 0x10)))); } while (0 ) |
1525 | ADW_BIOS_EN | ADW_RAM_SZ_32KB)do { (((iot))->write_2(((ioh)), (0x04), ((0x00B0)))); (((iot ))->write_2(((ioh)), (0x06), ((0x40 | 0x10)))); } while (0 ); |
1526 | |
1527 | return 0; |
1528 | } |
1529 | |
1530 | |
1531 | /* |
1532 | * Read EEPROM configuration into the specified buffer. |
1533 | * |
1534 | * Return a checksum based on the EEPROM configuration read. |
1535 | */ |
1536 | u_int16_t |
1537 | AdwGetEEPROMConfig(bus_space_tag_t iot, bus_space_handle_t ioh, |
1538 | ADW_EEPROM *cfg_buf) |
1539 | { |
1540 | u_int16_t wval, chksum; |
1541 | u_int16_t *wbuf; |
1542 | int eep_addr; |
1543 | |
1544 | |
1545 | wbuf = (u_int16_t *) cfg_buf; |
1546 | chksum = 0; |
1547 | |
1548 | for (eep_addr = ADW_EEP_DVC_CFG_BEGIN(0x00); |
1549 | eep_addr < ADW_EEP_DVC_CFG_END(0x15); |
1550 | eep_addr++, wbuf++) { |
1551 | wval = AdwReadEEPWord(iot, ioh, eep_addr); |
1552 | chksum += wval; |
1553 | *wbuf = wval; |
1554 | } |
1555 | |
1556 | *wbuf = AdwReadEEPWord(iot, ioh, eep_addr); |
1557 | wbuf++; |
1558 | for (eep_addr = ADW_EEP_DVC_CTL_BEGIN(0x16); |
1559 | eep_addr < ADW_EEP_MAX_WORD_ADDR(0x1E); |
1560 | eep_addr++, wbuf++) { |
1561 | *wbuf = AdwReadEEPWord(iot, ioh, eep_addr); |
1562 | } |
1563 | |
1564 | return chksum; |
1565 | } |
1566 | |
1567 | |
1568 | /* |
1569 | * Read the EEPROM from specified location |
1570 | */ |
1571 | u_int16_t |
1572 | AdwReadEEPWord(bus_space_tag_t iot, bus_space_handle_t ioh, int eep_word_addr) |
1573 | { |
1574 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD,(((iot))->write_2(((ioh)), ((0x1A)), ((0x80 | eep_word_addr )))) |
1575 | ADW_EEP_CMD_READ | eep_word_addr)(((iot))->write_2(((ioh)), ((0x1A)), ((0x80 | eep_word_addr )))); |
1576 | AdwWaitEEPCmd(iot, ioh); |
1577 | |
1578 | return ADW_READ_WORD_REGISTER(iot, ioh, IOPW_EE_DATA)(((iot))->read_2(((ioh)), ((0x1C)))); |
1579 | } |
1580 | |
1581 | |
1582 | /* |
1583 | * Wait for EEPROM command to complete |
1584 | */ |
1585 | void |
1586 | AdwWaitEEPCmd(bus_space_tag_t iot, bus_space_handle_t ioh) |
1587 | { |
1588 | int eep_delay_ms; |
1589 | |
1590 | |
1591 | for (eep_delay_ms = 0; eep_delay_ms < ADW_EEP_DELAY_MS100; eep_delay_ms++){ |
1592 | if (ADW_READ_WORD_REGISTER(iot, ioh, IOPW_EE_CMD)(((iot))->read_2(((ioh)), ((0x1A)))) & |
1593 | ADW_EEP_CMD_DONE0x0200) { |
1594 | break; |
1595 | } |
1596 | AdwSleepMilliSecond(1); |
1597 | } |
1598 | |
1599 | ADW_READ_WORD_REGISTER(iot, ioh, IOPW_EE_CMD)(((iot))->read_2(((ioh)), ((0x1A)))); |
1600 | } |
1601 | |
1602 | |
1603 | /* |
1604 | * Write the EEPROM from 'cfg_buf'. |
1605 | */ |
1606 | void |
1607 | AdwSetEEPROMConfig(bus_space_tag_t iot, bus_space_handle_t ioh, |
1608 | ADW_EEPROM *cfg_buf) |
1609 | { |
1610 | u_int16_t *wbuf; |
1611 | u_int16_t addr, chksum; |
1612 | |
1613 | |
1614 | wbuf = (u_int16_t *) cfg_buf; |
1615 | chksum = 0; |
1616 | |
1617 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD, ADW_EEP_CMD_WRITE_ABLE)(((iot))->write_2(((ioh)), ((0x1A)), ((0x30)))); |
1618 | AdwWaitEEPCmd(iot, ioh); |
1619 | |
1620 | /* |
1621 | * Write EEPROM from word 0 to word 20 |
1622 | */ |
1623 | for (addr = ADW_EEP_DVC_CFG_BEGIN(0x00); |
1624 | addr < ADW_EEP_DVC_CFG_END(0x15); addr++, wbuf++) { |
1625 | chksum += *wbuf; |
1626 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_DATA, *wbuf)(((iot))->write_2(((ioh)), ((0x1C)), ((*wbuf)))); |
1627 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD,(((iot))->write_2(((ioh)), ((0x1A)), ((0x40 | addr)))) |
1628 | ADW_EEP_CMD_WRITE | addr)(((iot))->write_2(((ioh)), ((0x1A)), ((0x40 | addr)))); |
1629 | AdwWaitEEPCmd(iot, ioh); |
1630 | AdwSleepMilliSecond(ADW_EEP_DELAY_MS100); |
1631 | } |
1632 | |
1633 | /* |
1634 | * Write EEPROM checksum at word 21 |
1635 | */ |
1636 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_DATA, chksum)(((iot))->write_2(((ioh)), ((0x1C)), ((chksum)))); |
1637 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD,(((iot))->write_2(((ioh)), ((0x1A)), ((0x40 | addr)))) |
1638 | ADW_EEP_CMD_WRITE | addr)(((iot))->write_2(((ioh)), ((0x1A)), ((0x40 | addr)))); |
1639 | AdwWaitEEPCmd(iot, ioh); |
1640 | wbuf++; /* skip over check_sum */ |
1641 | |
1642 | /* |
1643 | * Write EEPROM OEM name at words 22 to 29 |
1644 | */ |
1645 | for (addr = ADW_EEP_DVC_CTL_BEGIN(0x16); |
1646 | addr < ADW_EEP_MAX_WORD_ADDR(0x1E); addr++, wbuf++) { |
1647 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_DATA, *wbuf)(((iot))->write_2(((ioh)), ((0x1C)), ((*wbuf)))); |
1648 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD,(((iot))->write_2(((ioh)), ((0x1A)), ((0x40 | addr)))) |
1649 | ADW_EEP_CMD_WRITE | addr)(((iot))->write_2(((ioh)), ((0x1A)), ((0x40 | addr)))); |
1650 | AdwWaitEEPCmd(iot, ioh); |
1651 | } |
1652 | |
1653 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD,(((iot))->write_2(((ioh)), ((0x1A)), ((0x00)))) |
1654 | ADW_EEP_CMD_WRITE_DISABLE)(((iot))->write_2(((ioh)), ((0x1A)), ((0x00)))); |
1655 | AdwWaitEEPCmd(iot, ioh); |
1656 | |
1657 | return; |
1658 | } |
1659 | |
1660 | |
1661 | /* |
1662 | * AdwExeScsiQueue() - Send a request to the RISC microcode program. |
1663 | * |
1664 | * Allocate a carrier structure, point the carrier to the ADW_SCSI_REQ_Q, |
1665 | * add the carrier to the ICQ (Initiator Command Queue), and tickle the |
1666 | * RISC to notify it a new command is ready to be executed. |
1667 | * |
1668 | * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be |
1669 | * set to SCSI_MAX_RETRY. |
1670 | * |
1671 | * Return: |
1672 | * ADW_SUCCESS(1) - The request was successfully queued. |
1673 | * ADW_BUSY(0) - Resource unavailable; Retry again after pending |
1674 | * request completes. |
1675 | * ADW_ERROR(-1) - Invalid ADW_SCSI_REQ_Q request structure |
1676 | * host IC error. |
1677 | */ |
1678 | int |
1679 | AdwExeScsiQueue(ADW_SOFTC *sc, ADW_SCSI_REQ_Q *scsiq) |
1680 | { |
1681 | bus_space_tag_t iot = sc->sc_iot; |
1682 | bus_space_handle_t ioh = sc->sc_ioh; |
1683 | ADW_CCB *ccb; |
1684 | long req_size; |
1685 | u_int32_t req_paddr; |
1686 | ADW_CARRIER *new_carrp; |
1687 | |
1688 | /* |
1689 | * The ADW_SCSI_REQ_Q 'target_id' field should never exceed ADW_MAX_TID. |
1690 | */ |
1691 | if (scsiq->target_id > ADW_MAX_TID15) { |
1692 | scsiq->host_status = QHSTA_M_INVALID_DEVICE0x45; |
1693 | scsiq->done_status = QD_WITH_ERROR0x04; |
1694 | return ADW_ERROR(-1); |
1695 | } |
1696 | |
1697 | /* |
1698 | * Beginning of CRITICAL SECTION: ASSUME splbio() in effect |
1699 | */ |
1700 | |
1701 | ccb = adw_ccb_phys_kv(sc, scsiq->ccb_ptr); |
1702 | |
1703 | /* |
1704 | * Allocate a carrier and initialize fields. |
1705 | */ |
1706 | if ((new_carrp = sc->carr_freelist) == NULL((void *)0)) { |
1707 | return ADW_BUSY0; |
1708 | } |
1709 | sc->carr_freelist = ADW_CARRIER_VADDR(sc,((ADW_CARRIER *) (((u_int8_t *)(sc)->sc_control->carriers ) + ((u_long)((new_carrp->next_ba) & 0xFFFFFFF0)) - (sc )->sc_dmamap_carrier->dm_segs[0].ds_addr)) |
1710 | ADW_GET_CARRP(new_carrp->next_ba))((ADW_CARRIER *) (((u_int8_t *)(sc)->sc_control->carriers ) + ((u_long)((new_carrp->next_ba) & 0xFFFFFFF0)) - (sc )->sc_dmamap_carrier->dm_segs[0].ds_addr)); |
1711 | sc->carr_pending_cnt++; |
1712 | |
1713 | /* |
1714 | * Set the carrier to be a stopper by setting 'next_ba' |
1715 | * to the stopper value. The current stopper will be changed |
1716 | * below to point to the new stopper. |
1717 | */ |
1718 | new_carrp->next_ba = ADW_CQ_STOPPER0x00000000; |
1719 | |
1720 | req_size = sizeof(ADW_SCSI_REQ_Q); |
Value stored to 'req_size' is never read | |
1721 | req_paddr = sc->sc_dmamap_control->dm_segs[0].ds_addr + |
1722 | ADW_CCB_OFF(ccb)(__builtin_offsetof(struct adw_control, ccbs[0]) + (((u_long) (ccb)) - ((u_long)&sc->sc_control->ccbs[0]))) + offsetof(struct adw_ccb, scsiq)__builtin_offsetof(struct adw_ccb, scsiq); |
1723 | |
1724 | /* Save physical address of ADW_SCSI_REQ_Q and Carrier. */ |
1725 | scsiq->scsiq_rptr = req_paddr; |
1726 | |
1727 | /* |
1728 | * Every ADW_SCSI_REQ_Q.carr_ba is byte swapped to little-endian |
1729 | * order during initialization. |
1730 | */ |
1731 | scsiq->carr_ba = sc->icq_sp->carr_ba; |
1732 | scsiq->carr_va = sc->icq_sp->carr_ba; |
1733 | |
1734 | /* |
1735 | * Use the current stopper to send the ADW_SCSI_REQ_Q command to |
1736 | * the microcode. The newly allocated stopper will become the new |
1737 | * stopper. |
1738 | */ |
1739 | sc->icq_sp->areq_ba = req_paddr; |
1740 | |
1741 | /* |
1742 | * Set the 'next_ba' pointer for the old stopper to be the |
1743 | * physical address of the new stopper. The RISC can only |
1744 | * follow physical addresses. |
1745 | */ |
1746 | sc->icq_sp->next_ba = new_carrp->carr_ba; |
1747 | |
1748 | #if ADW_DEBUG |
1749 | printf("icq 0x%x, 0x%x, 0x%x, 0x%x\n", |
1750 | sc->icq_sp->carr_id, |
1751 | sc->icq_sp->carr_ba, |
1752 | sc->icq_sp->areq_ba, |
1753 | sc->icq_sp->next_ba); |
1754 | #endif |
1755 | /* |
1756 | * Set the host adapter stopper pointer to point to the new carrier. |
1757 | */ |
1758 | sc->icq_sp = new_carrp; |
1759 | |
1760 | if (sc->chip_type == ADW_CHIP_ASC35500x01 || |
1761 | sc->chip_type == ADW_CHIP_ASC38C08000x02) { |
1762 | /* |
1763 | * Tickle the RISC to tell it to read its Command Queue Head |
1764 | * pointer. |
1765 | */ |
1766 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_TICKLE, ADW_TICKLE_A)(((iot))->write_1(((ioh)), ((0x22)), ((0x01)))); |
1767 | if (sc->chip_type == ADW_CHIP_ASC35500x01) { |
1768 | /* |
1769 | * Clear the tickle value. In the ASC-3550 the RISC flag |
1770 | * command 'clr_tickle_a' does not work unless the host |
1771 | * value is cleared. |
1772 | */ |
1773 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_TICKLE,(((iot))->write_1(((ioh)), ((0x22)), ((0x00)))) |
1774 | ADW_TICKLE_NOP)(((iot))->write_1(((ioh)), ((0x22)), ((0x00)))); |
1775 | } |
1776 | } else if (sc->chip_type == ADW_CHIP_ASC38C16000x03) { |
1777 | /* |
1778 | * Notify the RISC a carrier is ready by writing the physical |
1779 | * address of the new carrier stopper to the COMMA register. |
1780 | */ |
1781 | ADW_WRITE_DWORD_REGISTER(iot, ioh, IOPDW_COMMA,(((iot))->write_4(((ioh)), ((0x14)), ((new_carrp->carr_ba )))) |
1782 | new_carrp->carr_ba)(((iot))->write_4(((ioh)), ((0x14)), ((new_carrp->carr_ba )))); |
1783 | } |
1784 | |
1785 | /* |
1786 | * End of CRITICAL SECTION: Must be protected within splbio/splx pair |
1787 | */ |
1788 | |
1789 | return ADW_SUCCESS1; |
1790 | } |
1791 | |
1792 | |
1793 | void |
1794 | AdwResetChip(bus_space_tag_t iot, bus_space_handle_t ioh) |
1795 | { |
1796 | |
1797 | /* |
1798 | * Reset Chip. |
1799 | */ |
1800 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_CTRL_REG,(((iot))->write_2(((ioh)), ((0x02)), ((0x00C6)))) |
1801 | ADW_CTRL_REG_CMD_RESET)(((iot))->write_2(((ioh)), ((0x02)), ((0x00C6)))); |
1802 | AdwSleepMilliSecond(100); |
1803 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_CTRL_REG,(((iot))->write_2(((ioh)), ((0x02)), ((0x00C5)))) |
1804 | ADW_CTRL_REG_CMD_WR_IO_REG)(((iot))->write_2(((ioh)), ((0x02)), ((0x00C5)))); |
1805 | } |
1806 | |
1807 | |
1808 | /* |
1809 | * Reset SCSI Bus and purge all outstanding requests. |
1810 | * |
1811 | * Return Value: |
1812 | * ADW_TRUE(1) - All requests are purged and SCSI Bus is reset. |
1813 | * ADW_FALSE(0) - Microcode command failed. |
1814 | * ADW_ERROR(-1) - Microcode command timed-out. Microcode or IC |
1815 | * may be hung which requires driver recovery. |
1816 | */ |
1817 | int |
1818 | AdwResetCCB(ADW_SOFTC *sc) |
1819 | { |
1820 | int status; |
1821 | |
1822 | /* |
1823 | * Send the SCSI Bus Reset idle start idle command which asserts |
1824 | * the SCSI Bus Reset signal. |
1825 | */ |
1826 | status = AdwSendIdleCmd(sc, (u_int16_t) IDLE_CMD_SCSI_RESET_START0x0020, 0L); |
1827 | if (status != ADW_TRUE1) { |
1828 | return status; |
1829 | } |
1830 | |
1831 | /* |
1832 | * Delay for the specified SCSI Bus Reset hold time. |
1833 | * |
1834 | * The hold time delay is done on the host because the RISC has no |
1835 | * microsecond accurate timer. |
1836 | */ |
1837 | AdwDelayMicroSecond((u_int16_t) ADW_SCSI_RESET_HOLD_TIME_US60); |
1838 | |
1839 | /* |
1840 | * Send the SCSI Bus Reset end idle command which de-asserts |
1841 | * the SCSI Bus Reset signal and purges any pending requests. |
1842 | */ |
1843 | status = AdwSendIdleCmd(sc, (u_int16_t) IDLE_CMD_SCSI_RESET_END0x0040, 0L); |
1844 | if (status != ADW_TRUE1) { |
1845 | return status; |
1846 | } |
1847 | |
1848 | AdwSleepMilliSecond((u_int32_t) sc->scsi_reset_wait * 1000); |
1849 | |
1850 | return status; |
1851 | } |
1852 | |
1853 | |
1854 | /* |
1855 | * Reset chip and SCSI Bus. |
1856 | * |
1857 | * Return Value: |
1858 | * ADW_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful. |
1859 | * ADW_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure. |
1860 | */ |
1861 | int |
1862 | AdwResetSCSIBus(ADW_SOFTC *sc) |
1863 | { |
1864 | bus_space_tag_t iot = sc->sc_iot; |
1865 | bus_space_handle_t ioh = sc->sc_ioh; |
1866 | int status; |
1867 | u_int16_t wdtr_able, sdtr_able, ppr_able = 0, tagqng_able; |
1868 | u_int8_t tid, max_cmd[ADW_MAX_TID15 + 1]; |
1869 | u_int16_t bios_sig; |
1870 | |
1871 | |
1872 | /* |
1873 | * Save current per TID negotiated values. |
1874 | */ |
1875 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE, wdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (wdtr_able ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
1876 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE, sdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x009E)))); (sdtr_able ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
1877 | if (sc->chip_type == ADW_CHIP_ASC38C16000x03) { |
1878 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_PPR_ABLE, ppr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x017A)))); (ppr_able ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
1879 | } |
1880 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE, tagqng_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A0)))); (tagqng_able ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
1881 | for (tid = 0; tid <= ADW_MAX_TID15; tid++) { |
1882 | ADW_READ_BYTE_LRAM(iot, ioh, ADW_MC_NUMBER_OF_MAX_CMD + tid,do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (max_cmd[tid]) = (((iot))->read_1(((ioh)), (0x06))); } while (0) |
1883 | max_cmd[tid])do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (max_cmd[tid]) = (((iot))->read_1(((ioh)), (0x06))); } while (0); |
1884 | } |
1885 | |
1886 | /* |
1887 | * Force the AdwInitAscDriver() function to perform a SCSI Bus Reset |
1888 | * by clearing the BIOS signature word. |
1889 | * The initialization functions assumes a SCSI Bus Reset is not |
1890 | * needed if the BIOS signature word is present. |
1891 | */ |
1892 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_BIOS_SIGNATURE, bios_sig)do { (((iot))->write_2(((ioh)), (0x04), ((0x0058)))); (bios_sig ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
1893 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_BIOS_SIGNATURE, 0)do { (((iot))->write_2(((ioh)), (0x04), ((0x0058)))); (((iot ))->write_2(((ioh)), (0x06), ((0)))); } while (0); |
1894 | |
1895 | /* |
1896 | * Stop chip and reset it. |
1897 | */ |
1898 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_RISC_CSR, ADW_RISC_CSR_STOP)(((iot))->write_2(((ioh)), ((0x0A)), (((0x0000))))); |
1899 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_CTRL_REG,(((iot))->write_2(((ioh)), ((0x02)), ((0x00C6)))) |
1900 | ADW_CTRL_REG_CMD_RESET)(((iot))->write_2(((ioh)), ((0x02)), ((0x00C6)))); |
1901 | AdwSleepMilliSecond(100); |
1902 | ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_CTRL_REG,(((iot))->write_2(((ioh)), ((0x02)), ((0x00C5)))) |
1903 | ADW_CTRL_REG_CMD_WR_IO_REG)(((iot))->write_2(((ioh)), ((0x02)), ((0x00C5)))); |
1904 | |
1905 | /* |
1906 | * Reset Adw Library error code, if any, and try |
1907 | * re-initializing the chip. |
1908 | * Then translate initialization return value to status value. |
1909 | */ |
1910 | status = (AdwInitDriver(sc) == 0)? ADW_TRUE1 : ADW_FALSE0; |
1911 | |
1912 | /* |
1913 | * Restore the BIOS signature word. |
1914 | */ |
1915 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_BIOS_SIGNATURE, bios_sig)do { (((iot))->write_2(((ioh)), (0x04), ((0x0058)))); (((iot ))->write_2(((ioh)), (0x06), ((bios_sig)))); } while (0); |
1916 | |
1917 | /* |
1918 | * Restore per TID negotiated values. |
1919 | */ |
1920 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE, wdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (((iot ))->write_2(((ioh)), (0x06), ((wdtr_able)))); } while (0); |
1921 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE, sdtr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x009E)))); (((iot ))->write_2(((ioh)), (0x06), ((sdtr_able)))); } while (0); |
1922 | if (sc->chip_type == ADW_CHIP_ASC38C16000x03) { |
1923 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_PPR_ABLE, ppr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x017A)))); (((iot ))->write_2(((ioh)), (0x06), ((ppr_able)))); } while (0); |
1924 | } |
1925 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE, tagqng_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A0)))); (((iot ))->write_2(((ioh)), (0x06), ((tagqng_able)))); } while (0 ); |
1926 | for (tid = 0; tid <= ADW_MAX_TID15; tid++) { |
1927 | ADW_WRITE_BYTE_LRAM(iot, ioh, ADW_MC_NUMBER_OF_MAX_CMD + tid,do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (((iot))->write_1(((ioh)), (0x06), ((max_cmd[tid])))); } while (0) |
1928 | max_cmd[tid])do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (((iot))->write_1(((ioh)), (0x06), ((max_cmd[tid])))); } while (0); |
1929 | } |
1930 | |
1931 | return status; |
1932 | } |
1933 | |
1934 | |
1935 | /* |
1936 | * Adw Library Interrupt Service Routine |
1937 | * |
1938 | * This function is called by a driver's interrupt service routine. |
1939 | * The function disables and re-enables interrupts. |
1940 | * |
1941 | * Note: AdwISR() can be called when interrupts are disabled or even |
1942 | * when there is no hardware interrupt condition present. It will |
1943 | * always check for completed idle commands and microcode requests. |
1944 | * This is an important feature that shouldn't be changed because it |
1945 | * allows commands to be completed from polling mode loops. |
1946 | * |
1947 | * Return: |
1948 | * ADW_TRUE(1) - interrupt was pending |
1949 | * ADW_FALSE(0) - no interrupt was pending |
1950 | */ |
1951 | int |
1952 | AdwISR(ADW_SOFTC *sc) |
1953 | { |
1954 | bus_space_tag_t iot = sc->sc_iot; |
1955 | bus_space_handle_t ioh = sc->sc_ioh; |
1956 | u_int8_t int_stat; |
1957 | u_int16_t target_bit; |
1958 | ADW_CARRIER *free_carrp/*, *ccb_carr*/; |
1959 | u_int32_t irq_next_pa; |
1960 | ADW_SCSI_REQ_Q *scsiq; |
1961 | ADW_CCB *ccb; |
1962 | int s; |
1963 | |
1964 | |
1965 | s = splbio()splraise(0x3); |
1966 | |
1967 | /* Reading the register clears the interrupt. */ |
1968 | int_stat = ADW_READ_BYTE_REGISTER(iot, ioh, IOPB_INTR_STATUS_REG)(((iot))->read_1(((ioh)), ((0x00)))); |
1969 | |
1970 | if ((int_stat & (ADW_INTR_STATUS_INTRA0x01 | ADW_INTR_STATUS_INTRB0x02 | |
1971 | ADW_INTR_STATUS_INTRC0x04)) == 0) { |
1972 | splx(s)spllower(s); |
1973 | return ADW_FALSE0; |
1974 | } |
1975 | |
1976 | /* |
1977 | * Notify the driver of an asynchronous microcode condition by |
1978 | * calling the ADW_SOFTC.async_callback function. The function |
1979 | * is passed the microcode ADW_MC_INTRB_CODE byte value. |
1980 | */ |
1981 | if (int_stat & ADW_INTR_STATUS_INTRB0x02) { |
1982 | u_int8_t intrb_code; |
1983 | |
1984 | ADW_READ_BYTE_LRAM(iot, ioh, ADW_MC_INTRB_CODE, intrb_code)do { (((iot))->write_2(((ioh)), (0x04), ((0x009B)))); (intrb_code ) = (((iot))->read_1(((ioh)), (0x06))); } while (0); |
1985 | |
1986 | if (sc->chip_type == ADW_CHIP_ASC35500x01 || |
1987 | sc->chip_type == ADW_CHIP_ASC38C08000x02) { |
1988 | if (intrb_code == ADW_ASYNC_CARRIER_READY_FAILURE0x03 && |
1989 | sc->carr_pending_cnt != 0) { |
1990 | ADW_WRITE_BYTE_REGISTER(iot, ioh,(((iot))->write_1(((ioh)), ((0x22)), ((0x01)))) |
1991 | IOPB_TICKLE, ADW_TICKLE_A)(((iot))->write_1(((ioh)), ((0x22)), ((0x01)))); |
1992 | if (sc->chip_type == ADW_CHIP_ASC35500x01) { |
1993 | ADW_WRITE_BYTE_REGISTER(iot, ioh,(((iot))->write_1(((ioh)), ((0x22)), ((0x00)))) |
1994 | IOPB_TICKLE, ADW_TICKLE_NOP)(((iot))->write_1(((ioh)), ((0x22)), ((0x00)))); |
1995 | } |
1996 | } |
1997 | } |
1998 | |
1999 | if (sc->async_callback != 0) { |
2000 | (*(ADW_ASYNC_CALLBACK)sc->async_callback)(sc, intrb_code); |
2001 | } |
2002 | } |
2003 | |
2004 | /* |
2005 | * Check if the IRQ stopper carrier contains a completed request. |
2006 | */ |
2007 | while (((irq_next_pa = sc->irq_sp->next_ba) & ADW_RQ_DONE0x00000001) != 0) |
2008 | { |
2009 | #if ADW_DEBUG |
2010 | printf("irq 0x%x, 0x%x, 0x%x, 0x%x\n", |
2011 | sc->irq_sp->carr_id, |
2012 | sc->irq_sp->carr_ba, |
2013 | sc->irq_sp->areq_ba, |
2014 | sc->irq_sp->next_ba); |
2015 | #endif |
2016 | /* |
2017 | * Get a pointer to the newly completed ADW_SCSI_REQ_Q |
2018 | * structure. |
2019 | * The RISC will have set 'areq_ba' to a virtual address. |
2020 | * |
2021 | * The firmware will have copied the ADW_SCSI_REQ_Q.ccb_ptr |
2022 | * field to the carrier ADW_CARRIER.areq_ba field. |
2023 | * The conversion below complements the conversion of |
2024 | * ADW_SCSI_REQ_Q.ccb_ptr' in AdwExeScsiQueue(). |
2025 | */ |
2026 | ccb = adw_ccb_phys_kv(sc, sc->irq_sp->areq_ba); |
2027 | scsiq = &ccb->scsiq; |
2028 | scsiq->ccb_ptr = sc->irq_sp->areq_ba; |
2029 | |
2030 | /* |
2031 | * Request finished with good status and the queue was not |
2032 | * DMAed to host memory by the firmware. Set all status fields |
2033 | * to indicate good status. |
2034 | */ |
2035 | if ((irq_next_pa & ADW_RQ_GOOD0x00000002) != 0) { |
2036 | scsiq->done_status = QD_NO_ERROR0x01; |
2037 | scsiq->host_status = scsiq->scsi_status = 0; |
2038 | scsiq->data_cnt = 0L; |
2039 | } |
2040 | |
2041 | /* |
2042 | * Advance the stopper pointer to the next carrier |
2043 | * ignoring the lower four bits. Free the previous |
2044 | * stopper carrier. |
2045 | */ |
2046 | free_carrp = sc->irq_sp; |
2047 | sc->irq_sp = ADW_CARRIER_VADDR(sc, ADW_GET_CARRP(irq_next_pa))((ADW_CARRIER *) (((u_int8_t *)(sc)->sc_control->carriers ) + ((u_long)((irq_next_pa) & 0xFFFFFFF0)) - (sc)->sc_dmamap_carrier ->dm_segs[0].ds_addr)); |
2048 | |
2049 | free_carrp->next_ba = (sc->carr_freelist == NULL((void *)0)) ? 0 |
2050 | : sc->carr_freelist->carr_ba; |
2051 | sc->carr_freelist = free_carrp; |
2052 | sc->carr_pending_cnt--; |
2053 | |
2054 | target_bit = ADW_TID_TO_TIDMASK(scsiq->target_id)(0x01 << ((scsiq->target_id) & 15)); |
2055 | |
2056 | /* |
2057 | * Clear request microcode control flag. |
2058 | */ |
2059 | scsiq->cntl = 0; |
2060 | |
2061 | /* |
2062 | * Check Condition handling |
2063 | */ |
2064 | /* |
2065 | * If the command that completed was a SCSI INQUIRY and |
2066 | * LUN 0 was sent the command, then process the INQUIRY |
2067 | * command information for the device. |
2068 | */ |
2069 | if (scsiq->done_status == QD_NO_ERROR0x01 && |
2070 | scsiq->cdb[0] == INQUIRY0x12 && |
2071 | scsiq->target_lun == 0) { |
2072 | AdwInquiryHandling(sc, scsiq); |
2073 | } |
2074 | |
2075 | /* |
2076 | * Notify the driver of the completed request by passing |
2077 | * the ADW_SCSI_REQ_Q pointer to its callback function. |
2078 | */ |
2079 | (*(ADW_ISR_CALLBACK)sc->isr_callback)(sc, scsiq); |
2080 | /* |
2081 | * Note: After the driver callback function is called, 'scsiq' |
2082 | * can no longer be referenced. |
2083 | * |
2084 | * Fall through and continue processing other completed |
2085 | * requests... |
2086 | */ |
2087 | } |
2088 | |
2089 | splx(s)spllower(s); |
2090 | |
2091 | return ADW_TRUE1; |
2092 | } |
2093 | |
2094 | |
2095 | /* |
2096 | * Send an idle command to the chip and wait for completion. |
2097 | * |
2098 | * Command completion is polled for once per microsecond. |
2099 | * |
2100 | * The function can be called from anywhere including an interrupt handler. |
2101 | * But the function is not re-entrant, so it uses the splbio/splx() |
2102 | * functions to prevent reentrancy. |
2103 | * |
2104 | * Return Values: |
2105 | * ADW_TRUE - command completed successfully |
2106 | * ADW_FALSE - command failed |
2107 | * ADW_ERROR - command timed out |
2108 | */ |
2109 | int |
2110 | AdwSendIdleCmd(ADW_SOFTC *sc, u_int16_t idle_cmd, u_int32_t idle_cmd_parameter) |
2111 | { |
2112 | bus_space_tag_t iot = sc->sc_iot; |
2113 | bus_space_handle_t ioh = sc->sc_ioh; |
2114 | u_int16_t result; |
2115 | u_int32_t i, j, s; |
2116 | |
2117 | s = splbio()splraise(0x3); |
2118 | |
2119 | /* |
2120 | * Clear the idle command status which is set by the microcode |
2121 | * to a non-zero value to indicate when the command is completed. |
2122 | */ |
2123 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_IDLE_CMD_STATUS, (u_int16_t) 0)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A4)))); (((iot ))->write_2(((ioh)), (0x06), (((u_int16_t) 0)))); } while ( 0); |
2124 | |
2125 | /* |
2126 | * Write the idle command value after the idle command parameter |
2127 | * has been written to avoid a race condition. If the order is not |
2128 | * followed, the microcode may process the idle command before the |
2129 | * parameters have been written to LRAM. |
2130 | */ |
2131 | ADW_WRITE_DWORD_LRAM(iot, ioh, ADW_MC_IDLE_CMD_PARAMETER,do { (((iot))->write_2(((ioh)), (0x04), ((0x00A8)))); (((iot ))->write_2(((ioh)), (0x06), ((u_int16_t) ((idle_cmd_parameter ) & 0xFFFF)))); (((iot))->write_2(((ioh)), (0x04), ((0x00A8 ) + 2))); (((iot))->write_2(((ioh)), (0x06), ((u_int16_t) ( (idle_cmd_parameter >> 16) & 0xFFFF)))); } while (0 ) |
2132 | idle_cmd_parameter)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A8)))); (((iot ))->write_2(((ioh)), (0x06), ((u_int16_t) ((idle_cmd_parameter ) & 0xFFFF)))); (((iot))->write_2(((ioh)), (0x04), ((0x00A8 ) + 2))); (((iot))->write_2(((ioh)), (0x06), ((u_int16_t) ( (idle_cmd_parameter >> 16) & 0xFFFF)))); } while (0 ); |
2133 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_IDLE_CMD, idle_cmd)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A6)))); (((iot ))->write_2(((ioh)), (0x06), ((idle_cmd)))); } while (0); |
2134 | |
2135 | /* |
2136 | * Tickle the RISC to tell it to process the idle command. |
2137 | */ |
2138 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_TICKLE, ADW_TICKLE_B)(((iot))->write_1(((ioh)), ((0x22)), ((0x02)))); |
2139 | if (sc->chip_type == ADW_CHIP_ASC35500x01) { |
2140 | /* |
2141 | * Clear the tickle value. In the ASC-3550 the RISC flag |
2142 | * command 'clr_tickle_b' does not work unless the host |
2143 | * value is cleared. |
2144 | */ |
2145 | ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_TICKLE, ADW_TICKLE_NOP)(((iot))->write_1(((ioh)), ((0x22)), ((0x00)))); |
2146 | } |
2147 | |
2148 | /* Wait for up to 100 millisecond for the idle command to timeout. */ |
2149 | for (i = 0; i < SCSI_WAIT_100_MSEC100UL; i++) { |
2150 | /* Poll once each microsecond for command completion. */ |
2151 | for (j = 0; j < SCSI_US_PER_MSEC1000; j++) { |
2152 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_IDLE_CMD_STATUS,do { (((iot))->write_2(((ioh)), (0x04), ((0x00A4)))); (result ) = (((iot))->read_2(((ioh)), (0x06))); } while (0) |
2153 | result)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A4)))); (result ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
2154 | if (result != 0) { |
2155 | splx(s)spllower(s); |
2156 | return result; |
2157 | } |
2158 | AdwDelayMicroSecond(1); |
2159 | } |
2160 | } |
2161 | |
2162 | splx(s)spllower(s); |
2163 | return ADW_ERROR(-1); |
2164 | } |
2165 | |
2166 | |
2167 | /* |
2168 | * Inquiry Information Byte 7 Handling |
2169 | * |
2170 | * Handle SCSI Inquiry Command information for a device by setting |
2171 | * microcode operating variables that affect WDTR, SDTR, and Tag |
2172 | * Queuing. |
2173 | */ |
2174 | void |
2175 | AdwInquiryHandling(ADW_SOFTC *sc, ADW_SCSI_REQ_Q *scsiq) |
2176 | { |
2177 | #ifndef FAILSAFE |
2178 | bus_space_tag_t iot = sc->sc_iot; |
2179 | bus_space_handle_t ioh = sc->sc_ioh; |
2180 | u_int8_t tid; |
2181 | ADW_SCSI_INQUIRY *inq; |
2182 | u_int16_t tidmask; |
2183 | u_int16_t cfg_word; |
2184 | |
2185 | |
2186 | /* |
2187 | * AdwInquiryHandling() requires up to INQUIRY information Byte 7 |
2188 | * to be available. |
2189 | * |
2190 | * If less than 8 bytes of INQUIRY information were requested or less |
2191 | * than 8 bytes were transferred, then return. cdb[4] is the request |
2192 | * length and the ADW_SCSI_REQ_Q 'data_cnt' field is set by the |
2193 | * microcode to the transfer residual count. |
2194 | */ |
2195 | |
2196 | if (scsiq->cdb[4] < 8 || (scsiq->cdb[4] - scsiq->data_cnt) < 8) { |
2197 | return; |
2198 | } |
2199 | |
2200 | tid = scsiq->target_id; |
2201 | |
2202 | inq = (ADW_SCSI_INQUIRY *) scsiq->vdata_addr; |
2203 | |
2204 | /* |
2205 | * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices. |
2206 | */ |
2207 | if ((inq->rsp_data_fmt < 2) /*SCSI-1 | CCS*/ && |
2208 | (inq->ansi_apr_ver < 2)) { |
2209 | return; |
2210 | } else { |
2211 | /* |
2212 | * INQUIRY Byte 7 Handling |
2213 | * |
2214 | * Use a device's INQUIRY byte 7 to determine whether it |
2215 | * supports WDTR, SDTR, and Tag Queuing. If the feature |
2216 | * is enabled in the EEPROM and the device supports the |
2217 | * feature, then enable it in the microcode. |
2218 | */ |
2219 | |
2220 | tidmask = ADW_TID_TO_TIDMASK(tid)(0x01 << ((tid) & 15)); |
2221 | |
2222 | /* |
2223 | * Wide Transfers |
2224 | * |
2225 | * If the EEPROM enabled WDTR for the device and the device |
2226 | * supports wide bus (16 bit) transfers, then turn on the |
2227 | * device's 'wdtr_able' bit and write the new value to the |
2228 | * microcode. |
2229 | */ |
2230 | #ifdef SCSI_ADW_WDTR_DISABLE |
2231 | if(!(tidmask & SCSI_ADW_WDTR_DISABLE)) |
2232 | #endif /* SCSI_ADW_WDTR_DISABLE */ |
2233 | if ((sc->wdtr_able & tidmask) && inq->WBus16) { |
2234 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (cfg_word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0) |
2235 | cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (cfg_word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
2236 | if ((cfg_word & tidmask) == 0) { |
2237 | cfg_word |= tidmask; |
2238 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0) |
2239 | cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x009C)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0); |
2240 | |
2241 | /* |
2242 | * Clear the microcode "SDTR negotiation" and |
2243 | * "WDTR negotiation" done indicators for the |
2244 | * target to cause it to negotiate with the new |
2245 | * setting set above. |
2246 | * WDTR when accepted causes the target to enter |
2247 | * asynchronous mode, so SDTR must be negotiated |
2248 | */ |
2249 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_DONE,do { (((iot))->write_2(((ioh)), (0x04), ((0x00B6)))); (cfg_word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0) |
2250 | cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x00B6)))); (cfg_word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
2251 | cfg_word &= ~tidmask; |
2252 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_DONE,do { (((iot))->write_2(((ioh)), (0x04), ((0x00B6)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0) |
2253 | cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x00B6)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0); |
2254 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_WDTR_DONE,do { (((iot))->write_2(((ioh)), (0x04), ((0x0124)))); (cfg_word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0) |
2255 | cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x0124)))); (cfg_word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
2256 | cfg_word &= ~tidmask; |
2257 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_WDTR_DONE,do { (((iot))->write_2(((ioh)), (0x04), ((0x0124)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0) |
2258 | cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x0124)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0); |
2259 | } |
2260 | } |
2261 | |
2262 | /* |
2263 | * Synchronous Transfers |
2264 | * |
2265 | * If the EEPROM enabled SDTR for the device and the device |
2266 | * supports synchronous transfers, then turn on the device's |
2267 | * 'sdtr_able' bit. Write the new value to the microcode. |
2268 | */ |
2269 | #ifdef SCSI_ADW_SDTR_DISABLE |
2270 | if(!(tidmask & SCSI_ADW_SDTR_DISABLE)) |
2271 | #endif /* SCSI_ADW_SDTR_DISABLE */ |
2272 | if ((sc->sdtr_able & tidmask) && inq->Sync) { |
2273 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE,cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x009E)))); (cfg_word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
2274 | if ((cfg_word & tidmask) == 0) { |
2275 | cfg_word |= tidmask; |
2276 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x009E)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0) |
2277 | cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x009E)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0); |
2278 | |
2279 | /* |
2280 | * Clear the microcode "SDTR negotiation" |
2281 | * done indicator for the target to cause it |
2282 | * to negotiate with the new setting set above. |
2283 | */ |
2284 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_DONE,do { (((iot))->write_2(((ioh)), (0x04), ((0x00B6)))); (cfg_word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0) |
2285 | cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x00B6)))); (cfg_word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
2286 | cfg_word &= ~tidmask; |
2287 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_DONE,do { (((iot))->write_2(((ioh)), (0x04), ((0x00B6)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0) |
2288 | cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x00B6)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0); |
2289 | } |
2290 | } |
2291 | /* |
2292 | * If the Inquiry data included enough space for the SPI-3 |
2293 | * Clocking field, then check if DT mode is supported. |
2294 | */ |
2295 | if (sc->chip_type == ADW_CHIP_ASC38C16000x03 && |
2296 | (scsiq->cdb[4] >= 57 || |
2297 | (scsiq->cdb[4] - scsiq->data_cnt) >= 57)) { |
2298 | /* |
2299 | * PPR (Parallel Protocol Request) Capable |
2300 | * |
2301 | * If the device supports DT mode, then it must be |
2302 | * PPR capable. |
2303 | * The PPR message will be used in place of the SDTR |
2304 | * and WDTR messages to negotiate synchronous speed |
2305 | * and offset, transfer width, and protocol options. |
2306 | */ |
2307 | if((inq->Clocking) & INQ_CLOCKING_DT_ONLY0x1){ |
2308 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_PPR_ABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x017A)))); (sc-> ppr_able) = (((iot))->read_2(((ioh)), (0x06))); } while (0 ) |
2309 | sc->ppr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x017A)))); (sc-> ppr_able) = (((iot))->read_2(((ioh)), (0x06))); } while (0 ); |
2310 | sc->ppr_able |= tidmask; |
2311 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_PPR_ABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x017A)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->ppr_able)))); } while (0) |
2312 | sc->ppr_able)do { (((iot))->write_2(((ioh)), (0x04), ((0x017A)))); (((iot ))->write_2(((ioh)), (0x06), ((sc->ppr_able)))); } while (0); |
2313 | } |
2314 | } |
2315 | |
2316 | /* |
2317 | * If the EEPROM enabled Tag Queuing for the device and the |
2318 | * device supports Tag Queueing, then turn on the device's |
2319 | * 'tagqng_enable' bit in the microcode and set the microcode |
2320 | * maximum command count to the ADW_SOFTC 'max_dvc_qng' |
2321 | * value. |
2322 | * |
2323 | * Tag Queuing is disabled for the BIOS which runs in polled |
2324 | * mode and would see no benefit from Tag Queuing. Also by |
2325 | * disabling Tag Queuing in the BIOS devices with Tag Queuing |
2326 | * bugs will at least work with the BIOS. |
2327 | */ |
2328 | #ifdef SCSI_ADW_TAGQ_DISABLE |
2329 | if(!(tidmask & SCSI_ADW_TAGQ_DISABLE)) |
2330 | #endif /* SCSI_ADW_TAGQ_DISABLE */ |
2331 | if ((sc->tagqng_able & tidmask) && inq->CmdQue) { |
2332 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x00A0)))); (cfg_word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0) |
2333 | cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A0)))); (cfg_word ) = (((iot))->read_2(((ioh)), (0x06))); } while (0); |
2334 | cfg_word |= tidmask; |
2335 | ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE,do { (((iot))->write_2(((ioh)), (0x04), ((0x00A0)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0) |
2336 | cfg_word)do { (((iot))->write_2(((ioh)), (0x04), ((0x00A0)))); (((iot ))->write_2(((ioh)), (0x06), ((cfg_word)))); } while (0); |
2337 | |
2338 | ADW_WRITE_BYTE_LRAM(iot, ioh,do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (((iot))->write_1(((ioh)), (0x06), ((sc->max_dvc_qng) ))); } while (0) |
2339 | ADW_MC_NUMBER_OF_MAX_CMD + tid,do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (((iot))->write_1(((ioh)), (0x06), ((sc->max_dvc_qng) ))); } while (0) |
2340 | sc->max_dvc_qng)do { (((iot))->write_2(((ioh)), (0x04), ((0x00D0 + tid)))) ; (((iot))->write_1(((ioh)), (0x06), ((sc->max_dvc_qng) ))); } while (0); |
2341 | } |
2342 | } |
2343 | #endif /* FAILSAFE */ |
2344 | } |
2345 | |
2346 | |
2347 | void |
2348 | AdwSleepMilliSecond(u_int32_t n) |
2349 | { |
2350 | |
2351 | DELAY(n * 1000)(*delay_func)(n * 1000); |
2352 | } |
2353 | |
2354 | |
2355 | void |
2356 | AdwDelayMicroSecond(u_int32_t n) |
2357 | { |
2358 | |
2359 | DELAY(n)(*delay_func)(n); |
2360 | } |
2361 |