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