Commit | Line | Data |
---|---|---|
d6489fd6 MK |
1 | /* |
2 | * Copyright (c) 1988 Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Chris Torek. | |
7 | * | |
af359dea C |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | |
16 | * 3. All advertising materials mentioning features or use of this software | |
17 | * must display the following acknowledgement: | |
18 | * This product includes software developed by the University of | |
19 | * California, Berkeley and its contributors. | |
20 | * 4. Neither the name of the University nor the names of its contributors | |
21 | * may be used to endorse or promote products derived from this software | |
22 | * without specific prior written permission. | |
d6489fd6 | 23 | * |
af359dea C |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34 | * SUCH DAMAGE. | |
35 | * | |
36 | * @(#)rx50.c 7.5 (Berkeley) 12/16/90 | |
d6489fd6 MK |
37 | */ |
38 | ||
39 | #if VAX8200 | |
40 | ||
41 | /* | |
42 | * Routines to handle the console RX50. | |
43 | */ | |
44 | ||
b28b3a13 KB |
45 | #include "sys/param.h" |
46 | #include "sys/time.h" | |
47 | #include "sys/kernel.h" | |
48 | #include "sys/vmmac.h" | |
49 | #include "sys/buf.h" | |
50 | #include "sys/errno.h" | |
51 | #include "sys/uio.h" | |
d6489fd6 | 52 | |
b28b3a13 | 53 | #include "../include/cpu.h" |
d6489fd6 MK |
54 | #include "rx50reg.h" |
55 | ||
56 | struct rx50device rx50device; | |
57 | ||
58 | #define rx50unit(dev) minor(dev) | |
59 | ||
60 | struct rx50state { | |
61 | short rs_flags; /* see below */ | |
62 | short rs_drive; /* current drive number */ | |
63 | u_int rs_blkno; /* current block number */ | |
64 | } rx50state; | |
65 | ||
66 | /* flags */ | |
67 | #define RS_0OPEN 0x01 /* drive 0 open -- must be first */ | |
68 | #define RS_1OPEN 0x02 /* drive 1 open -- must be second */ | |
69 | #define RS_BUSY 0x04 /* operation in progress */ | |
70 | #define RS_WANT 0x08 /* wakeup when done */ | |
71 | #define RS_DONE 0x20 /* I/O operation done */ | |
72 | #define RS_ERROR 0x40 /* error bit set at interrupt */ | |
73 | ||
74 | /* | |
75 | * Open a console RX50. | |
76 | */ | |
77 | /*ARGSUSED*/ | |
78 | rx50open(dev, flags) | |
79 | dev_t dev; | |
80 | int flags; | |
81 | { | |
82 | int unit; | |
83 | ||
84 | /* only on 8200 (yet) */ | |
85 | if (cpu != VAX_8200 || (unit = rx50unit(dev)) >= 2) | |
86 | return (ENXIO); | |
87 | ||
88 | /* enforce exclusive access */ | |
89 | if (rx50state.rs_flags & (1 << unit)) | |
90 | return (EBUSY); | |
91 | rx50state.rs_flags |= 1 << unit; | |
92 | return (0); | |
93 | } | |
94 | ||
95 | /* | |
96 | * Close a console RX50. | |
97 | */ | |
98 | /*ARGSUSED*/ | |
99 | rx50close(dev, flags) | |
100 | dev_t dev; | |
101 | int flags; | |
102 | { | |
103 | ||
104 | rx50state.rs_flags &= ~(1 << dev); /* atomic */ | |
105 | } | |
106 | ||
107 | /* | |
3299817a | 108 | * Perform a read (uio->uio_rw==UIO_READ) or write (uio->uio_rw==UIO_WRITE). |
d6489fd6 | 109 | */ |
c8c58db5 | 110 | rx50rw(dev, uio, flags) |
d6489fd6 | 111 | dev_t dev; |
d6489fd6 | 112 | register struct uio *uio; |
3299817a | 113 | int flags; |
d6489fd6 MK |
114 | { |
115 | register struct rx50device *rxaddr; | |
116 | register struct rx50state *rs; | |
117 | register char *cp; | |
118 | register int error, i, t; | |
119 | char secbuf[512]; | |
120 | static char driveselect[2] = { RXCMD_DRIVE0, RXCMD_DRIVE1 }; | |
121 | ||
122 | /* enforce whole-sector I/O */ | |
123 | if ((uio->uio_offset & 511) || (uio->uio_resid & 511)) | |
124 | return (EINVAL); | |
125 | ||
126 | rs = &rx50state; | |
127 | ||
128 | /* lock out others */ | |
129 | i = spl4(); | |
130 | while (rs->rs_flags & RS_BUSY) { | |
131 | rs->rs_flags |= RS_WANT; | |
132 | sleep((caddr_t) &rx50state, PZERO - 1); | |
133 | } | |
134 | rs->rs_flags |= RS_BUSY; | |
135 | rs->rs_drive = rx50unit(dev); | |
136 | splx(i); | |
137 | ||
138 | rxaddr = &rx50device; | |
139 | error = 0; | |
140 | ||
141 | while (uio->uio_resid) { | |
142 | rs->rs_blkno = uio->uio_offset >> 9; | |
143 | if (rs->rs_blkno >= RX50MAXSEC) { | |
144 | if (rs->rs_blkno > RX50MAXSEC) | |
145 | error = EINVAL; | |
3299817a | 146 | else if (uio->uio_rw == UIO_WRITE) |
d6489fd6 MK |
147 | error = ENOSPC; |
148 | /* else ``eof'' */ | |
149 | break; | |
150 | } | |
151 | rs->rs_flags &= ~(RS_ERROR | RS_DONE); | |
3299817a | 152 | if (uio->uio_rw == UIO_WRITE) { |
d6489fd6 | 153 | /* copy the data to the RX50 silo */ |
3299817a | 154 | error = uiomove(secbuf, 512, uio); |
d6489fd6 MK |
155 | if (error) |
156 | break; | |
157 | i = rxaddr->rxrda; | |
158 | for (cp = secbuf, i = 512; --i >= 0;) | |
159 | rxaddr->rxfdb = *cp++; | |
160 | i = RXCMD_WRITE; | |
161 | } else | |
162 | i = RXCMD_READ; | |
163 | rxaddr->rxcmd = i | driveselect[rs->rs_drive]; | |
164 | i = rs->rs_blkno - ((t = rs->rs_blkno / RX50SEC) * RX50SEC); | |
165 | rxaddr->rxtrk = t == 79 ? 0 : t + 1; | |
166 | #ifdef notdef | |
167 | rxaddr->rxsec = "\1\3\5\7\11\1\3\5\7"[(2*t + i) % 5] + (i > 4); | |
168 | #else | |
169 | rxaddr->rxsec = RX50SKEW(i, t); | |
170 | #endif | |
171 | i = rxaddr->rxgo; /* start it up */ | |
172 | i = spl4(); | |
173 | while ((rs->rs_flags & RS_DONE) == 0) | |
174 | sleep((caddr_t) &rs->rs_blkno, PRIBIO); | |
175 | splx(i); | |
176 | if (rs->rs_flags & RS_ERROR) { | |
177 | error = EIO; | |
178 | break; | |
179 | } | |
3299817a | 180 | if (uio->uio_rw == UIO_READ) { |
d6489fd6 MK |
181 | /* copy the data out of the silo */ |
182 | i = rxaddr->rxrda; | |
183 | for (cp = secbuf, i = 512; --i >= 0;) | |
184 | *cp++ = rxaddr->rxedb; | |
3299817a | 185 | error = uiomove(secbuf, 512, uio); |
d6489fd6 MK |
186 | if (error) |
187 | break; | |
188 | } | |
189 | } | |
190 | ||
191 | /* let others in */ | |
192 | rs->rs_flags &= ~RS_BUSY; | |
193 | if (rs->rs_flags & RS_WANT) | |
194 | wakeup((caddr_t) rs); | |
195 | ||
196 | return (error); | |
197 | } | |
198 | ||
d6489fd6 MK |
199 | rx50intr() |
200 | { | |
201 | register struct rx50device *rxaddr = &rx50device; | |
202 | register struct rx50state *rs = &rx50state; | |
203 | int i; | |
204 | ||
205 | #ifdef lint | |
206 | i = 0; i = i; | |
207 | #endif | |
208 | ||
209 | /* ignore spurious interrupts */ | |
210 | if ((rxaddr->rxcmd & RXCMD_DONE) == 0) | |
211 | return; | |
212 | if ((rs->rs_flags & RS_BUSY) == 0) { | |
213 | printf("stray rx50 interrupt ignored\n"); | |
214 | return; | |
215 | } | |
216 | if (rxaddr->rxcmd & RXCMD_ERROR) { | |
217 | printf( | |
218 | "csa%d: hard error sn%d: cmd=%x trk=%x sec=%x csc=%x ict=%x ext=%x\n", | |
219 | rs->rs_drive + 1, rs->rs_blkno, | |
220 | rxaddr->rxcmd, rxaddr->rxtrk, rxaddr->rxsec, | |
221 | rxaddr->rxcsc, rxaddr->rxict, rxaddr->rxext); | |
222 | rxaddr->rxcmd = RXCMD_RESET; | |
223 | i = rxaddr->rxgo; | |
224 | rs->rs_flags |= RS_ERROR; | |
225 | } | |
226 | rs->rs_flags |= RS_DONE; | |
227 | wakeup((caddr_t) &rs->rs_blkno); | |
228 | } | |
229 | #endif |