FreeBSD/Linux Kernel Cross Reference
sys/scsi/sctarg.c
1 /*
2 * sctarg: Target mode user interface
3 *
4 * Copyright (C) 1995, HD Associates, Inc.
5 * PO Box 276
6 * Pepperell, MA 01463
7 * 508 433 5266
8 * dufault@hda.com
9 *
10 * This code is contributed to the University of California at Berkeley:
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * $FreeBSD: src/sys/scsi/sctarg.c,v 1.17.2.2 1999/09/05 08:21:48 peter Exp $
41 */
42
43 #include "opt_bounce.h"
44 #include "opt_scsi.h"
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/buf.h>
49 #include <sys/proc.h>
50 #include <sys/conf.h>
51 #include <sys/kernel.h>
52 #ifdef DEVFS
53 #include <sys/devfsext.h>
54 #endif /*DEVFS*/
55 #include <scsi/scsi_all.h>
56 #include <scsi/scsiconf.h>
57
58
59 #define OPEN 0x01
60
61 struct scsi_data {
62 struct buf_queue_head buf_queue;
63 int flags; /* Already open */
64 };
65
66 static d_open_t sctargopen;
67 static d_close_t sctargclose;
68 static d_ioctl_t sctargioctl;
69 static d_strategy_t sctargstrategy;
70
71 #define CDEV_MAJOR 65
72 static struct cdevsw sctarg_cdevsw =
73 { sctargopen, sctargclose, rawread, rawwrite, /*65*/
74 sctargioctl, nostop, nullreset, nodevtotty,/* sctarg */
75 seltrue, nommap, sctargstrategy, "sctarg", NULL, -1 };
76
77 SCSI_DEVICE_ENTRIES(sctarg)
78
79 static errval sctarg_open(dev_t dev, int flags, int fmt, struct proc *p,
80 struct scsi_link *sc_link);
81 static void sctargstart(u_int32_t unit, u_int32_t unused_flags);
82 static void sctarg_strategy(struct buf *bp, struct scsi_link *sc_link);
83
84 static struct scsi_device sctarg_switch =
85 {
86 NULL,
87 sctargstart, /* we have a queue, and this is how we service it */
88 NULL,
89 NULL,
90 "sctarg",
91 0,
92 {0, 0},
93 SDEV_ONCE_ONLY,
94 sctargattach,
95 "Processor Target",
96 sctargopen,
97 sizeof(struct scsi_data),
98 T_TARGET,
99 0,
100 0,
101 sctarg_open,
102 0,
103 0,
104 sctarg_strategy,
105 };
106
107 static errval
108 sctargattach(struct scsi_link *sc_link)
109 {
110 struct scsi_data *sctarg;
111
112 sctarg = sc_link->sd;
113 bufq_init(&sctarg->buf_queue);
114 sctarg->flags = 0;
115 return 0;
116 }
117
118 static errval
119 sctarg_open(dev_t dev, int flags, int fmt, struct proc *p,
120 struct scsi_link *sc_link)
121 {
122 int ret = 0;
123
124 /* Does this host adapter support target mode operation?
125 */
126 if ((sc_link->flags & SDEV_TARGET_OPS) == 0)
127 return ENODEV; /* Operation not supported */
128
129 if (SCSI_FIXED(dev)) {
130 sc_link->scsibus = SCSI_BUS(dev);
131 scsi_set_bus(sc_link->scsibus, sc_link);
132
133 sc_link->target = SCSI_ID(dev);
134 sc_link->lun = SCSI_LUN(dev);
135 }
136
137 if (sc_link->scsibus == SCCONF_UNSPEC ||
138 sc_link->target == SCCONF_UNSPEC ||
139 sc_link->lun == SCCONF_UNSPEC)
140 return ENXIO;
141
142 /* XXX: You can have more than one target device on a single
143 * host adapter. We need a reference count.
144 */
145 if ((sc_link->sd->flags & OPEN) == 0) /* Enable target mode */
146 {
147 ret = scsi_target_mode(sc_link, 1);
148 sc_link->sd->flags |= OPEN;
149 }
150
151 return ret;
152 }
153
154 /*
155 * sctargstart looks to see if there is a buf waiting for the device
156 * and that the device is not already busy. If both are true,
157 * It dequeues the buf and creates a scsi command to perform the
158 * transfer required. The transfer request will call scsi_done
159 * on completion, which will in turn call this routine again
160 * so that the next queued transfer is performed.
161 * The bufs are queued by the strategy routine (sctargstrategy)
162 *
163 * This routine is also called after other non-queued requests
164 * have been made of the scsi driver, to ensure that the queue
165 * continues to be drained.
166 * sctargstart() is called at splbio
167 */
168 static void
169 sctargstart(unit, unused_flags)
170 u_int32_t unit;
171 u_int32_t unused_flags;
172 {
173 struct scsi_link *sc_link = SCSI_LINK(&sctarg_switch, unit);
174 struct scsi_data *sctarg = sc_link->sd;
175 register struct buf *bp = 0;
176 struct
177 {
178 #define PROCESSOR_SEND 0x0A
179 #define PROCESSOR_RECEIVE 0x08
180 u_char op_code;
181 u_char byte2;
182 u_char len[3];
183 u_char control;
184 } cmd;
185
186 u_int32_t flags;
187
188 SC_DEBUG(sc_link, SDEV_DB2, ("sctargstart "));
189 /*
190 * See if there is a buf to do and we are not already
191 * doing one
192 */
193 while (sc_link->opennings != 0) {
194
195 /* if a special awaits, let it proceed first */
196 if (sc_link->flags & SDEV_WAITING) {
197 sc_link->flags &= ~SDEV_WAITING;
198 wakeup((caddr_t)sc_link);
199 return;
200 }
201
202 bp = bufq_first(&sctarg->buf_queue);
203 if (bp == NULL)
204 return;
205 bufq_remove(&sctarg->buf_queue, bp);
206
207 /*
208 * Fill out the scsi command
209 */
210 bzero(&cmd, sizeof(cmd));
211 flags = SCSI_TARGET;
212 if ((bp->b_flags & B_READ) == B_WRITE) {
213 cmd.op_code = PROCESSOR_SEND;
214 flags |= SCSI_DATA_OUT;
215 } else {
216 cmd.op_code = PROCESSOR_RECEIVE;
217 flags |= SCSI_DATA_IN;
218 }
219
220 scsi_uto3b(bp->b_bcount, cmd.len);
221 /*
222 * go ask the adapter to do all this for us
223 */
224 if (scsi_scsi_cmd(sc_link,
225 (struct scsi_generic *) &cmd,
226 sizeof(cmd),
227 (u_char *) bp->b_un.b_addr,
228 bp->b_bcount,
229 0,
230 100000,
231 bp,
232 flags | SCSI_NOSLEEP) == SUCCESSFULLY_QUEUED) {
233 } else {
234 printf("sctarg%ld: oops not queued\n", unit);
235 bp->b_flags |= B_ERROR;
236 bp->b_error = EIO;
237 biodone(bp);
238 }
239 } /* go back and see if we can cram more work in.. */
240 }
241
242 static void
243 sctarg_strategy(struct buf *bp, struct scsi_link *sc_link)
244 {
245 unsigned char unit;
246 u_int32_t opri;
247 struct scsi_data *sctarg;
248
249 unit = minor((bp->b_dev));
250 sctarg = sc_link->sd;
251
252 opri = splbio();
253
254 /*
255 * Use a bounce buffer if necessary
256 */
257 #ifdef BOUNCE_BUFFERS
258 if (sc_link->flags & SDEV_BOUNCE)
259 vm_bounce_alloc(bp);
260 #endif
261
262 /*
263 * Place it at the end of the queue of activities for this device.
264 */
265 bufq_insert_tail(&sctarg->buf_queue, bp);
266
267 /*
268 * Tell the device to get going on the transfer if it's
269 * not doing anything, otherwise just wait for completion
270 * (All a bit silly if we're only allowing 1 open but..)
271 */
272 sctargstart(unit, 0);
273
274 splx(opri);
275 return;
276 }
277
278 static sctarg_devsw_installed = 0;
279 #ifdef DEVFS
280 static void *sctarg_devfs_token;
281 #endif
282
283 static void sctarg_drvinit(void *unused)
284 {
285 dev_t dev;
286
287 if( ! sctarg_devsw_installed ) {
288 dev = makedev(CDEV_MAJOR, 0);
289 cdevsw_add(&dev,&sctarg_cdevsw, NULL);
290 sctarg_devsw_installed = 1;
291 #ifdef DEVFS
292 /* XXX should be in ADAPTER code */
293 sctarg_devfs_token =
294 devfs_add_devswf(&sctarg_cdevsw, 0, DV_CHR, 0, 0,
295 0600, "sctarg");
296 #endif
297 }
298 }
299
300 SYSINIT(sctargdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,sctarg_drvinit,NULL)
301
302
Cache object: 445c8f4d40df7cd2f8adc071448f2a7b
|