11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of PCI-SCSI IO processors. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver is derived from the Linux sym53c8xx driver. 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1998-2000 Gerard Roudier 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The sym53c8xx driver is derived from the ncr53c8xx driver that had been 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a port of the FreeBSD ncr driver to Linux-1.2.13. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The original ncr driver has been written for 386bsd and FreeBSD by 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wolfgang Stanglmeier <wolf@cologne.de> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stefan Esser <se@mi.Uni-Koeln.de> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1994 Wolfgang Stanglmeier 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Other major contributions: 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NVRAM detection and reading. 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *----------------------------------------------------------------------------- 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sym_glue.h" 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sym_nvram.h" 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SYM_CONF_DEBUG_NVRAM 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_char Tekram_boot_delay[7] = {3, 5, 10, 20, 30, 60, 120}; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get host setup from NVRAM. 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram) 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get parity checking, host ID, verbose mode 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and miscellaneous host flags from NVRAM. 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (nvram->type) { 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SYM_SYMBIOS_NVRAM: 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(nvram->data.Symbios.flags & SYMBIOS_PARITY_ENABLE)) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np->rv_scntl0 &= ~0x0a; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np->myaddr = nvram->data.Symbios.host_id & 0x0f; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nvram->data.Symbios.flags & SYMBIOS_VERBOSE_MSGS) 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np->verbose += 1; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nvram->data.Symbios.flags1 & SYMBIOS_SCAN_HI_LO) 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shost->reverse_ordering = 1; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nvram->data.Symbios.flags2 & SYMBIOS_AVOID_BUS_RESET) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np->usrflags |= SYM_AVOID_BUS_RESET; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SYM_TEKRAM_NVRAM: 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np->myaddr = nvram->data.Tekram.host_id & 0x0f; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PARISC 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SYM_PARISC_PDC: 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nvram->data.parisc.host_id != -1) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np->myaddr = nvram->data.parisc.host_id; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nvram->data.parisc.factor != -1) 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np->minsync = nvram->data.parisc.factor; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nvram->data.parisc.width != -1) 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np->maxwide = nvram->data.parisc.width; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (nvram->data.parisc.mode) { 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: np->scsi_mode = SMODE_SE; break; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: np->scsi_mode = SMODE_HVD; break; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: np->scsi_mode = SMODE_LVD; break; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: break; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get target set-up from Symbios format NVRAM. 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 95b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcoxsym_Symbios_setup_target(struct sym_tcb *tp, int target, Symbios_nvram *nvram) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Symbios_target *tn = &nvram->target[target]; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 99b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox if (!(tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)) 100b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox tp->usrtags = 0; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(tn->flags & SYMBIOS_DISCONNECT_ENABLE)) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tp->usrflags &= ~SYM_DISC_ENABLED; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME)) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tp->usrflags |= SYM_SCAN_BOOT_DISABLED; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(tn->flags & SYMBIOS_SCAN_LUNS)) 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tp->usrflags |= SYM_SCAN_LUNS_DISABLED; 107b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox tp->usr_period = (tn->sync_period + 3) / 4; 108b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox tp->usr_width = (tn->bus_width == 0x8) ? 0 : 1; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcoxstatic const unsigned char Tekram_sync[16] = { 112b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox 25, 31, 37, 43, 50, 62, 75, 125, 12, 15, 18, 21, 6, 7, 9, 10 113b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox}; 114b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get target set-up from Tekram format NVRAM. 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 119b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcoxsym_Tekram_setup_target(struct sym_tcb *tp, int target, Tekram_nvram *nvram) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Tekram_target *tn = &nvram->target[target]; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tn->flags & TEKRAM_TAGGED_COMMANDS) { 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tp->usrtags = 2 << nvram->max_tags_index; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tn->flags & TEKRAM_DISCONNECT_ENABLE) 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tp->usrflags |= SYM_DISC_ENABLED; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 130b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox if (tn->flags & TEKRAM_SYNC_NEGO) 131b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox tp->usr_period = Tekram_sync[tn->sync_index & 0xf]; 132b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox tp->usr_width = (tn->flags & TEKRAM_WIDE_NEGO) ? 1 : 0; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get target setup from NVRAM. 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 138b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcoxvoid sym_nvram_setup_target(struct sym_tcb *tp, int target, struct sym_nvram *nvp) 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (nvp->type) { 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SYM_SYMBIOS_NVRAM: 142b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox sym_Symbios_setup_target(tp, target, &nvp->data.Symbios); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SYM_TEKRAM_NVRAM: 145b37df48923b76155de2a728e1155ed263dba5f53Matthew Wilcox sym_Tekram_setup_target(tp, target, &nvp->data.Tekram); 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SYM_CONF_DEBUG_NVRAM 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dump Symbios format NVRAM for debugging purpose. 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sym_display_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* display Symbios nvram host data */ 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("%s: HOST ID=%d%s%s%s%s%s%s\n", 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sym_name(np), nvram->host_id & 0x0f, 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"", 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags & SYMBIOS_PARITY_ENABLE) ? " PARITY" :"", 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags & SYMBIOS_VERBOSE_MSGS) ? " VERBOSE" :"", 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags & SYMBIOS_CHS_MAPPING) ? " CHS_ALT" :"", 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags2 & SYMBIOS_AVOID_BUS_RESET)?" NO_RESET" :"", 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags1 & SYMBIOS_SCAN_HI_LO) ? " HI_LO" :""); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* display Symbios nvram drive data */ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0 ; i < 15 ; i++) { 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Symbios_target *tn = &nvram->target[i]; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("%s-%d:%s%s%s%s WIDTH=%d SYNC=%d TMO=%d\n", 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sym_name(np), i, 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tn->flags & SYMBIOS_DISCONNECT_ENABLE) ? " DISC" : "", 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME) ? " SCAN_BOOT" : "", 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tn->flags & SYMBIOS_SCAN_LUNS) ? " SCAN_LUNS" : "", 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? " TCQ" : "", 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tn->bus_width, 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tn->sync_period / 4, 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tn->timeout); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dump TEKRAM format NVRAM for debugging purpose. 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sym_display_Tekram_nvram(struct sym_device *np, Tekram_nvram *nvram) 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, tags, boot_delay; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *rem; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* display Tekram nvram host data */ 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tags = 2 << nvram->max_tags_index; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_delay = 0; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nvram->boot_delay_index < 6) 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_delay = Tekram_boot_delay[nvram->boot_delay_index]; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch ((nvram->flags & TEKRAM_REMOVABLE_FLAGS) >> 6) { 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: rem = ""; break; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: rem = " REMOVABLE=boot device"; break; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: rem = " REMOVABLE=all"; break; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("%s: HOST ID=%d%s%s%s%s%s%s%s%s%s BOOT DELAY=%d tags=%d\n", 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sym_name(np), nvram->host_id & 0x0f, 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags1 & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"", 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags & TEKRAM_MORE_THAN_2_DRIVES) ? " >2DRIVES":"", 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags & TEKRAM_DRIVES_SUP_1GB) ? " >1GB" :"", 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags & TEKRAM_RESET_ON_POWER_ON) ? " RESET" :"", 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags & TEKRAM_ACTIVE_NEGATION) ? " ACT_NEG" :"", 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags & TEKRAM_IMMEDIATE_SEEK) ? " IMM_SEEK" :"", 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags & TEKRAM_SCAN_LUNS) ? " SCAN_LUNS" :"", 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nvram->flags1 & TEKRAM_F2_F6_ENABLED) ? " F2_F6" :"", 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rem, boot_delay, tags); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* display Tekram nvram drive data */ 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i <= 15; i++) { 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int sync, j; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Tekram_target *tn = &nvram->target[i]; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds j = tn->sync_index & 0xf; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sync = Tekram_sync[j]; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("%s-%d:%s%s%s%s%s%s PERIOD=%d\n", 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sym_name(np), i, 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tn->flags & TEKRAM_PARITY_CHECK) ? " PARITY" : "", 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tn->flags & TEKRAM_SYNC_NEGO) ? " SYNC" : "", 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tn->flags & TEKRAM_DISCONNECT_ENABLE) ? " DISC" : "", 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tn->flags & TEKRAM_START_CMD) ? " START" : "", 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tn->flags & TEKRAM_TAGGED_COMMANDS) ? " TCQ" : "", 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tn->flags & TEKRAM_WIDE_NEGO) ? " WIDE" : "", 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sync); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sym_display_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram) { (void)np; (void)nvram; } 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sym_display_Tekram_nvram(struct sym_device *np, Tekram_nvram *nvram) { (void)np; (void)nvram; } 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* SYM_CONF_DEBUG_NVRAM */ 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 24C16 EEPROM reading. 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GPOI0 - data in/data out 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GPIO1 - clock 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Symbios NVRAM wiring now also used by Tekram. 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_BIT 0 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CLR_BIT 1 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_CLK 2 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CLR_CLK 3 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set/clear data/clock bit in GPIO0 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void S24C16_set_bit(struct sym_device *np, u_char write_bit, u_char *gpreg, 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bit_mode) 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(5); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (bit_mode) { 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SET_BIT: 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *gpreg |= write_bit; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLR_BIT: 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *gpreg &= 0xfe; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SET_CLK: 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *gpreg |= 0x02; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLR_CLK: 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *gpreg &= 0xfd; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpreg, *gpreg); 27653222b906903fd861dc24ebccfa07ee125941313Matthew Wilcox INB(np, nc_mbox1); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(5); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send START condition to NVRAM to wake it up. 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void S24C16_start(struct sym_device *np, u_char *gpreg) 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 1, gpreg, SET_BIT); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 0, gpreg, SET_CLK); 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 0, gpreg, CLR_BIT); 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 0, gpreg, CLR_CLK); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZzzzz!! 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void S24C16_stop(struct sym_device *np, u_char *gpreg) 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 0, gpreg, SET_CLK); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 1, gpreg, SET_BIT); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read or write a bit to the NVRAM, 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * read if GPIO0 input else write if GPIO0 output 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void S24C16_do_bit(struct sym_device *np, u_char *read_bit, u_char write_bit, 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *gpreg) 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, write_bit, gpreg, SET_BIT); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 0, gpreg, SET_CLK); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (read_bit) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *read_bit = INB(np, nc_gpreg); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 0, gpreg, CLR_CLK); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 0, gpreg, CLR_BIT); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Output an ACK to the NVRAM after reading, 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * change GPIO0 to output and when done back to an input 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void S24C16_write_ack(struct sym_device *np, u_char write_bit, u_char *gpreg, 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *gpcntl) 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, *gpcntl & 0xfe); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_do_bit(np, NULL, write_bit, gpreg); 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, *gpcntl); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Input an ACK from NVRAM after writing, 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * change GPIO0 to input and when done back to an output 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void S24C16_read_ack(struct sym_device *np, u_char *read_bit, u_char *gpreg, 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *gpcntl) 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, *gpcntl | 0x01); 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_do_bit(np, read_bit, 1, gpreg); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, *gpcntl); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WRITE a byte to the NVRAM and then get an ACK to see it was accepted OK, 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GPIO0 must already be set as an output 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void S24C16_write_byte(struct sym_device *np, u_char *ack_data, u_char write_data, 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *gpreg, u_char *gpcntl) 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int x; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (x = 0; x < 8; x++) 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_do_bit(np, NULL, (write_data >> (7 - x)) & 0x01, gpreg); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_read_ack(np, ack_data, gpreg, gpcntl); 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * READ a byte from the NVRAM and then send an ACK to say we have got it, 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GPIO0 must already be set as an input 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void S24C16_read_byte(struct sym_device *np, u_char *read_data, u_char ack_data, 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *gpreg, u_char *gpcntl) 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int x; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char read_bit; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *read_data = 0; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (x = 0; x < 8; x++) { 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_do_bit(np, &read_bit, 1, gpreg); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *read_data |= ((read_bit & 0x01) << (7 - x)); 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_write_ack(np, ack_data, gpreg, gpcntl); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37344456d37b59d8e541936ed26d8b6e08d27e88ac1Olaf Hering#ifdef SYM_CONF_NVRAM_WRITE_SUPPORT 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Write 'len' bytes starting at 'offset'. 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sym_write_S24C16_nvram(struct sym_device *np, int offset, 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *data, int len) 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char gpcntl, gpreg; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char old_gpcntl, old_gpreg; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char ack_data; 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int x; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save current state of GPCNTL and GPREG */ 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_gpreg = INB(np, nc_gpreg); 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_gpcntl = INB(np, nc_gpcntl); 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpcntl = old_gpcntl & 0x1c; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */ 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpreg, old_gpreg); 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, gpcntl); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this is to set NVRAM into a known state with GPIO0/1 both low */ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpreg = old_gpreg; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 0, &gpreg, CLR_CLK); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 0, &gpreg, CLR_BIT); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* now set NVRAM inactive with GPIO0/1 both high */ 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_stop(np, &gpreg); 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NVRAM has to be written in segments of 16 bytes */ 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (x = 0; x < len ; x += 16) { 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_start(np, &gpreg); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_write_byte(np, &ack_data, 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xa0 | (((offset+x) >> 7) & 0x0e), 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &gpreg, &gpcntl); 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (ack_data & 0x01); 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_write_byte(np, &ack_data, (offset+x) & 0xff, 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &gpreg, &gpcntl); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (y = 0; y < 16; y++) 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_write_byte(np, &ack_data, data[x+y], 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &gpreg, &gpcntl); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_stop(np, &gpreg); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* return GPIO0/1 to original states after having accessed NVRAM */ 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, old_gpcntl); 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpreg, old_gpreg); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* SYM_CONF_NVRAM_WRITE_SUPPORT */ 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read 'len' bytes starting at 'offset'. 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data, int len) 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char gpcntl, gpreg; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char old_gpcntl, old_gpreg; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char ack_data; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retv = 1; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int x; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save current state of GPCNTL and GPREG */ 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_gpreg = INB(np, nc_gpreg); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_gpcntl = INB(np, nc_gpcntl); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpcntl = old_gpcntl & 0x1c; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */ 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpreg, old_gpreg); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, gpcntl); 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this is to set NVRAM into a known state with GPIO0/1 both low */ 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpreg = old_gpreg; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 0, &gpreg, CLR_CLK); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_set_bit(np, 0, &gpreg, CLR_BIT); 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* now set NVRAM inactive with GPIO0/1 both high */ 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_stop(np, &gpreg); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* activate NVRAM */ 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_start(np, &gpreg); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* write device code and random address MSB */ 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_write_byte(np, &ack_data, 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xa0 | ((offset >> 7) & 0x0e), &gpreg, &gpcntl); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ack_data & 0x01) 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* write random address LSB */ 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_write_byte(np, &ack_data, 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset & 0xff, &gpreg, &gpcntl); 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ack_data & 0x01) 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* regenerate START state to set up for reading */ 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_start(np, &gpreg); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* rewrite device code and address MSB with read bit set (lsb = 0x01) */ 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_write_byte(np, &ack_data, 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xa1 | ((offset >> 7) & 0x0e), &gpreg, &gpcntl); 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ack_data & 0x01) 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* now set up GPIO0 for inputting data */ 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpcntl |= 0x01; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, gpcntl); 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* input all requested data - only part of total NVRAM */ 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (x = 0; x < len; x++) 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_read_byte(np, &data[x], (x == (len-1)), &gpreg, &gpcntl); 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* finally put NVRAM back in inactive mode */ 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpcntl &= 0xfe; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, gpcntl); 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds S24C16_stop(np, &gpreg); 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retv = 0; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* return GPIO0/1 to original states after having accessed NVRAM */ 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, old_gpcntl); 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpreg, old_gpreg); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retv; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef SET_BIT 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CLR_BIT 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef SET_CLK 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CLR_CLK 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try reading Symbios NVRAM. 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return 0 if OK. 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sym_read_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram) 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static u_char Symbios_trailer[6] = {0xfe, 0xfe, 0, 0, 0, 0}; 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *data = (u_char *) nvram; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len = sizeof(*nvram); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_short csum; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int x; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* probe the 24c16 and read the SYMBIOS 24c16 area */ 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sym_read_S24C16_nvram (np, SYMBIOS_NVRAM_ADDRESS, data, len)) 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check valid NVRAM signature, verify byte count and checksum */ 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nvram->type != 0 || 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcmp(nvram->trailer, Symbios_trailer, 6) || 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nvram->byte_count != len - 12) 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* verify checksum */ 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (x = 6, csum = 0; x < len - 6; x++) 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csum += data[x]; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csum != nvram->checksum) 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 93C46 EEPROM reading. 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GPOI0 - data in 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GPIO1 - data out 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GPIO2 - clock 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GPIO4 - chip select 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used by Tekram. 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Pulse clock bit in GPIO0 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void T93C46_Clk(struct sym_device *np, u_char *gpreg) 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpreg, *gpreg | 0x04); 55453222b906903fd861dc24ebccfa07ee125941313Matthew Wilcox INB(np, nc_mbox1); 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(2); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpreg, *gpreg); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read bit from NVRAM 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void T93C46_Read_Bit(struct sym_device *np, u_char *read_bit, u_char *gpreg) 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(2); 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds T93C46_Clk(np, gpreg); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *read_bit = INB(np, nc_gpreg); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Write bit to GPIO0 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void T93C46_Write_Bit(struct sym_device *np, u_char write_bit, u_char *gpreg) 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (write_bit & 0x01) 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *gpreg |= 0x02; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *gpreg &= 0xfd; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *gpreg |= 0x10; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpreg, *gpreg); 58253222b906903fd861dc24ebccfa07ee125941313Matthew Wilcox INB(np, nc_mbox1); 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(2); 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds T93C46_Clk(np, gpreg); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZZzzz!! 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void T93C46_Stop(struct sym_device *np, u_char *gpreg) 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *gpreg &= 0xef; 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpreg, *gpreg); 59553222b906903fd861dc24ebccfa07ee125941313Matthew Wilcox INB(np, nc_mbox1); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(2); 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds T93C46_Clk(np, gpreg); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send read command and address to NVRAM 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void T93C46_Send_Command(struct sym_device *np, u_short write_data, 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *read_bit, u_char *gpreg) 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int x; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* send 9 bits, start bit (1), command (2), address (6) */ 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (x = 0; x < 9; x++) 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds T93C46_Write_Bit(np, (u_char) (write_data >> (8 - x)), gpreg); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *read_bit = INB(np, nc_gpreg); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * READ 2 bytes from the NVRAM 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void T93C46_Read_Word(struct sym_device *np, 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short *nvram_data, unsigned char *gpreg) 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int x; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char read_bit; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *nvram_data = 0; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (x = 0; x < 16; x++) { 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds T93C46_Read_Bit(np, &read_bit, gpreg); 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (read_bit & 0x01) 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *nvram_data |= (0x01 << (15 - x)); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *nvram_data &= ~(0x01 << (15 - x)); 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read Tekram NvRAM data. 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int T93C46_Read_Data(struct sym_device *np, unsigned short *data, 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len, unsigned char *gpreg) 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int x; 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (x = 0; x < len; x++) { 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char read_bit; 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* output read command and address */ 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds T93C46_Send_Command(np, 0x180 | x, &read_bit, gpreg); 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (read_bit & 0x01) 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; /* Bad */ 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds T93C46_Read_Word(np, &data[x], gpreg); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds T93C46_Stop(np, gpreg); 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try reading 93C46 Tekram NVRAM. 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sym_read_T93C46_nvram(struct sym_device *np, Tekram_nvram *nvram) 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char gpcntl, gpreg; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char old_gpcntl, old_gpreg; 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retv = 1; 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save current state of GPCNTL and GPREG */ 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_gpreg = INB(np, nc_gpreg); 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_gpcntl = INB(np, nc_gpcntl); 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set up GPREG & GPCNTL to set GPIO0/1/2/4 in to known state, 0 in, 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1/2/4 out */ 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpreg = old_gpreg & 0xe9; 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpreg, gpreg); 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpcntl = (old_gpcntl & 0xe9) | 0x09; 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, gpcntl); 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* input all of NVRAM, 64 words */ 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retv = T93C46_Read_Data(np, (u_short *) nvram, 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(*nvram) / sizeof(short), &gpreg); 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* return GPIO0/1/2/4 to original states after having accessed NVRAM */ 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpcntl, old_gpcntl); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTB(np, nc_gpreg, old_gpreg); 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retv; 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try reading Tekram NVRAM. 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return 0 if OK. 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sym_read_Tekram_nvram (struct sym_device *np, Tekram_nvram *nvram) 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *data = (u_char *) nvram; 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len = sizeof(*nvram); 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_short csum; 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int x; 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 699e58bc06ed071e43bef4e2f94340853761a4bf034Matthew Wilcox switch (np->pdev->device) { 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCI_DEVICE_ID_NCR_53C885: 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCI_DEVICE_ID_NCR_53C895: 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCI_DEVICE_ID_NCR_53C896: 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds x = sym_read_S24C16_nvram(np, TEKRAM_24C16_NVRAM_ADDRESS, 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data, len); 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCI_DEVICE_ID_NCR_53C875: 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds x = sym_read_S24C16_nvram(np, TEKRAM_24C16_NVRAM_ADDRESS, 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data, len); 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!x) 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds x = sym_read_T93C46_nvram(np, nvram); 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (x) 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* verify checksum */ 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (x = 0, csum = 0; x < len - 1; x += 2) 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csum += data[x] + (data[x+1] << 8); 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csum != 0x1234) 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PARISC 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Host firmware (PDC) keeps a table for altering SCSI capabilities. 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Many newer machines export one channel of 53c896 chip as SE, 50-pin HD. 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Also used for Multi-initiator SCSI clusters to set the SCSI Initiator ID. 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *pdc) 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hardware_path hwpath; 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_pci_node_path(np->pdev, &hwpath); 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pdc_get_initiator(&hwpath, pdc)) 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SYM_PARISC_PDC; 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 74353222b906903fd861dc24ebccfa07ee125941313Matthew Wilcoxstatic inline int sym_read_parisc_pdc(struct sym_device *np, 74453222b906903fd861dc24ebccfa07ee125941313Matthew Wilcox struct pdc_initiator *x) 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try reading Symbios or Tekram NVRAM 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp) 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sym_read_Symbios_nvram(np, &nvp->data.Symbios)) { 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nvp->type = SYM_SYMBIOS_NVRAM; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sym_display_Symbios_nvram(np, &nvp->data.Symbios); 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!sym_read_Tekram_nvram(np, &nvp->data.Tekram)) { 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nvp->type = SYM_TEKRAM_NVRAM; 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sym_display_Tekram_nvram(np, &nvp->data.Tekram); 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nvp->type = sym_read_parisc_pdc(np, &nvp->data.parisc); 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return nvp->type; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar *sym_nvram_type(struct sym_nvram *nvp) 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (nvp->type) { 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SYM_SYMBIOS_NVRAM: 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return "Symbios NVRAM"; 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SYM_TEKRAM_NVRAM: 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return "Tekram NVRAM"; 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SYM_PARISC_PDC: 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return "PA-RISC Firmware"; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return "No NVRAM"; 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 780