|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * File: mapped_scsi.c ! 28: * Author: Alessandro Forin, Carnegie Mellon University ! 29: * Date: 9/90 ! 30: * ! 31: * In-kernel side of the user-mapped SCSI driver. ! 32: */ ! 33: ! 34: #include <asc.h> ! 35: #include <sii.h> ! 36: #define NRZ (NASC+NSII) ! 37: #if NRZ > 0 ! 38: #include <platforms.h> ! 39: ! 40: #include <machine/machspl.h> /* spl definitions */ ! 41: ! 42: #include <device/device_types.h> ! 43: #include <device/io_req.h> ! 44: #include <chips/busses.h> ! 45: ! 46: #include <vm/vm_kern.h> ! 47: #include <kern/eventcount.h> ! 48: ! 49: #include <scsi/mapped_scsi.h> ! 50: ! 51: #include <machine/machspl.h> ! 52: ! 53: #ifdef DECSTATION ! 54: ! 55: #define machine_btop mips_btop ! 56: ! 57: #define kvctophys(v) K0SEG_TO_PHYS((v)) /* kernel virtual cached */ ! 58: #define phystokvc(p) PHYS_TO_K0SEG((p)) /* and back */ ! 59: #define kvutophys(v) K1SEG_TO_PHYS((v)) /* kernel virtual uncached */ ! 60: #define phystokvu(p) PHYS_TO_K1SEG((p)) /* and back */ ! 61: ! 62: #include <mips/mips_cpu.h> ! 63: #include <mips/PMAX/kn01.h> ! 64: #include <mips/PMAX/pmaz_aa.h> ! 65: ! 66: #define SII_REG_PHYS(self) kvutophys(self->registers.any) ! 67: #define SII_RAM_PHYS(self) (SII_REG_PHYS((self))+(KN01_SYS_SII_B_START-KN01_SYS_SII)) ! 68: #define SII_RAM_SIZE (KN01_SYS_SII_B_END-KN01_SYS_SII_B_START) ! 69: ! 70: #define ASC_REG_PHYS(self) kvutophys(self->registers.any) ! 71: #define ASC_DMAR_PHYS(self) (ASC_REG_PHYS((self))+ ASC_OFFSET_DMAR) ! 72: #define ASC_RAM_PHYS(self) (ASC_REG_PHYS((self))+ ASC_OFFSET_RAM) ! 73: ! 74: #define PAD_7061(n) short n ! 75: #define PAD_53C94(n) char n[3] ! 76: ! 77: #endif /*DECSTATION*/ ! 78: ! 79: #ifdef VAXSTATION ! 80: #define machine_btop vax_btop ! 81: #endif /*VAXSTATION*/ ! 82: ! 83: #ifdef P40 ! 84: ! 85: #define machine_btop mips_btop ! 86: ! 87: #define kvctophys(v) K0SEG_TO_PHYS((v)) /* kernel virtual cached */ ! 88: #define phystokvc(p) PHYS_TO_K0SEG((p)) /* and back */ ! 89: #define kvutophys(v) K1SEG_TO_PHYS((v)) /* kernel virtual uncached */ ! 90: #define phystokvu(p) PHYS_TO_K1SEG((p)) /* and back */ ! 91: ! 92: #include <mips/mips_cpu.h> ! 93: ! 94: #define ASC_RAM_SIZE 0 ! 95: #define ASC_OFFSET_DMAR 0 ! 96: #define ASC_OFFSET_RAM 0 ! 97: ! 98: #define ASC_REG_PHYS(self) kvutophys(self->registers.any) ! 99: #define ASC_DMAR_PHYS(self) (ASC_REG_PHYS((self))+ ASC_OFFSET_DMAR) ! 100: #define ASC_RAM_PHYS(self) (ASC_REG_PHYS((self))+ ASC_OFFSET_RAM) ! 101: #endif /* P40 */ ! 102: ! 103: /* ! 104: * Phys defines for the various supported HBAs ! 105: */ ! 106: ! 107: /* DEC7061 */ ! 108: #include <scsi/adapters/scsi_7061.h> ! 109: ! 110: #ifdef PAD_7061 ! 111: ! 112: typedef struct { ! 113: volatile unsigned short sii_sdb; /* rw: Data bus and parity */ ! 114: PAD_7061(pad0); ! 115: volatile unsigned short sii_sc1; /* rw: scsi signals 1 */ ! 116: PAD_7061(pad1); ! 117: volatile unsigned short sii_sc2; /* rw: scsi signals 2 */ ! 118: PAD_7061(pad2); ! 119: volatile unsigned short sii_csr; /* rw: control and status */ ! 120: PAD_7061(pad3); ! 121: volatile unsigned short sii_id; /* rw: scsi bus ID */ ! 122: PAD_7061(pad4); ! 123: volatile unsigned short sii_sel_csr; /* rw: selection status */ ! 124: PAD_7061(pad5); ! 125: volatile unsigned short sii_destat; /* ro: selection detector status */ ! 126: PAD_7061(pad6); ! 127: volatile unsigned short sii_dstmo; /* unsupp: dssi timeout */ ! 128: PAD_7061(pad7); ! 129: volatile unsigned short sii_data; /* rw: data register */ ! 130: PAD_7061(pad8); ! 131: volatile unsigned short sii_dma_ctrl; /* rw: dma control reg */ ! 132: PAD_7061(pad9); ! 133: volatile unsigned short sii_dma_len; /* rw: length of transfer */ ! 134: PAD_7061(pad10); ! 135: volatile unsigned short sii_dma_adr_low;/* rw: low address */ ! 136: PAD_7061(pad11); ! 137: volatile unsigned short sii_dma_adr_hi; /* rw: high address */ ! 138: PAD_7061(pad12); ! 139: volatile unsigned short sii_dma_1st_byte;/* rw: initial byte */ ! 140: PAD_7061(pad13); ! 141: volatile unsigned short sii_stlp; /* unsupp: dssi short trgt list ptr */ ! 142: PAD_7061(pad14); ! 143: volatile unsigned short sii_ltlp; /* unsupp: dssi long " " " */ ! 144: PAD_7061(pad15); ! 145: volatile unsigned short sii_ilp; /* unsupp: dssi initiator list ptr */ ! 146: PAD_7061(pad16); ! 147: volatile unsigned short sii_dssi_csr; /* unsupp: dssi control */ ! 148: PAD_7061(pad17); ! 149: volatile unsigned short sii_conn_csr; /* rc: connection interrupt control */ ! 150: PAD_7061(pad18); ! 151: volatile unsigned short sii_data_csr; /* rc: data interrupt control */ ! 152: PAD_7061(pad19); ! 153: volatile unsigned short sii_cmd; /* rw: command register */ ! 154: PAD_7061(pad20); ! 155: volatile unsigned short sii_diag_csr; /* rw: disgnostic status */ ! 156: PAD_7061(pad21); ! 157: } sii_padded_regmap_t; ! 158: ! 159: #else /*!PAD_7061*/ ! 160: ! 161: typedef sii_regmap_t sii_padded_regmap_t; ! 162: ! 163: #endif /*!PAD_7061*/ ! 164: ! 165: /* NCR 53C94 */ ! 166: #include <scsi/adapters/scsi_53C94.h> ! 167: ! 168: #ifdef PAD_53C94 ! 169: typedef struct { ! 170: volatile unsigned char asc_tc_lsb; /* rw: Transfer Counter LSB */ ! 171: PAD_53C94(pad0); ! 172: volatile unsigned char asc_tc_msb; /* rw: Transfer Counter MSB */ ! 173: PAD_53C94(pad1); ! 174: volatile unsigned char asc_fifo; /* rw: FIFO top */ ! 175: PAD_53C94(pad2); ! 176: volatile unsigned char asc_cmd; /* rw: Command */ ! 177: PAD_53C94(pad3); ! 178: volatile unsigned char asc_csr; /* r: Status */ ! 179: /*#define asc_dbus_id asc_csr /* w: Destination Bus ID */ ! 180: PAD_53C94(pad4); ! 181: volatile unsigned char asc_intr; /* r: Interrupt */ ! 182: /*#define asc_sel_timo asc_intr /* w: (re)select timeout */ ! 183: PAD_53C94(pad5); ! 184: volatile unsigned char asc_ss; /* r: Sequence Step */ ! 185: /*#define asc_syn_p asc_ss /* w: synchronous period */ ! 186: PAD_53C94(pad6); ! 187: volatile unsigned char asc_flags; /* r: FIFO flags + seq step */ ! 188: /*#define asc_syn_o asc_flags /* w: synchronous offset */ ! 189: PAD_53C94(pad7); ! 190: volatile unsigned char asc_cnfg1; /* rw: Configuration 1 */ ! 191: PAD_53C94(pad8); ! 192: volatile unsigned char asc_ccf; /* w: Clock Conv. Factor */ ! 193: PAD_53C94(pad9); ! 194: volatile unsigned char asc_test; /* w: Test Mode */ ! 195: PAD_53C94(pad10); ! 196: volatile unsigned char asc_cnfg2; /* rw: Configuration 2 */ ! 197: PAD_53C94(pad11); ! 198: volatile unsigned char asc_cnfg3; /* rw: Configuration 3 */ ! 199: PAD_53C94(pad12); ! 200: volatile unsigned char asc_rfb; /* w: Reserve FIFO byte */ ! 201: PAD_53C94(pad13); ! 202: } asc_padded_regmap_t; ! 203: ! 204: #else /* !PAD_53C94 */ ! 205: ! 206: typedef asc_regmap_t asc_padded_regmap_t; ! 207: ! 208: #endif /* !PAD_53C94 */ ! 209: ! 210: /* ! 211: * Co-existency with in-kernel drivers ! 212: */ ! 213: boolean_t rz_use_mapped_interface = FALSE; ! 214: ! 215: /* ! 216: * Status information for all HBAs ! 217: */ ! 218: /*static*/ struct RZ_status { ! 219: union { ! 220: unsigned long any; ! 221: asc_padded_regmap_t *asc; ! 222: sii_padded_regmap_t *sii; ! 223: } registers; ! 224: int (*stop)(); ! 225: vm_offset_t (*mmap)(); ! 226: mapped_scsi_info_t info; ! 227: struct evc eventcounter; ! 228: } RZ_statii[NRZ]; ! 229: ! 230: typedef struct RZ_status *RZ_status_t; ! 231: ! 232: ! 233: /* ! 234: * Probe routine for all HBAs ! 235: */ ! 236: RZ_probe(regbase, ui, hba) ! 237: unsigned long regbase; ! 238: register struct bus_device *ui; ! 239: { ! 240: int unit = ui->unit; ! 241: vm_offset_t addr; ! 242: mapped_scsi_info_t info; ! 243: struct RZ_status *self; ! 244: ! 245: printf("[mappable] "); ! 246: ! 247: self = &RZ_statii[unit]; ! 248: ! 249: self->registers.any = regbase; ! 250: ! 251: /* ! 252: * Grab a page to be mapped later to users ! 253: */ ! 254: (void) kmem_alloc_wired(kernel_map, &addr, PAGE_SIZE); /* kseg2 */ ! 255: bzero(addr, PAGE_SIZE); ! 256: addr = pmap_extract(pmap_kernel(), addr); /* phys */ ! 257: info = (mapped_scsi_info_t) (phystokvc(addr)); ! 258: self->info = info; ! 259: ! 260: /* ! 261: * Set permanent info ! 262: */ ! 263: info->interrupt_count = 0; ! 264: /*XXX*/ info->ram_size = ASC_RAM_SIZE; ! 265: info->hba_type = hba; ! 266: ! 267: evc_init(&self->eventcounter); ! 268: info->wait_event = self->eventcounter.ev_id; ! 269: ! 270: return 1; ! 271: } ! 272: ! 273: /* ! 274: * Device open procedure ! 275: */ ! 276: RZ_open(dev, flag, ior) ! 277: io_req_t ior; ! 278: { ! 279: int unit = dev; ! 280: register RZ_status_t self = &RZ_statii[unit]; ! 281: ! 282: ! 283: if (unit >= NRZ) ! 284: return D_NO_SUCH_DEVICE; ! 285: ! 286: /* ! 287: * Silence interface, just in case ! 288: */ ! 289: (*self->stop)(unit); ! 290: ! 291: /* ! 292: * Reset eventcounter ! 293: */ ! 294: evc_signal(&self->eventcounter); ! 295: ! 296: rz_use_mapped_interface = TRUE; ! 297: ! 298: /* ! 299: * Do not turn interrupts on. The user can do it when ready ! 300: * to take them. ! 301: */ ! 302: ! 303: return 0; ! 304: } ! 305: ! 306: /* ! 307: * Device close procedure ! 308: */ ! 309: RZ_close(dev, flag) ! 310: { ! 311: int unit = dev; ! 312: register RZ_status_t self = &RZ_statii[unit]; ! 313: ! 314: if (unit >= NRZ) ! 315: return D_NO_SUCH_DEVICE; ! 316: ! 317: /* ! 318: * Silence interface, in case user forgot ! 319: */ ! 320: (*self->stop)(unit); ! 321: ! 322: evc_signal(&self->eventcounter); ! 323: ! 324: rz_use_mapped_interface = FALSE; ! 325: ! 326: /* XXX rz_kernel_mode(); XXX */ ! 327: ! 328: return 0; ! 329: } ! 330: ! 331: ! 332: /* ! 333: * Get status procedure. ! 334: * We need to tell that we are mappable. ! 335: */ ! 336: io_return_t ! 337: RZ_get_status(dev, flavor, status, status_count) ! 338: int dev; ! 339: int flavor; ! 340: dev_status_t status; ! 341: unsigned int status_count; ! 342: { ! 343: return (D_SUCCESS); ! 344: } ! 345: ! 346: /* ! 347: * Should not refuse this either ! 348: */ ! 349: RZ_set_status(dev, flavor, status, status_count) ! 350: int dev; ! 351: int flavor; ! 352: dev_status_t status; ! 353: unsigned int status_count; ! 354: { ! 355: return (D_SUCCESS); ! 356: } ! 357: ! 358: /* ! 359: * Port death notification routine ! 360: */ ! 361: RZ_portdeath(dev, dead_port) ! 362: { ! 363: } ! 364: ! 365: /* ! 366: * Page mapping, switch off to HBA-specific for regs&ram ! 367: */ ! 368: vm_offset_t ! 369: RZ_mmap(dev, off, prot) ! 370: int dev; ! 371: { ! 372: int unit = dev; ! 373: register RZ_status_t self = &RZ_statii[unit]; ! 374: vm_offset_t page; ! 375: vm_offset_t addr; ! 376: io_return_t ret; ! 377: ! 378: if (off < SCSI_INFO_SIZE) { ! 379: addr = kvctophys (self->info) + off; ! 380: ret = D_SUCCESS; ! 381: } else ! 382: ret = (*self->mmap)(self, off, prot, &addr); ! 383: ! 384: if (ret != D_SUCCESS) ! 385: return ret; ! 386: ! 387: page = machine_btop(addr); ! 388: ! 389: return (page); ! 390: } ! 391: ! 392: ! 393: /* ! 394: *--------------------------------------------------------------- ! 395: * The rest of the file contains HBA-specific routines ! 396: *--------------------------------------------------------------- ! 397: */ ! 398: ! 399: #if NASC > 0 ! 400: /* ! 401: * Routines for the NCR 53C94 ! 402: */ ! 403: static ! 404: ASC_stop(unit) ! 405: { ! 406: register RZ_status_t self = &RZ_statii[unit]; ! 407: register asc_padded_regmap_t *regs = self->registers.asc; ! 408: int ack; ! 409: ! 410: ack = regs->asc_intr; /* Just acknowledge pending interrupts */ ! 411: } ! 412: ! 413: ASC_probe(reg, ui) ! 414: unsigned long reg; ! 415: register struct bus_device *ui; ! 416: { ! 417: register RZ_status_t self = &RZ_statii[ui->unit]; ! 418: static vm_offset_t ASC_mmap(); ! 419: ! 420: self->stop = ASC_stop; ! 421: self->mmap = ASC_mmap; ! 422: return RZ_probe(reg, ui, HBA_NCR_53c94); ! 423: } ! 424: ! 425: ! 426: ASC_intr(unit,spllevel) ! 427: spl_t spllevel; ! 428: { ! 429: register RZ_status_t self = &RZ_statii[unit]; ! 430: register asc_padded_regmap_t *regs = self->registers.asc; ! 431: register csr, intr, seq_step, cmd; ! 432: ! 433: /* ! 434: * Acknowledge interrupt request ! 435: * ! 436: * This clobbers some two other registers, therefore ! 437: * we read them beforehand. It also clears the intr ! 438: * request bit, silencing the interface for now. ! 439: */ ! 440: csr = regs->asc_csr; ! 441: ! 442: /* drop spurious interrupts */ ! 443: if ((csr & ASC_CSR_INT) == 0) ! 444: return; ! 445: seq_step = regs->asc_ss; ! 446: cmd = regs->asc_cmd; ! 447: ! 448: intr = regs->asc_intr; /* ack */ ! 449: ! 450: splx(spllevel); /* drop priority */ ! 451: ! 452: if (self->info) { ! 453: self->info->interrupt_count++; /* total interrupts */ ! 454: self->info->saved_regs.asc.csr = csr; ! 455: self->info->saved_regs.asc.isr = intr; ! 456: self->info->saved_regs.asc.seq = seq_step; ! 457: self->info->saved_regs.asc.cmd = cmd; ! 458: } ! 459: ! 460: /* Awake user thread */ ! 461: evc_signal(&self->eventcounter); ! 462: } ! 463: ! 464: /* ! 465: * Virtual->physical mapping routine for PMAZ-AA ! 466: */ ! 467: static vm_offset_t ! 468: ASC_mmap(self, off, prot, addr) ! 469: RZ_status_t self; ! 470: vm_offset_t off; ! 471: vm_prot_t prot; ! 472: vm_offset_t *addr; ! 473: { ! 474: /* ! 475: * The offset (into the VM object) defines the following layout ! 476: * ! 477: * off size what ! 478: * 0 1pg mapping information (csr & #interrupts) ! 479: * 1pg 1pg ASC registers ! 480: * 2pg 1pg ASC dma ! 481: * 3pg 128k ASC ram buffers ! 482: */ ! 483: ! 484: #define ASC_END (ASC_RAM_BASE+ASC_RAM_SIZE) ! 485: ! 486: if (off < ASC_DMAR_BASE) ! 487: *addr = (vm_offset_t) ASC_REG_PHYS(self) + (off - SCSI_INFO_SIZE); ! 488: else if (off < ASC_RAM_BASE) ! 489: *addr = (vm_offset_t) ASC_DMAR_PHYS(self) + (off - ASC_REGS_BASE); ! 490: else if (off < ASC_END) ! 491: *addr = (vm_offset_t) ASC_RAM_PHYS(self) + (off - ASC_RAM_BASE); ! 492: else ! 493: return D_INVALID_SIZE; ! 494: ! 495: return D_SUCCESS; ! 496: } ! 497: #endif NASC > 0 ! 498: ! 499: #if NSII > 0 ! 500: SII_stop(unit) ! 501: { ! 502: register RZ_status_t self = &RZ_statii[unit]; ! 503: register sii_padded_regmap_t *regs = self->registers.sii; ! 504: ! 505: regs->sii_csr &= ~SII_CSR_IE; /* disable interrupts */ ! 506: /* clear all wtc bits */ ! 507: regs->sii_conn_csr = regs->sii_conn_csr; ! 508: regs->sii_data_csr = regs->sii_data_csr; ! 509: } ! 510: ! 511: SII_probe(reg, ui) ! 512: unsigned long reg; ! 513: register struct bus_device *ui; ! 514: { ! 515: register RZ_status_t self = &RZ_statii[ui->unit]; ! 516: static vm_offset_t SII_mmap(); ! 517: ! 518: self->stop = SII_stop; ! 519: self->mmap = SII_mmap; ! 520: return RZ_probe(reg, ui, HBA_DEC_7061); ! 521: } ! 522: ! 523: SII_intr(unit,spllevel) ! 524: spl_t spllevel; ! 525: { ! 526: register RZ_status_t self = &RZ_statii[unit]; ! 527: register sii_padded_regmap_t *regs = self->registers.sii; ! 528: register unsigned short conn, data; ! 529: ! 530: /* ! 531: * Disable interrupts, saving cause(s) first. ! 532: */ ! 533: conn = regs->sii_conn_csr; ! 534: data = regs->sii_data_csr; ! 535: ! 536: /* drop spurious calls */ ! 537: if (((conn|data) & (SII_DTR_DI|SII_DTR_CI)) == 0) ! 538: return; ! 539: ! 540: regs->sii_csr &= ~SII_CSR_IE; ! 541: ! 542: regs->sii_conn_csr = conn; ! 543: regs->sii_data_csr = data; ! 544: ! 545: splx(spllevel); ! 546: ! 547: if (self->info) { ! 548: self->info->interrupt_count++; /* total interrupts */ ! 549: self->info->saved_regs.sii.sii_conn_csr = conn; ! 550: self->info->saved_regs.sii.sii_data_csr = data; ! 551: } ! 552: ! 553: /* Awake user thread */ ! 554: evc_signal(&self->eventcounter); ! 555: } ! 556: ! 557: static vm_offset_t ! 558: SII_mmap(self, off, prot, addr) ! 559: RZ_status_t self; ! 560: vm_offset_t off; ! 561: vm_prot_t prot; ! 562: vm_offset_t *addr; ! 563: { ! 564: /* ! 565: * The offset (into the VM object) defines the following layout ! 566: * ! 567: * off size what ! 568: * 0 1pg mapping information (csr & #interrupts) ! 569: * 1pg 1pg SII registers ! 570: * 2pg 128k SII ram buffer ! 571: */ ! 572: ! 573: #define SII_END (SII_RAM_BASE+SII_RAM_SIZE) ! 574: ! 575: if (off < SII_RAM_BASE) ! 576: *addr = (vm_offset_t) SII_REG_PHYS(self) + (off - SCSI_INFO_SIZE); ! 577: else if (off < SII_END) ! 578: *addr = (vm_offset_t) SII_RAM_PHYS(self) + (off - SII_RAM_BASE); ! 579: else ! 580: return D_INVALID_SIZE; ! 581: ! 582: return D_SUCCESS; ! 583: } ! 584: #endif NSII > 0 ! 585: ! 586: #endif NRZ > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.