1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,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 Software.Distribution@CS.CMU.EDU
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 * HISTORY
28 * $Log: mapped_scsi.c,v $
29 * Revision 2.18 93/11/17 18:41:45 dbg
30 * Changed mmap routines to return physical address instead of
31 * physical page number.
32 * [93/06/16 dbg]
33 *
34 * Revision 2.17 93/05/15 19:42:22 mrt
35 * machparam.h -> machspl.h
36 *
37 * Revision 2.16 93/05/10 21:22:13 rvb
38 * No more sys/types.
39 * [93/05/06 10:04:40 af]
40 *
41 * Revision 2.15 93/01/14 17:55:03 danner
42 * Proper spl typing.
43 * [92/12/01 af]
44 *
45 * Revision 2.14 92/01/03 20:42:47 dbg
46 * No need to destroy/init the eventcounter all the time.
47 * [91/12/27 af]
48 *
49 * Since we are actually using this, make user-safe.
50 * [91/12/27 af]
51 *
52 * Revision 2.13 91/12/13 14:55:18 jsb
53 * Use eventcounters.
54 * [91/11/08 12:11:44 af]
55 *
56 * Revision 2.12 91/10/09 16:16:42 af
57 * Changing the header files broke this module cuz padding, fixed now.
58 * Made to work with the DEC driver first, and then with our driver
59 * in user space.
60 * [91/10/05 10:23:39 af]
61 *
62 * Revision 2.11 91/08/24 12:27:36 af
63 * Spl defs.
64 * [91/08/02 03:45:16 af]
65 *
66 * Revision 2.10 91/06/25 20:56:05 rpd
67 * Tweaks to make gcc happy.
68 *
69 * Revision 2.9 91/06/19 11:56:42 rvb
70 * minor improvements
71 * [91/06/18 21:34:58 rvb]
72 *
73 * mips->DECSTATION; vax->VAXSTATION
74 * [91/06/12 14:02:17 rvb]
75 *
76 * File moved here from mips/PMAX since it is now "MI" code, also
77 * used by Vax3100 and soon -- the omron luna88k.
78 * [91/06/04 rvb]
79 *
80 * Revision 2.8 91/05/14 17:24:01 mrt
81 * Correcting copyright
82 *
83 * Revision 2.7 91/05/13 06:35:07 af
84 * Check for spurious interrupts before disabling them.
85 *
86 * Revision 2.6 91/03/16 14:54:20 rpd
87 * Updated for new kmem_alloc interface.
88 * [91/03/03 rpd]
89 * Removed thread_swappable.
90 * [91/01/18 rpd]
91 *
92 * Revision 2.5 91/02/14 14:34:32 mrt
93 * In interrupt routines, drop priority as now required.
94 * Also, sanity check against spurious interrupts.
95 * [91/02/12 13:17:21 af]
96 *
97 * Revision 2.4 91/02/05 17:42:25 mrt
98 * Added author notices
99 * [91/02/04 11:14:48 mrt]
100 *
101 * Changed to use new Mach copyright
102 * [91/02/02 12:13:25 mrt]
103 *
104 * Revision 2.3 90/12/05 23:32:20 af
105 *
106 *
107 * Revision 2.1.1.2 90/11/13 15:10:18 af
108 * Added pmax support.
109 *
110 * Revision 2.1.1.1 90/11/01 02:44:02 af
111 * Created.
112 * [90/09/12 af]
113 *
114 */
115 /*
116 * File: mapped_scsi.c
117 * Author: Alessandro Forin, Carnegie Mellon University
118 * Date: 9/90
119 *
120 * In-kernel side of the user-mapped SCSI driver.
121 */
122
123 #include <asc.h>
124 #include <sii.h>
125 #define NRZ (NASC+NSII)
126 #if NRZ > 0
127 #include <platforms.h>
128
129 #include <machine/machspl.h> /* spl definitions */
130
131 #include <device/device_types.h>
132 #include <device/io_req.h>
133 #include <chips/busses.h>
134
135 #include <vm/vm_kern.h>
136 #include <kern/eventcount.h>
137
138 #include <scsi/mapped_scsi.h>
139
140 #include <machine/machspl.h>
141
142 #ifdef DECSTATION
143
144 #define machine_btop mips_btop
145
146 #define kvctophys(v) K0SEG_TO_PHYS((v)) /* kernel virtual cached */
147 #define phystokvc(p) PHYS_TO_K0SEG((p)) /* and back */
148 #define kvutophys(v) K1SEG_TO_PHYS((v)) /* kernel virtual uncached */
149 #define phystokvu(p) PHYS_TO_K1SEG((p)) /* and back */
150
151 #include <mips/mips_cpu.h>
152 #include <mips/PMAX/kn01.h>
153 #include <mips/PMAX/pmaz_aa.h>
154
155 #define SII_REG_PHYS(self) kvutophys(self->registers.any)
156 #define SII_RAM_PHYS(self) (SII_REG_PHYS((self))+(KN01_SYS_SII_B_START-KN01_SYS_SII))
157 #define SII_RAM_SIZE (KN01_SYS_SII_B_END-KN01_SYS_SII_B_START)
158
159 #define ASC_REG_PHYS(self) kvutophys(self->registers.any)
160 #define ASC_DMAR_PHYS(self) (ASC_REG_PHYS((self))+ ASC_OFFSET_DMAR)
161 #define ASC_RAM_PHYS(self) (ASC_REG_PHYS((self))+ ASC_OFFSET_RAM)
162
163 #define PAD_7061(n) short n
164 #define PAD_53C94(n) char n[3]
165
166 #endif /*DECSTATION*/
167
168 #ifdef VAXSTATION
169 #define machine_btop vax_btop
170 #endif /*VAXSTATION*/
171
172
173 /*
174 * Phys defines for the various supported HBAs
175 */
176
177 /* DEC7061 */
178 #include <scsi/adapters/scsi_7061.h>
179
180 #ifdef PAD_7061
181
182 typedef struct {
183 volatile unsigned short sii_sdb; /* rw: Data bus and parity */
184 PAD_7061(pad0);
185 volatile unsigned short sii_sc1; /* rw: scsi signals 1 */
186 PAD_7061(pad1);
187 volatile unsigned short sii_sc2; /* rw: scsi signals 2 */
188 PAD_7061(pad2);
189 volatile unsigned short sii_csr; /* rw: control and status */
190 PAD_7061(pad3);
191 volatile unsigned short sii_id; /* rw: scsi bus ID */
192 PAD_7061(pad4);
193 volatile unsigned short sii_sel_csr; /* rw: selection status */
194 PAD_7061(pad5);
195 volatile unsigned short sii_destat; /* ro: selection detector status */
196 PAD_7061(pad6);
197 volatile unsigned short sii_dstmo; /* unsupp: dssi timeout */
198 PAD_7061(pad7);
199 volatile unsigned short sii_data; /* rw: data register */
200 PAD_7061(pad8);
201 volatile unsigned short sii_dma_ctrl; /* rw: dma control reg */
202 PAD_7061(pad9);
203 volatile unsigned short sii_dma_len; /* rw: length of transfer */
204 PAD_7061(pad10);
205 volatile unsigned short sii_dma_adr_low;/* rw: low address */
206 PAD_7061(pad11);
207 volatile unsigned short sii_dma_adr_hi; /* rw: high address */
208 PAD_7061(pad12);
209 volatile unsigned short sii_dma_1st_byte;/* rw: initial byte */
210 PAD_7061(pad13);
211 volatile unsigned short sii_stlp; /* unsupp: dssi short trgt list ptr */
212 PAD_7061(pad14);
213 volatile unsigned short sii_ltlp; /* unsupp: dssi long " " " */
214 PAD_7061(pad15);
215 volatile unsigned short sii_ilp; /* unsupp: dssi initiator list ptr */
216 PAD_7061(pad16);
217 volatile unsigned short sii_dssi_csr; /* unsupp: dssi control */
218 PAD_7061(pad17);
219 volatile unsigned short sii_conn_csr; /* rc: connection interrupt control */
220 PAD_7061(pad18);
221 volatile unsigned short sii_data_csr; /* rc: data interrupt control */
222 PAD_7061(pad19);
223 volatile unsigned short sii_cmd; /* rw: command register */
224 PAD_7061(pad20);
225 volatile unsigned short sii_diag_csr; /* rw: disgnostic status */
226 PAD_7061(pad21);
227 } sii_padded_regmap_t;
228
229 #else /*!PAD_7061*/
230
231 typedef sii_regmap_t sii_padded_regmap_t;
232
233 #endif /*!PAD_7061*/
234
235 /* NCR 53C94 */
236 #include <scsi/adapters/scsi_53C94.h>
237
238 #ifdef PAD_53C94
239 typedef struct {
240 volatile unsigned char asc_tc_lsb; /* rw: Transfer Counter LSB */
241 PAD_53C94(pad0);
242 volatile unsigned char asc_tc_msb; /* rw: Transfer Counter MSB */
243 PAD_53C94(pad1);
244 volatile unsigned char asc_fifo; /* rw: FIFO top */
245 PAD_53C94(pad2);
246 volatile unsigned char asc_cmd; /* rw: Command */
247 PAD_53C94(pad3);
248 volatile unsigned char asc_csr; /* r: Status */
249 /*#define asc_dbus_id asc_csr /* w: Destination Bus ID */
250 PAD_53C94(pad4);
251 volatile unsigned char asc_intr; /* r: Interrupt */
252 /*#define asc_sel_timo asc_intr /* w: (re)select timeout */
253 PAD_53C94(pad5);
254 volatile unsigned char asc_ss; /* r: Sequence Step */
255 /*#define asc_syn_p asc_ss /* w: synchronous period */
256 PAD_53C94(pad6);
257 volatile unsigned char asc_flags; /* r: FIFO flags + seq step */
258 /*#define asc_syn_o asc_flags /* w: synchronous offset */
259 PAD_53C94(pad7);
260 volatile unsigned char asc_cnfg1; /* rw: Configuration 1 */
261 PAD_53C94(pad8);
262 volatile unsigned char asc_ccf; /* w: Clock Conv. Factor */
263 PAD_53C94(pad9);
264 volatile unsigned char asc_test; /* w: Test Mode */
265 PAD_53C94(pad10);
266 volatile unsigned char asc_cnfg2; /* rw: Configuration 2 */
267 PAD_53C94(pad11);
268 volatile unsigned char asc_cnfg3; /* rw: Configuration 3 */
269 PAD_53C94(pad12);
270 volatile unsigned char asc_rfb; /* w: Reserve FIFO byte */
271 PAD_53C94(pad13);
272 } asc_padded_regmap_t;
273
274 #else /* !PAD_53C94 */
275
276 typedef asc_regmap_t asc_padded_regmap_t;
277
278 #endif /* !PAD_53C94 */
279
280 /*
281 * Co-existency with in-kernel drivers
282 */
283 boolean_t rz_use_mapped_interface = FALSE;
284
285 /*
286 * Status information for all HBAs
287 */
288 /*static*/ struct RZ_status {
289 union {
290 unsigned long any;
291 asc_padded_regmap_t *asc;
292 sii_padded_regmap_t *sii;
293 } registers;
294 int (*stop)();
295 vm_offset_t (*mmap)();
296 mapped_scsi_info_t info;
297 struct evc eventcounter;
298 } RZ_statii[NRZ];
299
300 typedef struct RZ_status *RZ_status_t;
301
302
303 /*
304 * Probe routine for all HBAs
305 */
306 RZ_probe(regbase, ui, hba)
307 unsigned long regbase;
308 register struct bus_device *ui;
309 {
310 int unit = ui->unit;
311 vm_offset_t addr;
312 mapped_scsi_info_t info;
313 struct RZ_status *self;
314
315 printf("[mappable] ");
316
317 self = &RZ_statii[unit];
318
319 self->registers.any = regbase;
320
321 /*
322 * Grab a page to be mapped later to users
323 */
324 (void) kmem_alloc_wired(kernel_map, &addr, PAGE_SIZE); /* kseg2 */
325 bzero(addr, PAGE_SIZE);
326 addr = pmap_extract(pmap_kernel(), addr); /* phys */
327 info = (mapped_scsi_info_t) (phystokvc(addr));
328 self->info = info;
329
330 /*
331 * Set permanent info
332 */
333 info->interrupt_count = 0;
334 /*XXX*/ info->ram_size = ASC_RAM_SIZE;
335 info->hba_type = hba;
336
337 evc_init(&self->eventcounter);
338 info->wait_event = self->eventcounter.ev_id;
339
340 return 1;
341 }
342
343 /*
344 * Device open procedure
345 */
346 RZ_open(dev, flag, ior)
347 io_req_t ior;
348 {
349 int unit = dev;
350 register RZ_status_t self = &RZ_statii[unit];
351
352
353 if (unit >= NRZ)
354 return D_NO_SUCH_DEVICE;
355
356 /*
357 * Silence interface, just in case
358 */
359 (*self->stop)(unit);
360
361 /*
362 * Reset eventcounter
363 */
364 evc_signal(&self->eventcounter);
365
366 rz_use_mapped_interface = TRUE;
367
368 /*
369 * Do not turn interrupts on. The user can do it when ready
370 * to take them.
371 */
372
373 return 0;
374 }
375
376 /*
377 * Device close procedure
378 */
379 RZ_close(dev, flag)
380 {
381 int unit = dev;
382 register RZ_status_t self = &RZ_statii[unit];
383
384 if (unit >= NRZ)
385 return D_NO_SUCH_DEVICE;
386
387 /*
388 * Silence interface, in case user forgot
389 */
390 (*self->stop)(unit);
391
392 evc_signal(&self->eventcounter);
393
394 rz_use_mapped_interface = FALSE;
395
396 /* XXX rz_kernel_mode(); XXX */
397
398 return 0;
399 }
400
401
402 /*
403 * Get status procedure.
404 * We need to tell that we are mappable.
405 */
406 io_return_t
407 RZ_get_status(dev, flavor, status, status_count)
408 int dev;
409 int flavor;
410 dev_status_t status;
411 unsigned int status_count;
412 {
413 return (D_SUCCESS);
414 }
415
416 /*
417 * Should not refuse this either
418 */
419 RZ_set_status(dev, flavor, status, status_count)
420 int dev;
421 int flavor;
422 dev_status_t status;
423 unsigned int status_count;
424 {
425 return (D_SUCCESS);
426 }
427
428 /*
429 * Port death notification routine
430 */
431 RZ_portdeath(dev, dead_port)
432 {
433 }
434
435 /*
436 * Page mapping, switch off to HBA-specific for regs&ram
437 */
438 vm_offset_t
439 RZ_mmap(dev, off, prot)
440 int dev;
441 {
442 int unit = dev;
443 register RZ_status_t self = &RZ_statii[unit];
444 vm_offset_t addr;
445 io_return_t ret;
446
447 if (off < SCSI_INFO_SIZE) {
448 addr = kvctophys (self->info) + off;
449 ret = D_SUCCESS;
450 } else
451 ret = (*self->mmap)(self, off, prot, &addr);
452
453 if (ret != D_SUCCESS)
454 return -1;
455
456 return addr;
457 }
458
459
460 /*
461 *---------------------------------------------------------------
462 * The rest of the file contains HBA-specific routines
463 *---------------------------------------------------------------
464 */
465
466 #if NASC > 0
467 /*
468 * Routines for the NCR 53C94
469 */
470 static
471 ASC_stop(unit)
472 {
473 register RZ_status_t self = &RZ_statii[unit];
474 register asc_padded_regmap_t *regs = self->registers.asc;
475 int ack;
476
477 ack = regs->asc_intr; /* Just acknowledge pending interrupts */
478 }
479
480 ASC_probe(reg, ui)
481 unsigned long reg;
482 register struct bus_device *ui;
483 {
484 register RZ_status_t self = &RZ_statii[ui->unit];
485 static vm_offset_t ASC_mmap();
486
487 self->stop = ASC_stop;
488 self->mmap = ASC_mmap;
489 return RZ_probe(reg, ui, HBA_NCR_53c94);
490 }
491
492
493 ASC_intr(unit,spllevel)
494 spl_t spllevel;
495 {
496 register RZ_status_t self = &RZ_statii[unit];
497 register asc_padded_regmap_t *regs = self->registers.asc;
498 register csr, intr, seq_step, cmd;
499
500 /*
501 * Acknowledge interrupt request
502 *
503 * This clobbers some two other registers, therefore
504 * we read them beforehand. It also clears the intr
505 * request bit, silencing the interface for now.
506 */
507 csr = regs->asc_csr;
508
509 /* drop spurious interrupts */
510 if ((csr & ASC_CSR_INT) == 0)
511 return;
512 seq_step = regs->asc_ss;
513 cmd = regs->asc_cmd;
514
515 intr = regs->asc_intr; /* ack */
516
517 splx(spllevel); /* drop priority */
518
519 if (self->info) {
520 self->info->interrupt_count++; /* total interrupts */
521 self->info->saved_regs.asc.csr = csr;
522 self->info->saved_regs.asc.isr = intr;
523 self->info->saved_regs.asc.seq = seq_step;
524 self->info->saved_regs.asc.cmd = cmd;
525 }
526
527 /* Awake user thread */
528 evc_signal(&self->eventcounter);
529 }
530
531 /*
532 * Virtual->physical mapping routine for PMAZ-AA
533 */
534 static vm_offset_t
535 ASC_mmap(self, off, prot, addr)
536 RZ_status_t self;
537 vm_offset_t off;
538 vm_prot_t prot;
539 vm_offset_t *addr;
540 {
541 /*
542 * The offset (into the VM object) defines the following layout
543 *
544 * off size what
545 * 0 1pg mapping information (csr & #interrupts)
546 * 1pg 1pg ASC registers
547 * 2pg 1pg ASC dma
548 * 3pg 128k ASC ram buffers
549 */
550
551 #define ASC_END (ASC_RAM_BASE+ASC_RAM_SIZE)
552
553 if (off < ASC_DMAR_BASE)
554 *addr = (vm_offset_t) ASC_REG_PHYS(self) + (off - SCSI_INFO_SIZE);
555 else if (off < ASC_RAM_BASE)
556 *addr = (vm_offset_t) ASC_DMAR_PHYS(self) + (off - ASC_REGS_BASE);
557 else if (off < ASC_END)
558 *addr = (vm_offset_t) ASC_RAM_PHYS(self) + (off - ASC_RAM_BASE);
559 else
560 return D_INVALID_SIZE;
561
562 return D_SUCCESS;
563 }
564 #endif NASC > 0
565
566 #if NSII > 0
567 SII_stop(unit)
568 {
569 register RZ_status_t self = &RZ_statii[unit];
570 register sii_padded_regmap_t *regs = self->registers.sii;
571
572 regs->sii_csr &= ~SII_CSR_IE; /* disable interrupts */
573 /* clear all wtc bits */
574 regs->sii_conn_csr = regs->sii_conn_csr;
575 regs->sii_data_csr = regs->sii_data_csr;
576 }
577
578 SII_probe(reg, ui)
579 unsigned long reg;
580 register struct bus_device *ui;
581 {
582 register RZ_status_t self = &RZ_statii[ui->unit];
583 static vm_offset_t SII_mmap();
584
585 self->stop = SII_stop;
586 self->mmap = SII_mmap;
587 return RZ_probe(reg, ui, HBA_DEC_7061);
588 }
589
590 SII_intr(unit,spllevel)
591 spl_t spllevel;
592 {
593 register RZ_status_t self = &RZ_statii[unit];
594 register sii_padded_regmap_t *regs = self->registers.sii;
595 register unsigned short conn, data;
596
597 /*
598 * Disable interrupts, saving cause(s) first.
599 */
600 conn = regs->sii_conn_csr;
601 data = regs->sii_data_csr;
602
603 /* drop spurious calls */
604 if (((conn|data) & (SII_DTR_DI|SII_DTR_CI)) == 0)
605 return;
606
607 regs->sii_csr &= ~SII_CSR_IE;
608
609 regs->sii_conn_csr = conn;
610 regs->sii_data_csr = data;
611
612 splx(spllevel);
613
614 if (self->info) {
615 self->info->interrupt_count++; /* total interrupts */
616 self->info->saved_regs.sii.sii_conn_csr = conn;
617 self->info->saved_regs.sii.sii_data_csr = data;
618 }
619
620 /* Awake user thread */
621 evc_signal(&self->eventcounter);
622 }
623
624 static vm_offset_t
625 SII_mmap(self, off, prot, addr)
626 RZ_status_t self;
627 vm_offset_t off;
628 vm_prot_t prot;
629 vm_offset_t *addr;
630 {
631 /*
632 * The offset (into the VM object) defines the following layout
633 *
634 * off size what
635 * 0 1pg mapping information (csr & #interrupts)
636 * 1pg 1pg SII registers
637 * 2pg 128k SII ram buffer
638 */
639
640 #define SII_END (SII_RAM_BASE+SII_RAM_SIZE)
641
642 if (off < SII_RAM_BASE)
643 *addr = (vm_offset_t) SII_REG_PHYS(self) + (off - SCSI_INFO_SIZE);
644 else if (off < SII_END)
645 *addr = (vm_offset_t) SII_RAM_PHYS(self) + (off - SII_RAM_BASE);
646 else
647 return D_INVALID_SIZE;
648
649 return D_SUCCESS;
650 }
651 #endif NSII > 0
652
653 #endif NRZ > 0
Cache object: a4418784577c7ddf73fbd2d9ced08992
|