|
|
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.