Deleted Added
sdiff udiff text old ( 35210 ) new ( 38061 )
full compact
1/*-
2 * Copyright (c) 1997, 1998 Nicolas Souchu
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 28 unchanged lines hidden (view full) ---

39#include <scsi/scsi_disk.h>
40#include <scsi/scsiconf.h>
41
42#ifdef KERNEL
43#include <sys/kernel.h>
44#endif /*KERNEL */
45
46#include <dev/ppbus/ppbconf.h>
47#include <dev/ppbus/vpoio.h>
48
49#define VP0_BUFFER_SIZE 0x12000
50
51struct vpo_sense {
52 struct scsi_sense cmd;
53 unsigned int stat;
54 unsigned int count;
55};
56
57struct vpo_data {
58 unsigned short vpo_unit;
59
60 int vpo_stat;
61 int vpo_count;
62 int vpo_error;
63
64 struct ppb_status vpo_status;
65 struct vpo_sense vpo_sense;
66
67 unsigned char vpo_buffer[VP0_BUFFER_SIZE];
68
69 struct vpoio_data vpo_io; /* interface to low level functions */
70
71 struct scsi_link sc_link;
72};
73
74
75static int32_t vpo_scsi_cmd(struct scsi_xfer *);
76static void vpominphys(struct buf *);
77static u_int32_t vpo_adapter_info(int);
78
79static int nvpo = 0;
80#define MAXVP0 8 /* XXX not much better! */
81static struct vpo_data *vpodata[MAXVP0];
82
83static struct scsi_adapter vpo_switch =
84{
85 vpo_scsi_cmd,
86 vpominphys,
87 0,
88 0,
89 vpo_adapter_info,
90 "vpo",

--- 24 unchanged lines hidden (view full) ---

115static int vpoattach(struct ppb_device *dev);
116
117static struct ppb_driver vpodriver = {
118 vpoprobe, vpoattach, "vpo"
119};
120DATA_SET(ppbdriver_set, vpodriver);
121
122
123static u_int32_t
124vpo_adapter_info(int unit)
125{
126
127 return 1;
128}
129
130/*
131 * vpoprobe()
132 *
133 * Called by ppb_attachdevs().
134 */
135static struct ppb_device *
136vpoprobe(struct ppb_data *ppb)
137{
138 struct vpo_data *vpo;
139 struct ppb_device *dev;
140
141 if (nvpo >= MAXVP0) {
142 printf("vpo: Too many devices (max %d)\n", MAXVP0);
143 return(NULL);
144 }
145
146 vpo = (struct vpo_data *)malloc(sizeof(struct vpo_data),
147 M_DEVBUF, M_NOWAIT);
148 if (!vpo) {
149 printf("vpo: cannot malloc!\n");
150 return(NULL);
151 }
152 bzero(vpo, sizeof(struct vpo_data));
153
154 vpodata[nvpo] = vpo;
155
156 /* vpo dependent initialisation */
157 vpo->vpo_unit = nvpo;
158
159 /* ok, go to next device on next probe */
160 nvpo ++;
161
162 /* low level probe */
163 vpoio_set_unit(&vpo->vpo_io, vpo->vpo_unit);
164
165 if (!(dev = vpoio_probe(ppb, &vpo->vpo_io))) {
166 free(vpo, M_DEVBUF);
167 return (NULL);
168 }
169
170 return (dev);
171}
172
173/*
174 * vpoattach()
175 *
176 * Called by ppb_attachdevs().
177 */
178static int
179vpoattach(struct ppb_device *dev)
180{
181
182 struct scsibus_data *scbus;
183 struct vpo_data *vpo = vpodata[dev->id_unit];
184
185 /* low level attachment */
186 if (!vpoio_attach(&vpo->vpo_io))
187 return (0);
188
189 vpo->sc_link.adapter_unit = vpo->vpo_unit;
190 vpo->sc_link.adapter_targ = VP0_INITIATOR;
191 vpo->sc_link.adapter = &vpo_switch;
192 vpo->sc_link.device = &vpo_dev;
193 vpo->sc_link.opennings = VP0_OPENNINGS;
194
195 /*
196 * Prepare the scsibus_data area for the upperlevel
197 * scsi code.
198 */
199 scbus = scsi_alloc_bus();
200 if(!scbus)
201 return (0);
202 scbus->adapter_link = &vpo->sc_link;
203
204 /* all went ok */
205 printf("vpo%d: <Iomega PPA-3/VPI0 SCSI controller>\n", dev->id_unit);
206
207 scsi_attachdevs(scbus);
208
209 return (1);
210}
211
212static void
213vpominphys(struct buf *bp)
214{
215
216 if (bp->b_bcount > VP0_BUFFER_SIZE)
217 bp->b_bcount = VP0_BUFFER_SIZE;
218
219 return;
220}
221
222/*
223 * vpo_intr()
224 */
225static void
226vpo_intr(struct vpo_data *vpo, struct scsi_xfer *xs)
227{
228
229 int errno; /* error in errno.h */
230
231 if (xs->datalen && !(xs->flags & SCSI_DATA_IN))
232 bcopy(xs->data, vpo->vpo_buffer, xs->datalen);
233
234 errno = vpoio_do_scsi(&vpo->vpo_io, VP0_INITIATOR,
235 xs->sc_link->target, (char *)xs->cmd, xs->cmdlen,
236 vpo->vpo_buffer, xs->datalen, &vpo->vpo_stat, &vpo->vpo_count,
237 &vpo->vpo_error);
238
239#ifdef VP0_DEBUG
240 printf("vpo_do_scsi = %d, status = 0x%x, count = %d, vpo_error = %d\n",
241 errno, vpo->vpo_stat, vpo->vpo_count, vpo->vpo_error);
242#endif
243
244 if (errno) {
245#ifdef VP0_WARNING
246 log(LOG_WARNING, "vpo%d: errno = %d\n", vpo->vpo_unit, errno);
247#endif
248 /* connection to ppbus interrupted */
249 xs->error = XS_DRIVER_STUFFUP;
250 goto error;
251 }
252
253 /* if a timeout occured, no sense */
254 if (vpo->vpo_error) {
255 xs->error = XS_TIMEOUT;
256 goto error;
257 }
258
259#define RESERVED_BITS_MASK 0x3e /* 00111110b */
260#define NO_SENSE 0x0
261#define CHECK_CONDITION 0x02
262
263 switch (vpo->vpo_stat & RESERVED_BITS_MASK) {
264 case NO_SENSE:
265 break;
266
267 case CHECK_CONDITION:
268 vpo->vpo_sense.cmd.op_code = REQUEST_SENSE;
269 vpo->vpo_sense.cmd.length = sizeof(xs->sense);
270 vpo->vpo_sense.cmd.control = 0;
271
272 errno = vpoio_do_scsi(&vpo->vpo_io, VP0_INITIATOR,
273 xs->sc_link->target, (char *)&vpo->vpo_sense.cmd,
274 sizeof(vpo->vpo_sense.cmd),
275 (char *)&xs->sense, sizeof(xs->sense),
276 &vpo->vpo_sense.stat, &vpo->vpo_sense.count,
277 &vpo->vpo_error);
278
279 if (errno)
280 /* connection to ppbus interrupted */
281 xs->error = XS_DRIVER_STUFFUP;
282 else
283 xs->error = XS_SENSE;
284
285 goto error;

--- 37 unchanged lines hidden (view full) ---

323#ifdef VP0_DEBUG
324 printf("vpo_scsi_cmd(): xs->flags = 0x%x, "\
325 "xs->data = 0x%x, xs->datalen = %d\ncommand : %*D\n",
326 xs->flags, xs->data, xs->datalen,
327 xs->cmdlen, xs->cmd, " " );
328#endif
329
330 if (xs->flags & SCSI_NOMASK) {
331 vpo_intr(vpodata[xs->sc_link->adapter_unit], xs);
332 return COMPLETE;
333 }
334
335 s = splbio();
336
337 vpo_intr(vpodata[xs->sc_link->adapter_unit], xs);
338
339 splx(s);
340 return SUCCESSFULLY_QUEUED;
341}