Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.29 422 lines 13 kB view raw
1/* 2** ----------------------------------------------------------------------------- 3** 4** Perle Specialix driver for Linux 5** Ported from existing RIO Driver for SCO sources. 6 * 7 * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22** 23** Module : rioinit.c 24** SID : 1.3 25** Last Modified : 11/6/98 10:33:43 26** Retrieved : 11/6/98 10:33:49 27** 28** ident @(#)rioinit.c 1.3 29** 30** ----------------------------------------------------------------------------- 31*/ 32 33#include <linux/module.h> 34#include <linux/slab.h> 35#include <linux/errno.h> 36#include <linux/delay.h> 37#include <asm/io.h> 38#include <asm/system.h> 39#include <asm/string.h> 40#include <asm/uaccess.h> 41 42#include <linux/termios.h> 43#include <linux/serial.h> 44 45#include <linux/generic_serial.h> 46 47 48#include "linux_compat.h" 49#include "pkt.h" 50#include "daemon.h" 51#include "rio.h" 52#include "riospace.h" 53#include "cmdpkt.h" 54#include "map.h" 55#include "rup.h" 56#include "port.h" 57#include "riodrvr.h" 58#include "rioinfo.h" 59#include "func.h" 60#include "errors.h" 61#include "pci.h" 62 63#include "parmmap.h" 64#include "unixrup.h" 65#include "board.h" 66#include "host.h" 67#include "phb.h" 68#include "link.h" 69#include "cmdblk.h" 70#include "route.h" 71#include "cirrus.h" 72#include "rioioctl.h" 73#include "rio_linux.h" 74 75int RIOPCIinit(struct rio_info *p, int Mode); 76 77static int RIOScrub(int, u8 __iomem *, int); 78 79 80/** 81** RIOAssignAT : 82** 83** Fill out the fields in the p->RIOHosts structure now we know we know 84** we have a board present. 85** 86** bits < 0 indicates 8 bit operation requested, 87** bits > 0 indicates 16 bit operation. 88*/ 89 90int RIOAssignAT(struct rio_info *p, int Base, void __iomem *virtAddr, int mode) 91{ 92 int bits; 93 struct DpRam __iomem *cardp = (struct DpRam __iomem *)virtAddr; 94 95 if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE)) 96 bits = BYTE_OPERATION; 97 else 98 bits = WORD_OPERATION; 99 100 /* 101 ** Board has passed its scrub test. Fill in all the 102 ** transient stuff. 103 */ 104 p->RIOHosts[p->RIONumHosts].Caddr = virtAddr; 105 p->RIOHosts[p->RIONumHosts].CardP = virtAddr; 106 107 /* 108 ** Revision 01 AT host cards don't support WORD operations, 109 */ 110 if (readb(&cardp->DpRevision) == 01) 111 bits = BYTE_OPERATION; 112 113 p->RIOHosts[p->RIONumHosts].Type = RIO_AT; 114 p->RIOHosts[p->RIONumHosts].Copy = rio_copy_to_card; 115 /* set this later */ 116 p->RIOHosts[p->RIONumHosts].Slot = -1; 117 p->RIOHosts[p->RIONumHosts].Mode = SLOW_LINKS | SLOW_AT_BUS | bits; 118 writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE , 119 &p->RIOHosts[p->RIONumHosts].Control); 120 writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); 121 writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE, 122 &p->RIOHosts[p->RIONumHosts].Control); 123 writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); 124 p->RIOHosts[p->RIONumHosts].UniqueNum = 125 ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)| 126 ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)| 127 ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)| 128 ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24); 129 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum); 130 131 p->RIONumHosts++; 132 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base); 133 return(1); 134} 135 136static u8 val[] = { 137#ifdef VERY_LONG_TEST 138 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 139 0xa5, 0xff, 0x5a, 0x00, 0xff, 0xc9, 0x36, 140#endif 141 0xff, 0x00, 0x00 }; 142 143#define TEST_END sizeof(val) 144 145/* 146** RAM test a board. 147** Nothing too complicated, just enough to check it out. 148*/ 149int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, int slot) 150{ 151 struct DpRam __iomem *DpRam = caddr; 152 void __iomem *ram[4]; 153 int size[4]; 154 int op, bank; 155 int nbanks; 156 157 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=%p, slot=%d\n", 158 type, DpRam, slot); 159 160 RIOHostReset(type, DpRam, slot); 161 162 /* 163 ** Scrub the memory. This comes in several banks: 164 ** DPsram1 - 7000h bytes 165 ** DPsram2 - 200h bytes 166 ** DPsram3 - 7000h bytes 167 ** scratch - 1000h bytes 168 */ 169 170 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Setup ram/size arrays\n"); 171 172 size[0] = DP_SRAM1_SIZE; 173 size[1] = DP_SRAM2_SIZE; 174 size[2] = DP_SRAM3_SIZE; 175 size[3] = DP_SCRATCH_SIZE; 176 177 ram[0] = DpRam->DpSram1; 178 ram[1] = DpRam->DpSram2; 179 ram[2] = DpRam->DpSram3; 180 nbanks = (type == RIO_PCI) ? 3 : 4; 181 if (nbanks == 4) 182 ram[3] = DpRam->DpScratch; 183 184 185 if (nbanks == 3) { 186 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: %p(0x%x), %p(0x%x), %p(0x%x)\n", 187 ram[0], size[0], ram[1], size[1], ram[2], size[2]); 188 } else { 189 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: %p(0x%x), %p(0x%x), %p(0x%x), %p(0x%x)\n", 190 ram[0], size[0], ram[1], size[1], ram[2], size[2], ram[3], size[3]); 191 } 192 193 /* 194 ** This scrub operation will test for crosstalk between 195 ** banks. TEST_END is a magic number, and relates to the offset 196 ** within the 'val' array used by Scrub. 197 */ 198 for (op=0; op<TEST_END; op++) { 199 for (bank=0; bank<nbanks; bank++) { 200 if (RIOScrub(op, ram[bank], size[bank]) == RIO_FAIL) { 201 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: RIOScrub band %d, op %d failed\n", 202 bank, op); 203 return RIO_FAIL; 204 } 205 } 206 } 207 208 rio_dprintk (RIO_DEBUG_INIT, "Test completed\n"); 209 return 0; 210} 211 212 213/* 214** Scrub an area of RAM. 215** Define PRETEST and POSTTEST for a more thorough checking of the 216** state of the memory. 217** Call with op set to an index into the above 'val' array to determine 218** which value will be written into memory. 219** Call with op set to zero means that the RAM will not be read and checked 220** before it is written. 221** Call with op not zero and the RAM will be read and compared with val[op-1] 222** to check that the data from the previous phase was retained. 223*/ 224 225static int RIOScrub(int op, u8 __iomem *ram, int size) 226{ 227 int off; 228 unsigned char oldbyte; 229 unsigned char newbyte; 230 unsigned char invbyte; 231 unsigned short oldword; 232 unsigned short newword; 233 unsigned short invword; 234 unsigned short swapword; 235 236 if (op) { 237 oldbyte = val[op-1]; 238 oldword = oldbyte | (oldbyte<<8); 239 } else 240 oldbyte = oldword = 0; /* Tell the compiler we've initilalized them. */ 241 newbyte = val[op]; 242 newword = newbyte | (newbyte<<8); 243 invbyte = ~newbyte; 244 invword = invbyte | (invbyte<<8); 245 246 /* 247 ** Check that the RAM contains the value that should have been left there 248 ** by the previous test (not applicable for pass zero) 249 */ 250 if (op) { 251 for (off=0; off<size; off++) { 252 if (readb(ram + off) != oldbyte) { 253 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 1: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, readb(ram + off)); 254 return RIO_FAIL; 255 } 256 } 257 for (off=0; off<size; off+=2) { 258 if (readw(ram + off) != oldword) { 259 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: WORD at offset 0x%x should have been=%x, was=%x\n",off,oldword, readw(ram + off)); 260 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram+off+1)); 261 return RIO_FAIL; 262 } 263 } 264 } 265 266 /* 267 ** Now write the INVERSE of the test data into every location, using 268 ** BYTE write operations, first checking before each byte is written 269 ** that the location contains the old value still, and checking after 270 ** the write that the location contains the data specified - this is 271 ** the BYTE read/write test. 272 */ 273 for (off=0; off<size; off++) { 274 if (op && (readb(ram + off) != oldbyte)) { 275 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, readb(ram + off)); 276 return RIO_FAIL; 277 } 278 writeb(invbyte, ram + off); 279 if (readb(ram + off) != invbyte) { 280 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Inv Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, invbyte, readb(ram + off)); 281 return RIO_FAIL; 282 } 283 } 284 285 /* 286 ** now, use WORD operations to write the test value into every location, 287 ** check as before that the location contains the previous test value 288 ** before overwriting, and that it contains the data value written 289 ** afterwards. 290 ** This is the WORD operation test. 291 */ 292 for (off=0; off<size; off+=2) { 293 if (readw(ram + off) != invword) { 294 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: WORD at offset 0x%x should have been=%x, was=%x\n", off, invword, readw(ram + off)); 295 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram+off+1)); 296 return RIO_FAIL; 297 } 298 299 writew(newword, ram + off); 300 if ( readw(ram + off) != newword ) { 301 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, readw(ram + off)); 302 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1)); 303 return RIO_FAIL; 304 } 305 } 306 307 /* 308 ** now run through the block of memory again, first in byte mode 309 ** then in word mode, and check that all the locations contain the 310 ** required test data. 311 */ 312 for (off=0; off<size; off++) { 313 if (readb(ram + off) != newbyte) { 314 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Byte Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, readb(ram + off)); 315 return RIO_FAIL; 316 } 317 } 318 319 for (off=0; off<size; off+=2) { 320 if (readw(ram + off) != newword ) { 321 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, readw(ram + off)); 322 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1)); 323 return RIO_FAIL; 324 } 325 } 326 327 /* 328 ** time to check out byte swapping errors 329 */ 330 swapword = invbyte | (newbyte << 8); 331 332 for (off=0; off<size; off+=2) { 333 writeb(invbyte, &ram[off]); 334 writeb(newbyte, &ram[off+1]); 335 } 336 337 for ( off=0; off<size; off+=2 ) { 338 if (readw(ram + off) != swapword) { 339 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, swapword, readw(ram + off)); 340 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1)); 341 return RIO_FAIL; 342 } 343 writew(~swapword, ram + off); 344 } 345 346 for (off=0; off<size; off+=2) { 347 if (readb(ram + off) != newbyte) { 348 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, readb(ram + off)); 349 return RIO_FAIL; 350 } 351 if (readb(ram + off + 1) != invbyte) { 352 rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off+1, invbyte, readb(ram + off + 1)); 353 return RIO_FAIL; 354 } 355 writew(newword, ram + off); 356 } 357 return 0; 358} 359 360 361int RIODefaultName(struct rio_info *p, struct Host *HostP, unsigned int UnitId) 362{ 363 memcpy(HostP->Mapping[UnitId].Name, "UNKNOWN RTA X-XX", 17); 364 HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts); 365 if ((UnitId+1) > 9) { 366 HostP->Mapping[UnitId].Name[14]='0'+((UnitId+1)/10); 367 HostP->Mapping[UnitId].Name[15]='0'+((UnitId+1)%10); 368 } 369 else { 370 HostP->Mapping[UnitId].Name[14]='1'+UnitId; 371 HostP->Mapping[UnitId].Name[15]=0; 372 } 373 return 0; 374} 375 376#define RIO_RELEASE "Linux" 377#define RELEASE_ID "1.0" 378 379static struct rioVersion stVersion; 380 381struct rioVersion *RIOVersid(void) 382{ 383 strlcpy(stVersion.version, "RIO driver for linux V1.0", 384 sizeof(stVersion.version)); 385 strlcpy(stVersion.buildDate, __DATE__, 386 sizeof(stVersion.buildDate)); 387 388 return &stVersion; 389} 390 391void RIOHostReset(unsigned int Type, struct DpRam __iomem *DpRamP, unsigned int Slot) 392{ 393 /* 394 ** Reset the Tpu 395 */ 396 rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: type 0x%x", Type); 397 switch ( Type ) { 398 case RIO_AT: 399 rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n"); 400 writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | BYTE_OPERATION | 401 SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl); 402 writeb(0xFF, &DpRamP->DpResetTpu); 403 udelay(3); 404 rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: Don't know if it worked. Try reset again\n"); 405 writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | 406 BYTE_OPERATION | SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl); 407 writeb(0xFF, &DpRamP->DpResetTpu); 408 udelay(3); 409 break; 410 case RIO_PCI: 411 rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n"); 412 writeb(RIO_PCI_BOOT_FROM_RAM, &DpRamP->DpControl); 413 writeb(0xFF, &DpRamP->DpResetInt); 414 writeb(0xFF, &DpRamP->DpResetTpu); 415 udelay(100); 416 break; 417 default: 418 rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n"); 419 break; 420 } 421 return; 422}