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