isp_netbsd.c revision 1.5.2.2 1 1.5.2.2 cgd /* $NetBSD: isp_netbsd.c,v 1.5.2.2 1998/11/07 05:50:35 cgd Exp $ */
2 1.5.2.2 cgd /*
3 1.5.2.2 cgd * Platform (NetBSD) dependent common attachment code for Qlogic adapters.
4 1.5.2.2 cgd *
5 1.5.2.2 cgd *---------------------------------------
6 1.5.2.2 cgd * Copyright (c) 1997, 1998 by Matthew Jacob
7 1.5.2.2 cgd * NASA/Ames Research Center
8 1.5.2.2 cgd * All rights reserved.
9 1.5.2.2 cgd *---------------------------------------
10 1.5.2.2 cgd *
11 1.5.2.2 cgd * Redistribution and use in source and binary forms, with or without
12 1.5.2.2 cgd * modification, are permitted provided that the following conditions
13 1.5.2.2 cgd * are met:
14 1.5.2.2 cgd * 1. Redistributions of source code must retain the above copyright
15 1.5.2.2 cgd * notice immediately at the beginning of the file, without modification,
16 1.5.2.2 cgd * this list of conditions, and the following disclaimer.
17 1.5.2.2 cgd * 2. Redistributions in binary form must reproduce the above copyright
18 1.5.2.2 cgd * notice, this list of conditions and the following disclaimer in the
19 1.5.2.2 cgd * documentation and/or other materials provided with the distribution.
20 1.5.2.2 cgd * 3. The name of the author may not be used to endorse or promote products
21 1.5.2.2 cgd * derived from this software without specific prior written permission.
22 1.5.2.2 cgd *
23 1.5.2.2 cgd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 1.5.2.2 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.5.2.2 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.5.2.2 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
27 1.5.2.2 cgd * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.5.2.2 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.5.2.2 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.5.2.2 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.5.2.2 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.5.2.2 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.5.2.2 cgd * SUCH DAMAGE.
34 1.5.2.2 cgd *
35 1.5.2.2 cgd * The author may be reached via electronic communications at
36 1.5.2.2 cgd *
37 1.5.2.2 cgd * mjacob (at) nas.nasa.gov
38 1.5.2.2 cgd * mjacob (at) feral.com
39 1.5.2.2 cgd *
40 1.5.2.2 cgd * or, via United States Postal Address
41 1.5.2.2 cgd *
42 1.5.2.2 cgd * Matthew Jacob
43 1.5.2.2 cgd * Feral Software
44 1.5.2.2 cgd * 2339 3rd Street
45 1.5.2.2 cgd * Suite 24
46 1.5.2.2 cgd * San Francisco, CA, 94107
47 1.5.2.2 cgd */
48 1.5.2.2 cgd
49 1.5.2.2 cgd #include <dev/ic/isp_netbsd.h>
50 1.5.2.2 cgd
51 1.5.2.2 cgd struct cfdriver isp_cd = {
52 1.5.2.2 cgd NULL, "isp", DV_DULL
53 1.5.2.2 cgd };
54 1.5.2.2 cgd
55 1.5.2.2 cgd static void ispminphys __P((struct buf *));
56 1.5.2.2 cgd static int32_t ispcmd __P((ISP_SCSI_XFER_T *));
57 1.5.2.2 cgd
58 1.5.2.2 cgd static struct scsipi_adapter isp_switch = {
59 1.5.2.2 cgd ispcmd, /* scsipi_cmd */
60 1.5.2.2 cgd ispminphys, /* scsipi_minphys */
61 1.5.2.2 cgd NULL, /* scsipi_ioctl */
62 1.5.2.2 cgd };
63 1.5.2.2 cgd
64 1.5.2.2 cgd static struct scsipi_device isp_dev = { NULL, NULL, NULL, NULL };
65 1.5.2.2 cgd static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int));
66 1.5.2.2 cgd
67 1.5.2.2 cgd /*
68 1.5.2.2 cgd * Complete attachment of hardware, include subdevices.
69 1.5.2.2 cgd */
70 1.5.2.2 cgd void
71 1.5.2.2 cgd isp_attach(isp)
72 1.5.2.2 cgd struct ispsoftc *isp;
73 1.5.2.2 cgd {
74 1.5.2.2 cgd isp->isp_state = ISP_RUNSTATE;
75 1.5.2.2 cgd isp->isp_osinfo._link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
76 1.5.2.2 cgd isp->isp_osinfo._link.adapter_softc = isp;
77 1.5.2.2 cgd isp->isp_osinfo._link.device = &isp_dev;
78 1.5.2.2 cgd isp->isp_osinfo._link.adapter = &isp_switch;
79 1.5.2.2 cgd
80 1.5.2.2 cgd if (isp->isp_type & ISP_HA_FC) {
81 1.5.2.2 cgd isp->isp_osinfo._link.scsipi_scsi.max_target = MAX_FC_TARG-1;
82 1.5.2.2 cgd isp->isp_osinfo._link.openings =
83 1.5.2.2 cgd RQUEST_QUEUE_LEN / (MAX_FC_TARG-1);
84 1.5.2.2 cgd isp->isp_osinfo._link.scsipi_scsi.adapter_target = 0xff;
85 1.5.2.2 cgd } else {
86 1.5.2.2 cgd isp->isp_osinfo._link.openings =
87 1.5.2.2 cgd RQUEST_QUEUE_LEN / (MAX_TARGETS-1);
88 1.5.2.2 cgd isp->isp_osinfo._link.scsipi_scsi.max_target = MAX_TARGETS-1;
89 1.5.2.2 cgd isp->isp_osinfo._link.scsipi_scsi.adapter_target =
90 1.5.2.2 cgd ((sdparam *)isp->isp_param)->isp_initiator_id;
91 1.5.2.2 cgd }
92 1.5.2.2 cgd if (isp->isp_osinfo._link.openings < 2)
93 1.5.2.2 cgd isp->isp_osinfo._link.openings = 2;
94 1.5.2.2 cgd isp->isp_osinfo._link.type = BUS_SCSI;
95 1.5.2.2 cgd config_found((void *)isp, &isp->isp_osinfo._link, scsiprint);
96 1.5.2.2 cgd }
97 1.5.2.2 cgd
98 1.5.2.2 cgd /*
99 1.5.2.2 cgd * minphys our xfers
100 1.5.2.2 cgd *
101 1.5.2.2 cgd * Unfortunately, the buffer pointer describes the target device- not the
102 1.5.2.2 cgd * adapter device, so we can't use the pointer to find out what kind of
103 1.5.2.2 cgd * adapter we are and adjust accordingly.
104 1.5.2.2 cgd */
105 1.5.2.2 cgd
106 1.5.2.2 cgd static void
107 1.5.2.2 cgd ispminphys(bp)
108 1.5.2.2 cgd struct buf *bp;
109 1.5.2.2 cgd {
110 1.5.2.2 cgd /*
111 1.5.2.2 cgd * XX: Only the 1020 has a 24 bit limit.
112 1.5.2.2 cgd */
113 1.5.2.2 cgd if (bp->b_bcount >= (1 << 24)) {
114 1.5.2.2 cgd bp->b_bcount = (1 << 24);
115 1.5.2.2 cgd }
116 1.5.2.2 cgd minphys(bp);
117 1.5.2.2 cgd }
118 1.5.2.2 cgd
119 1.5.2.2 cgd static int
120 1.5.2.2 cgd ispcmd(xs)
121 1.5.2.2 cgd ISP_SCSI_XFER_T *xs;
122 1.5.2.2 cgd {
123 1.5.2.2 cgd struct ispsoftc *isp;
124 1.5.2.2 cgd int result;
125 1.5.2.2 cgd ISP_LOCKVAL_DECL;
126 1.5.2.2 cgd
127 1.5.2.2 cgd isp = XS_ISP(xs);
128 1.5.2.2 cgd ISP_LOCK(isp);
129 1.5.2.2 cgd /*
130 1.5.2.2 cgd * This is less efficient than I would like in that the
131 1.5.2.2 cgd * majority of cases will have to do some pointer deferences
132 1.5.2.2 cgd * to find out that things don't need to be updated.
133 1.5.2.2 cgd */
134 1.5.2.2 cgd if ((xs->flags & SCSI_AUTOCONF) == 0 && (isp->isp_type & ISP_HA_SCSI)) {
135 1.5.2.2 cgd sdparam *sdp = isp->isp_param;
136 1.5.2.2 cgd if (sdp->isp_devparam[XS_TGT(xs)].dev_flags !=
137 1.5.2.2 cgd sdp->isp_devparam[XS_TGT(xs)].cur_dflags) {
138 1.5.2.2 cgd u_int16_t f = DPARM_WIDE|DPARM_SYNC|DPARM_TQING;
139 1.5.2.2 cgd #ifdef SDEV_NOSYNC
140 1.5.2.2 cgd if (xs->sc_link->quirks & SDEV_NOSYNC)
141 1.5.2.2 cgd f &= ~DPARM_SYNC;
142 1.5.2.2 cgd #endif
143 1.5.2.2 cgd #ifdef SDEV_NOWIDE
144 1.5.2.2 cgd if (xs->sc_link->quirks & SDEV_NOWIDE)
145 1.5.2.2 cgd f &= ~DPARM_WIDE;
146 1.5.2.2 cgd #endif
147 1.5.2.2 cgd #ifdef SDEV_NOTAG
148 1.5.2.2 cgd if (xs->sc_link->quirks & SDEV_NOTAG)
149 1.5.2.2 cgd f &= ~DPARM_TQING;
150 1.5.2.2 cgd #endif
151 1.5.2.2 cgd sdp->isp_devparam[XS_TGT(xs)].dev_flags &=
152 1.5.2.2 cgd ~(DPARM_WIDE|DPARM_SYNC|DPARM_TQING);
153 1.5.2.2 cgd sdp->isp_devparam[XS_TGT(xs)].dev_flags |= f;
154 1.5.2.2 cgd sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
155 1.5.2.2 cgd isp->isp_update = 1;
156 1.5.2.2 cgd }
157 1.5.2.2 cgd }
158 1.5.2.2 cgd result = ispscsicmd(xs);
159 1.5.2.2 cgd if (result != CMD_QUEUED || (xs->flags & SCSI_POLL) == 0) {
160 1.5.2.2 cgd ISP_UNLOCK(isp);
161 1.5.2.2 cgd return (result);
162 1.5.2.2 cgd }
163 1.5.2.2 cgd
164 1.5.2.2 cgd /*
165 1.5.2.2 cgd * If we can't use interrupts, poll on completion.
166 1.5.2.2 cgd */
167 1.5.2.2 cgd if (isp_poll(isp, xs, XS_TIME(xs))) {
168 1.5.2.2 cgd /*
169 1.5.2.2 cgd * If no other error occurred but we didn't finish,
170 1.5.2.2 cgd * something bad happened.
171 1.5.2.2 cgd */
172 1.5.2.2 cgd if (XS_IS_CMD_DONE(xs) == 0) {
173 1.5.2.2 cgd isp->isp_nactive--;
174 1.5.2.2 cgd if (isp->isp_nactive < 0)
175 1.5.2.2 cgd isp->isp_nactive = 0;
176 1.5.2.2 cgd if (XS_NOERR(xs)) {
177 1.5.2.2 cgd isp_lostcmd(isp, xs);
178 1.5.2.2 cgd XS_SETERR(xs, HBA_BOTCH);
179 1.5.2.2 cgd }
180 1.5.2.2 cgd }
181 1.5.2.2 cgd }
182 1.5.2.2 cgd ISP_UNLOCK(isp);
183 1.5.2.2 cgd return (CMD_COMPLETE);
184 1.5.2.2 cgd }
185 1.5.2.2 cgd
186 1.5.2.2 cgd static int
187 1.5.2.2 cgd isp_poll(isp, xs, mswait)
188 1.5.2.2 cgd struct ispsoftc *isp;
189 1.5.2.2 cgd ISP_SCSI_XFER_T *xs;
190 1.5.2.2 cgd int mswait;
191 1.5.2.2 cgd {
192 1.5.2.2 cgd
193 1.5.2.2 cgd while (mswait) {
194 1.5.2.2 cgd /* Try the interrupt handling routine */
195 1.5.2.2 cgd (void)isp_intr((void *)isp);
196 1.5.2.2 cgd
197 1.5.2.2 cgd /* See if the xs is now done */
198 1.5.2.2 cgd if (XS_IS_CMD_DONE(xs)) {
199 1.5.2.2 cgd return (0);
200 1.5.2.2 cgd }
201 1.5.2.2 cgd SYS_DELAY(1000); /* wait one millisecond */
202 1.5.2.2 cgd mswait--;
203 1.5.2.2 cgd }
204 1.5.2.2 cgd return (1);
205 1.5.2.2 cgd }
206