Deleted Added
full compact
aha.c (39852) aha.c (39881)
1/*
2 * Generic register and struct definitions for the Adaptech 154x/164x
3 * SCSI host adapters. Product specific probe and attach routines can
4 * be found in:
5 * aha 1540/1542B/1542C/1542CF/1542CP aha_isa.c
6 *
7 * Copyright (c) 1998 M. Warner Losh.
8 * All Rights Reserved.
9 *
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification, immediately at the beginning of the file.
17 * 2. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * Derived from bt.c written by:
33 *
34 * Copyright (c) 1998 Justin T. Gibbs.
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions, and the following disclaimer,
42 * without modification, immediately at the beginning of the file.
43 * 2. The name of the author may not be used to endorse or promote products
44 * derived from this software without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
50 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
1/*
2 * Generic register and struct definitions for the Adaptech 154x/164x
3 * SCSI host adapters. Product specific probe and attach routines can
4 * be found in:
5 * aha 1540/1542B/1542C/1542CF/1542CP aha_isa.c
6 *
7 * Copyright (c) 1998 M. Warner Losh.
8 * All Rights Reserved.
9 *
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification, immediately at the beginning of the file.
17 * 2. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * Derived from bt.c written by:
33 *
34 * Copyright (c) 1998 Justin T. Gibbs.
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions, and the following disclaimer,
42 * without modification, immediately at the beginning of the file.
43 * 2. The name of the author may not be used to endorse or promote products
44 * derived from this software without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
50 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
58 * $Id: aha.c,v 1.5 1998/09/30 00:10:44 imp Exp $
58 * $Id: aha.c,v 1.6 1998/10/01 04:53:55 imp Exp $
59 */
60
61#include <sys/param.h>
62#include <sys/systm.h>
63#include <sys/malloc.h>
64#include <sys/buf.h>
65#include <sys/kernel.h>
66#include <sys/sysctl.h>
67
68#include <machine/bus_pio.h>
69#include <machine/bus.h>
70#include <machine/clock.h>
71
72#include <cam/cam.h>
73#include <cam/cam_ccb.h>
74#include <cam/cam_sim.h>
75#include <cam/cam_xpt_sim.h>
76#include <cam/cam_debug.h>
77
78#include <cam/scsi/scsi_message.h>
79
80#include <vm/vm.h>
81#include <vm/pmap.h>
82
83#include <dev/aha/ahareg.h>
84
85struct aha_softc *aha_softcs[NAHA];
86
87#define MIN(a, b) ((a) < (b) ? (a) : (b))
59 */
60
61#include <sys/param.h>
62#include <sys/systm.h>
63#include <sys/malloc.h>
64#include <sys/buf.h>
65#include <sys/kernel.h>
66#include <sys/sysctl.h>
67
68#include <machine/bus_pio.h>
69#include <machine/bus.h>
70#include <machine/clock.h>
71
72#include <cam/cam.h>
73#include <cam/cam_ccb.h>
74#include <cam/cam_sim.h>
75#include <cam/cam_xpt_sim.h>
76#include <cam/cam_debug.h>
77
78#include <cam/scsi/scsi_message.h>
79
80#include <vm/vm.h>
81#include <vm/pmap.h>
82
83#include <dev/aha/ahareg.h>
84
85struct aha_softc *aha_softcs[NAHA];
86
87#define MIN(a, b) ((a) < (b) ? (a) : (b))
88#define PRVERBOSE(x) if (bootverbose) printf x
88#define PRVERB(x) if (bootverbose) printf x
89
90/* Macro to determine that a rev is potentially a new valid one
91 * so that the driver doesn't keep breaking on new revs as it
92 * did for the CF and CP.
93 */
94#define PROBABLY_NEW_BOARD(REV) (REV > 0x43 && REV < 0x56)
95
96/* MailBox Management functions */
97static __inline void ahanextinbox(struct aha_softc *aha);
98static __inline void ahanextoutbox(struct aha_softc *aha);
99
100static __inline void
101ahanextinbox(struct aha_softc *aha)
102{
103 if (aha->cur_inbox == aha->last_inbox)
104 aha->cur_inbox = aha->in_boxes;
105 else
106 aha->cur_inbox++;
107}
108
109static __inline void
110ahanextoutbox(struct aha_softc *aha)
111{
112 if (aha->cur_outbox == aha->last_outbox)
113 aha->cur_outbox = aha->out_boxes;
114 else
115 aha->cur_outbox++;
116}
117
118#define ahautoa24(u,s3) \
119 (s3)[0] = ((u) >> 16) & 0xff; \
120 (s3)[1] = ((u) >> 8) & 0xff; \
121 (s3)[2] = (u) & 0xff;
122
123#define aha_a24tou(s3) \
124 (((s3)[0] << 16) | ((s3)[1] << 8) | (s3)[2])
125
126/* CCB Mangement functions */
127static __inline u_int32_t ahaccbvtop(struct aha_softc *aha,
128 struct aha_ccb *bccb);
129static __inline struct aha_ccb* ahaccbptov(struct aha_softc *aha,
130 u_int32_t ccb_addr);
131
132static __inline u_int32_t
133ahaccbvtop(struct aha_softc *aha, struct aha_ccb *bccb)
134{
135 return (aha->aha_ccb_physbase
136 + (u_int32_t)((caddr_t)bccb - (caddr_t)aha->aha_ccb_array));
137}
138static __inline struct aha_ccb *
139ahaccbptov(struct aha_softc *aha, u_int32_t ccb_addr)
140{
141 return (aha->aha_ccb_array +
142 + ((struct aha_ccb*)ccb_addr-(struct aha_ccb*)aha->aha_ccb_physbase));
143}
144
145static struct aha_ccb* ahagetccb(struct aha_softc *aha);
146static __inline void ahafreeccb(struct aha_softc *aha, struct aha_ccb *bccb);
147static void ahaallocccbs(struct aha_softc *aha);
148static bus_dmamap_callback_t ahaexecuteccb;
149static void ahadone(struct aha_softc *aha, struct aha_ccb *bccb,
150 aha_mbi_comp_code_t comp_code);
151
152/* Host adapter command functions */
153static int ahareset(struct aha_softc* aha, int hard_reset);
154
155/* Initialization functions */
156static int ahainitmboxes(struct aha_softc *aha);
157static bus_dmamap_callback_t ahamapmboxes;
158static bus_dmamap_callback_t ahamapccbs;
159static bus_dmamap_callback_t ahamapsgs;
160
161/* Transfer Negotiation Functions */
162static void ahafetchtransinfo(struct aha_softc *aha,
163 struct ccb_trans_settings *cts);
164
165/* CAM SIM entry points */
166#define ccb_bccb_ptr spriv_ptr0
167#define ccb_aha_ptr spriv_ptr1
168static void ahaaction(struct cam_sim *sim, union ccb *ccb);
169static void ahapoll(struct cam_sim *sim);
170
171/* Our timeout handler */
172timeout_t ahatimeout;
173
174u_long aha_unit = 0;
175
176/*
177 * Do our own re-probe protection until a configuration
178 * manager can do it for us. This ensures that we don't
179 * reprobe a card already found by the EISA or PCI probes.
180 */
181struct aha_isa_port aha_isa_ports[] =
182{
183 { 0x330, 0 },
184 { 0x334, 0 },
185 { 0x230, 0 },
186 { 0x234, 0 },
187 { 0x130, 0 },
188 { 0x134, 0 }
189};
190
191/* Exported functions */
192struct aha_softc *
193aha_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh)
194{
195 struct aha_softc *aha;
196 int i;
197
198 if (unit != AHA_TEMP_UNIT) {
199 if (unit >= NAHA) {
200 printf("aha: unit number (%d) too high\n", unit);
201 return NULL;
202 }
203
204 /*
205 * Allocate a storage area for us
206 */
207 if (aha_softcs[unit]) {
208 printf("aha%d: memory already allocated\n", unit);
209 return NULL;
210 }
211 }
212
213 aha = malloc(sizeof(struct aha_softc), M_DEVBUF, M_NOWAIT);
214 if (!aha) {
215 printf("aha%d: cannot malloc!\n", unit);
216 return NULL;
217 }
218 bzero(aha, sizeof(struct aha_softc));
219 SLIST_INIT(&aha->free_aha_ccbs);
220 LIST_INIT(&aha->pending_ccbs);
221 SLIST_INIT(&aha->sg_maps);
222 aha->unit = unit;
223 aha->tag = tag;
224 aha->bsh = bsh;
225
226 if (aha->unit != AHA_TEMP_UNIT) {
227 aha_softcs[unit] = aha;
228 }
229 return (aha);
230}
231
232void
233aha_free(struct aha_softc *aha)
234{
235 switch (aha->init_level) {
236 default:
237 case 8:
238 {
239 struct sg_map_node *sg_map;
240
241 while ((sg_map = SLIST_FIRST(&aha->sg_maps))!= NULL) {
242 SLIST_REMOVE_HEAD(&aha->sg_maps, links);
243 bus_dmamap_unload(aha->sg_dmat,
244 sg_map->sg_dmamap);
245 bus_dmamem_free(aha->sg_dmat, sg_map->sg_vaddr,
246 sg_map->sg_dmamap);
247 free(sg_map, M_DEVBUF);
248 }
249 bus_dma_tag_destroy(aha->sg_dmat);
250 }
251 case 7:
252 bus_dmamap_unload(aha->ccb_dmat, aha->ccb_dmamap);
253 case 6:
254 bus_dmamap_destroy(aha->ccb_dmat, aha->ccb_dmamap);
255 bus_dmamem_free(aha->ccb_dmat, aha->aha_ccb_array,
256 aha->ccb_dmamap);
257 case 5:
258 bus_dma_tag_destroy(aha->ccb_dmat);
259 case 4:
260 bus_dmamap_unload(aha->mailbox_dmat, aha->mailbox_dmamap);
261 case 3:
262 bus_dmamem_free(aha->mailbox_dmat, aha->in_boxes,
263 aha->mailbox_dmamap);
264 bus_dmamap_destroy(aha->mailbox_dmat, aha->mailbox_dmamap);
265 case 2:
266 bus_dma_tag_destroy(aha->buffer_dmat);
267 case 1:
268 bus_dma_tag_destroy(aha->mailbox_dmat);
269 case 0:
270 }
271 if (aha->unit != AHA_TEMP_UNIT) {
272 aha_softcs[aha->unit] = NULL;
273 }
274 free(aha, M_DEVBUF);
275}
276
277/*
278 * Probe the adapter and verify that the card is an Adaptec.
279 */
280int
281aha_probe(struct aha_softc* aha)
282{
283 u_int status;
284 u_int intstat;
285 int error;
286 u_int8_t param;
287 board_id_data_t board_id;
288
289 /*
290 * See if the three I/O ports look reasonable.
291 * Touch the minimal number of registers in the
292 * failure case.
293 */
294 status = aha_inb(aha, STATUS_REG);
295 if ((status == 0)
296 || (status & (DIAG_ACTIVE|CMD_REG_BUSY|
297 STATUS_REG_RSVD|CMD_INVALID)) != 0) {
298 return (ENXIO);
299 }
300
301 intstat = aha_inb(aha, INTSTAT_REG);
302 if ((intstat & INTSTAT_REG_RSVD) != 0) {
303 printf("%s: Failed Intstat Reg Test\n", aha_name(aha));
304 return (ENXIO);
305 }
306
307 /*
308 * Get the board ID. We use this to see if we're dealing with
309 * a buslogic card or a aha card (or clone).
310 */
311 error = aha_cmd(aha, BOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0,
312 (u_int8_t*)&board_id, sizeof(board_id),
313 DEFAULT_CMD_TIMEOUT);
314 if (error != 0) {
89
90/* Macro to determine that a rev is potentially a new valid one
91 * so that the driver doesn't keep breaking on new revs as it
92 * did for the CF and CP.
93 */
94#define PROBABLY_NEW_BOARD(REV) (REV > 0x43 && REV < 0x56)
95
96/* MailBox Management functions */
97static __inline void ahanextinbox(struct aha_softc *aha);
98static __inline void ahanextoutbox(struct aha_softc *aha);
99
100static __inline void
101ahanextinbox(struct aha_softc *aha)
102{
103 if (aha->cur_inbox == aha->last_inbox)
104 aha->cur_inbox = aha->in_boxes;
105 else
106 aha->cur_inbox++;
107}
108
109static __inline void
110ahanextoutbox(struct aha_softc *aha)
111{
112 if (aha->cur_outbox == aha->last_outbox)
113 aha->cur_outbox = aha->out_boxes;
114 else
115 aha->cur_outbox++;
116}
117
118#define ahautoa24(u,s3) \
119 (s3)[0] = ((u) >> 16) & 0xff; \
120 (s3)[1] = ((u) >> 8) & 0xff; \
121 (s3)[2] = (u) & 0xff;
122
123#define aha_a24tou(s3) \
124 (((s3)[0] << 16) | ((s3)[1] << 8) | (s3)[2])
125
126/* CCB Mangement functions */
127static __inline u_int32_t ahaccbvtop(struct aha_softc *aha,
128 struct aha_ccb *bccb);
129static __inline struct aha_ccb* ahaccbptov(struct aha_softc *aha,
130 u_int32_t ccb_addr);
131
132static __inline u_int32_t
133ahaccbvtop(struct aha_softc *aha, struct aha_ccb *bccb)
134{
135 return (aha->aha_ccb_physbase
136 + (u_int32_t)((caddr_t)bccb - (caddr_t)aha->aha_ccb_array));
137}
138static __inline struct aha_ccb *
139ahaccbptov(struct aha_softc *aha, u_int32_t ccb_addr)
140{
141 return (aha->aha_ccb_array +
142 + ((struct aha_ccb*)ccb_addr-(struct aha_ccb*)aha->aha_ccb_physbase));
143}
144
145static struct aha_ccb* ahagetccb(struct aha_softc *aha);
146static __inline void ahafreeccb(struct aha_softc *aha, struct aha_ccb *bccb);
147static void ahaallocccbs(struct aha_softc *aha);
148static bus_dmamap_callback_t ahaexecuteccb;
149static void ahadone(struct aha_softc *aha, struct aha_ccb *bccb,
150 aha_mbi_comp_code_t comp_code);
151
152/* Host adapter command functions */
153static int ahareset(struct aha_softc* aha, int hard_reset);
154
155/* Initialization functions */
156static int ahainitmboxes(struct aha_softc *aha);
157static bus_dmamap_callback_t ahamapmboxes;
158static bus_dmamap_callback_t ahamapccbs;
159static bus_dmamap_callback_t ahamapsgs;
160
161/* Transfer Negotiation Functions */
162static void ahafetchtransinfo(struct aha_softc *aha,
163 struct ccb_trans_settings *cts);
164
165/* CAM SIM entry points */
166#define ccb_bccb_ptr spriv_ptr0
167#define ccb_aha_ptr spriv_ptr1
168static void ahaaction(struct cam_sim *sim, union ccb *ccb);
169static void ahapoll(struct cam_sim *sim);
170
171/* Our timeout handler */
172timeout_t ahatimeout;
173
174u_long aha_unit = 0;
175
176/*
177 * Do our own re-probe protection until a configuration
178 * manager can do it for us. This ensures that we don't
179 * reprobe a card already found by the EISA or PCI probes.
180 */
181struct aha_isa_port aha_isa_ports[] =
182{
183 { 0x330, 0 },
184 { 0x334, 0 },
185 { 0x230, 0 },
186 { 0x234, 0 },
187 { 0x130, 0 },
188 { 0x134, 0 }
189};
190
191/* Exported functions */
192struct aha_softc *
193aha_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh)
194{
195 struct aha_softc *aha;
196 int i;
197
198 if (unit != AHA_TEMP_UNIT) {
199 if (unit >= NAHA) {
200 printf("aha: unit number (%d) too high\n", unit);
201 return NULL;
202 }
203
204 /*
205 * Allocate a storage area for us
206 */
207 if (aha_softcs[unit]) {
208 printf("aha%d: memory already allocated\n", unit);
209 return NULL;
210 }
211 }
212
213 aha = malloc(sizeof(struct aha_softc), M_DEVBUF, M_NOWAIT);
214 if (!aha) {
215 printf("aha%d: cannot malloc!\n", unit);
216 return NULL;
217 }
218 bzero(aha, sizeof(struct aha_softc));
219 SLIST_INIT(&aha->free_aha_ccbs);
220 LIST_INIT(&aha->pending_ccbs);
221 SLIST_INIT(&aha->sg_maps);
222 aha->unit = unit;
223 aha->tag = tag;
224 aha->bsh = bsh;
225
226 if (aha->unit != AHA_TEMP_UNIT) {
227 aha_softcs[unit] = aha;
228 }
229 return (aha);
230}
231
232void
233aha_free(struct aha_softc *aha)
234{
235 switch (aha->init_level) {
236 default:
237 case 8:
238 {
239 struct sg_map_node *sg_map;
240
241 while ((sg_map = SLIST_FIRST(&aha->sg_maps))!= NULL) {
242 SLIST_REMOVE_HEAD(&aha->sg_maps, links);
243 bus_dmamap_unload(aha->sg_dmat,
244 sg_map->sg_dmamap);
245 bus_dmamem_free(aha->sg_dmat, sg_map->sg_vaddr,
246 sg_map->sg_dmamap);
247 free(sg_map, M_DEVBUF);
248 }
249 bus_dma_tag_destroy(aha->sg_dmat);
250 }
251 case 7:
252 bus_dmamap_unload(aha->ccb_dmat, aha->ccb_dmamap);
253 case 6:
254 bus_dmamap_destroy(aha->ccb_dmat, aha->ccb_dmamap);
255 bus_dmamem_free(aha->ccb_dmat, aha->aha_ccb_array,
256 aha->ccb_dmamap);
257 case 5:
258 bus_dma_tag_destroy(aha->ccb_dmat);
259 case 4:
260 bus_dmamap_unload(aha->mailbox_dmat, aha->mailbox_dmamap);
261 case 3:
262 bus_dmamem_free(aha->mailbox_dmat, aha->in_boxes,
263 aha->mailbox_dmamap);
264 bus_dmamap_destroy(aha->mailbox_dmat, aha->mailbox_dmamap);
265 case 2:
266 bus_dma_tag_destroy(aha->buffer_dmat);
267 case 1:
268 bus_dma_tag_destroy(aha->mailbox_dmat);
269 case 0:
270 }
271 if (aha->unit != AHA_TEMP_UNIT) {
272 aha_softcs[aha->unit] = NULL;
273 }
274 free(aha, M_DEVBUF);
275}
276
277/*
278 * Probe the adapter and verify that the card is an Adaptec.
279 */
280int
281aha_probe(struct aha_softc* aha)
282{
283 u_int status;
284 u_int intstat;
285 int error;
286 u_int8_t param;
287 board_id_data_t board_id;
288
289 /*
290 * See if the three I/O ports look reasonable.
291 * Touch the minimal number of registers in the
292 * failure case.
293 */
294 status = aha_inb(aha, STATUS_REG);
295 if ((status == 0)
296 || (status & (DIAG_ACTIVE|CMD_REG_BUSY|
297 STATUS_REG_RSVD|CMD_INVALID)) != 0) {
298 return (ENXIO);
299 }
300
301 intstat = aha_inb(aha, INTSTAT_REG);
302 if ((intstat & INTSTAT_REG_RSVD) != 0) {
303 printf("%s: Failed Intstat Reg Test\n", aha_name(aha));
304 return (ENXIO);
305 }
306
307 /*
308 * Get the board ID. We use this to see if we're dealing with
309 * a buslogic card or a aha card (or clone).
310 */
311 error = aha_cmd(aha, BOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0,
312 (u_int8_t*)&board_id, sizeof(board_id),
313 DEFAULT_CMD_TIMEOUT);
314 if (error != 0) {
315 if (bootverbose)
316 printf("%s: INQUIRE failed %x\n", aha_name(aha), error);
315 PRVERB(("%s: INQUIRE failed %x\n", aha_name(aha), error));
317 return (ENXIO);
318 }
319 aha->fw_major = board_id.firmware_rev_major;
320 aha->fw_minor = board_id.firmware_rev_minor;
321 aha->boardid = board_id.board_type;
322
323 /*
324 * The Buslogic cards have an id of either 0x41 or 0x42. So
325 * if those come up in the probe, we test the geometry register
326 * of the board. Adaptec boards that are this old will not have
327 * this register, and return 0xff, while buslogic cards will return
328 * something different.
329 *
330 * XXX I'm not sure how this will impact other cloned cards.
331 */
332 if (aha->boardid <= 0x42) {
333 status = aha_inb(aha, GEOMETRY_REG);
334 if (status != 0xff)
335 return (ENXIO);
336 }
337
338 return (0);
339}
340
341/*
342 * Pull the boards setup information and record it in our softc.
343 */
344int
345aha_fetch_adapter_info(struct aha_softc *aha)
346{
347 setup_data_t setup_info;
348 config_data_t config_data;
349 u_int8_t length_param;
350 int error;
351 struct aha_extbios extbios;
352
353 switch (aha->boardid) {
354 case BOARD_1540_16HEAD_BIOS:
355 strcpy(aha->model, "1540 16 head BIOS");
356 break;
357 case BOARD_1540_64HEAD_BIOS:
358 strcpy(aha->model, "1540 64 head BIOS");
359 break;
360 case BOARD_1542:
361 strcpy(aha->model, "1540/1542 64 head BIOS");
362 break;
363 case BOARD_1640:
364 strcpy(aha->model, "1640");
365 break;
366 case BOARD_1740:
367 strcpy(aha->model, "1740A/1742A/1744");
368 break;
369 case BOARD_1542C:
370 strcpy(aha->model, "1542C");
371 break;
372 case BOARD_1542CF:
373 strcpy(aha->model, "1542CF");
374 break;
375 case BOARD_1542CP:
376 strcpy(aha->model, "1542CP");
377 break;
378 default:
379 strcpy(aha->model, "Unknown");
380 break;
381 }
382 /*
383 * If we are a new type of 1542 board (anything newer than a 1542C)
384 * then disable the extended bios so that the
385 * mailbox interface is unlocked.
386 * This is also true for the 1542B Version 3.20. First Adaptec
387 * board that supports >1Gb drives.
388 * No need to check the extended bios flags as some of the
389 * extensions that cause us problems are not flagged in that byte.
390 */
391 if (PROBABLY_NEW_BOARD(aha->boardid) ||
392 (aha->boardid == 0x41
393 && aha->fw_major == 0x31 &&
394 aha->fw_minor >= 0x34)) {
395 error = aha_cmd(aha, BOP_RETURN_EXT_BIOS_INFO, NULL,
396 /*paramlen*/0, (u_char *)&extbios, sizeof(extbios),
397 DEFAULT_CMD_TIMEOUT);
398 error = aha_cmd(aha, BOP_MBOX_IF_ENABLE, (u_int8_t *)&extbios,
399 /*paramlen*/2, NULL, 0, DEFAULT_CMD_TIMEOUT);
400 }
401 if (aha->boardid < 0x41)
402 printf("%s: Likely aha 1542A, which might not work properly\n",
403 aha_name(aha));
404
405 aha->max_sg = 17;
406 aha->diff_bus = 0;
407 aha->extended_lun = 0;
408 aha->extended_trans = 0;
409 aha->max_ccbs = 17; /* Need 17 to do 64k I/O */
410 /* Determine Sync/Wide/Disc settings */
411 length_param = sizeof(setup_info);
412 error = aha_cmd(aha, BOP_INQUIRE_SETUP_INFO, &length_param,
413 /*paramlen*/1, (u_int8_t*)&setup_info,
414 sizeof(setup_info), DEFAULT_CMD_TIMEOUT);
415 if (error != 0) {
416 printf("%s: aha_fetch_adapter_info - Failed "
417 "Get Setup Info\n", aha_name(aha));
418 return (error);
419 }
420 if (setup_info.initiate_sync != 0) {
421 aha->sync_permitted = ALL_TARGETS;
422 }
423 aha->disc_permitted = ALL_TARGETS;
424
425 /* We need as many mailboxes as we can have ccbs */
426 aha->num_boxes = aha->max_ccbs;
427
428 /* Determine our SCSI ID */
429
430 error = aha_cmd(aha, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
431 (u_int8_t*)&config_data, sizeof(config_data),
432 DEFAULT_CMD_TIMEOUT);
433 if (error != 0) {
434 printf("%s: aha_fetch_adapter_info - Failed Get Config\n",
435 aha_name(aha));
436 return (error);
437 }
438 aha->scsi_id = config_data.scsi_id;
439 return (0);
440}
441
442/*
443 * Start the board, ready for normal operation
444 */
445int
446aha_init(struct aha_softc* aha)
447{
448 /* Announce the Adapter */
449 printf("%s: AHA-%s FW Rev. %c.%c (ID=%x) ", aha_name(aha),
450 aha->model, aha->fw_major, aha->fw_minor, aha->boardid);
451
452 if (aha->diff_bus != 0)
453 printf("Diff ");
454
455 printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", aha->scsi_id,
456 aha->max_ccbs);
457
458 /*
459 * Create our DMA tags. These tags define the kinds of device
460 * accessable memory allocations and memory mappings we will
461 * need to perform during normal operation.
462 *
463 * Unless we need to further restrict the allocation, we rely
464 * on the restrictions of the parent dmat, hence the common
465 * use of MAXADDR and MAXSIZE.
466 */
467
468 /* DMA tag for mapping buffers into device visible space. */
469 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0,
470 /*lowaddr*/BUS_SPACE_MAXADDR,
471 /*highaddr*/BUS_SPACE_MAXADDR,
472 /*filter*/NULL, /*filterarg*/NULL,
473 /*maxsize*/MAXBSIZE, /*nsegments*/AHA_NSEG,
474 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
475 /*flags*/BUS_DMA_ALLOCNOW,
476 &aha->buffer_dmat) != 0) {
477 goto error_exit;
478 }
479
480 aha->init_level++;
481 /* DMA tag for our mailboxes */
482 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0,
483 /*lowaddr*/BUS_SPACE_MAXADDR,
484 /*highaddr*/BUS_SPACE_MAXADDR,
485 /*filter*/NULL, /*filterarg*/NULL,
486 aha->num_boxes * (sizeof(aha_mbox_in_t)
487 + sizeof(aha_mbox_out_t)),
488 /*nsegments*/1,
489 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
490 /*flags*/0, &aha->mailbox_dmat) != 0) {
491 goto error_exit;
492 }
493
494 aha->init_level++;
495
496 /* Allocation for our mailboxes */
497 if (bus_dmamem_alloc(aha->mailbox_dmat, (void **)&aha->out_boxes,
498 BUS_DMA_NOWAIT, &aha->mailbox_dmamap) != 0) {
499 goto error_exit;
500 }
501
502 aha->init_level++;
503
504 /* And permanently map them */
505 bus_dmamap_load(aha->mailbox_dmat, aha->mailbox_dmamap,
506 aha->out_boxes,
507 aha->num_boxes * (sizeof(aha_mbox_in_t)
508 + sizeof(aha_mbox_out_t)),
509 ahamapmboxes, aha, /*flags*/0);
510
511 aha->init_level++;
512
513 aha->in_boxes = (aha_mbox_in_t *)&aha->out_boxes[aha->num_boxes];
514
515 ahainitmboxes(aha);
516
517 /* DMA tag for our ccb structures */
518 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0,
519 /*lowaddr*/BUS_SPACE_MAXADDR,
520 /*highaddr*/BUS_SPACE_MAXADDR,
521 /*filter*/NULL, /*filterarg*/NULL,
522 aha->max_ccbs * sizeof(struct aha_ccb),
523 /*nsegments*/1,
524 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
525 /*flags*/0, &aha->ccb_dmat) != 0) {
526 goto error_exit;
527 }
528
529 aha->init_level++;
530
531 /* Allocation for our ccbs */
532 if (bus_dmamem_alloc(aha->ccb_dmat, (void **)&aha->aha_ccb_array,
533 BUS_DMA_NOWAIT, &aha->ccb_dmamap) != 0) {
534 goto error_exit;
535 }
536
537 aha->init_level++;
538
539 /* And permanently map them */
540 bus_dmamap_load(aha->ccb_dmat, aha->ccb_dmamap,
541 aha->aha_ccb_array,
542 aha->max_ccbs * sizeof(struct aha_ccb),
543 ahamapccbs, aha, /*flags*/0);
544
545 aha->init_level++;
546
547 /* DMA tag for our S/G structures. We allocate in page sized chunks */
548 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0,
549 /*lowaddr*/BUS_SPACE_MAXADDR,
550 /*highaddr*/BUS_SPACE_MAXADDR,
551 /*filter*/NULL, /*filterarg*/NULL,
552 PAGE_SIZE, /*nsegments*/1,
553 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
554 /*flags*/0, &aha->sg_dmat) != 0) {
555 goto error_exit;
556 }
557
558 aha->init_level++;
559
560 /* Perform initial CCB allocation */
561 bzero(aha->aha_ccb_array, aha->max_ccbs * sizeof(struct aha_ccb));
562 ahaallocccbs(aha);
563
564 if (aha->num_ccbs == 0) {
565 printf("%s: aha_init - Unable to allocate initial ccbs\n",
566 aha_name(aha));
567 goto error_exit;
568 }
569
570 /*
571 * Note that we are going and return (to probe)
572 */
573 return 0;
574
575error_exit:
576
577 return (ENXIO);
578}
579
580int
581aha_attach(struct aha_softc *aha)
582{
583 int tagged_dev_openings;
584 struct cam_devq *devq;
585
586 /*
587 * We reserve 1 ccb for error recovery, so don't
588 * tell the XPT about it.
589 */
590 tagged_dev_openings = 0;
591
592 /*
593 * Create the device queue for our SIM.
594 */
595 devq = cam_simq_alloc(aha->max_ccbs - 1);
596 if (devq == NULL)
597 return (ENOMEM);
598
599 /*
600 * Construct our SIM entry
601 */
602 aha->sim = cam_sim_alloc(ahaaction, ahapoll, "aha", aha, aha->unit,
603 2, tagged_dev_openings, devq);
604 if (aha->sim == NULL) {
605 cam_simq_free(devq);
606 return (ENOMEM);
607 }
608
609 if (xpt_bus_register(aha->sim, 0) != CAM_SUCCESS) {
610 cam_sim_free(aha->sim, /*free_devq*/TRUE);
611 return (ENXIO);
612 }
613
614 if (xpt_create_path(&aha->path, /*periph*/NULL,
615 cam_sim_path(aha->sim), CAM_TARGET_WILDCARD,
616 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
617 xpt_bus_deregister(cam_sim_path(aha->sim));
618 cam_sim_free(aha->sim, /*free_devq*/TRUE);
619 return (ENXIO);
620 }
621
622 return (0);
623}
624
625char *
626aha_name(struct aha_softc *aha)
627{
628 static char name[10];
629
630 sprintf(name, "aha%d", aha->unit);
631 return (name);
632}
633
634int
635aha_check_probed_iop(u_int ioport)
636{
637 u_int i;
638
639 for (i=0; i < AHA_NUM_ISAPORTS; i++) {
640 if (aha_isa_ports[i].addr == ioport) {
641 if (aha_isa_ports[i].probed != 0)
642 return (1);
643 else {
644 return (0);
645 }
646 }
647 }
648 return (1);
649}
650
651void
652aha_mark_probed_bio(isa_compat_io_t port)
653{
654 if (port < BIO_DISABLED)
655 aha_isa_ports[port].probed = 1;
656}
657
658void
659aha_mark_probed_iop(u_int ioport)
660{
661 u_int i;
662
663 for (i = 0; i < AHA_NUM_ISAPORTS; i++) {
664 if (ioport == aha_isa_ports[i].addr) {
665 aha_isa_ports[i].probed = 1;
666 break;
667 }
668 }
669}
670
671static void
672ahaallocccbs(struct aha_softc *aha)
673{
674 struct aha_ccb *next_ccb;
675 struct sg_map_node *sg_map;
676 bus_addr_t physaddr;
677 aha_sg_t *segs;
678 int newcount;
679 int i;
680
681 next_ccb = &aha->aha_ccb_array[aha->num_ccbs];
682
683 sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
684
685 if (sg_map == NULL)
686 return;
687
688 /* Allocate S/G space for the next batch of CCBS */
689 if (bus_dmamem_alloc(aha->sg_dmat, (void **)&sg_map->sg_vaddr,
690 BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {
691 free(sg_map, M_DEVBUF);
692 return;
693 }
694
695 SLIST_INSERT_HEAD(&aha->sg_maps, sg_map, links);
696
697 bus_dmamap_load(aha->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr,
698 PAGE_SIZE, ahamapsgs, aha, /*flags*/0);
699
700 segs = sg_map->sg_vaddr;
701 physaddr = sg_map->sg_physaddr;
702
703 newcount = (PAGE_SIZE / (AHA_NSEG * sizeof(aha_sg_t)));
704 for (i = 0; aha->num_ccbs < aha->max_ccbs && i < newcount; i++) {
705 int error;
706
707 next_ccb->sg_list = segs;
708 next_ccb->sg_list_phys = physaddr;
709 next_ccb->flags = BCCB_FREE;
710 error = bus_dmamap_create(aha->buffer_dmat, /*flags*/0,
711 &next_ccb->dmamap);
712 if (error != 0)
713 break;
714 SLIST_INSERT_HEAD(&aha->free_aha_ccbs, next_ccb, links);
715 segs += AHA_NSEG;
716 physaddr += (AHA_NSEG * sizeof(aha_sg_t));
717 next_ccb++;
718 aha->num_ccbs++;
719 }
720
721 /* Reserve a CCB for error recovery */
722 if (aha->recovery_bccb == NULL) {
723 aha->recovery_bccb = SLIST_FIRST(&aha->free_aha_ccbs);
724 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
725 }
726}
727
728static __inline void
729ahafreeccb(struct aha_softc *aha, struct aha_ccb *bccb)
730{
731 int s;
732
733 s = splcam();
734 if ((bccb->flags & BCCB_ACTIVE) != 0)
735 LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le);
736 if (aha->resource_shortage != 0
737 && (bccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
738 bccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
739 aha->resource_shortage = FALSE;
740 }
741 bccb->flags = BCCB_FREE;
742 SLIST_INSERT_HEAD(&aha->free_aha_ccbs, bccb, links);
743 splx(s);
744}
745
746static struct aha_ccb*
747ahagetccb(struct aha_softc *aha)
748{
749 struct aha_ccb* bccb;
750 int s;
751
752 s = splcam();
753 if ((bccb = SLIST_FIRST(&aha->free_aha_ccbs)) != NULL) {
754 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
755 } else if (aha->num_ccbs < aha->max_ccbs) {
756 ahaallocccbs(aha);
757 bccb = SLIST_FIRST(&aha->free_aha_ccbs);
758 if (bccb == NULL)
759 printf("%s: Can't malloc BCCB\n", aha_name(aha));
760 else
761 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
762 }
763 splx(s);
764
765 return (bccb);
766}
767
768static void
769ahaaction(struct cam_sim *sim, union ccb *ccb)
770{
771 struct aha_softc *aha;
772 int s;
773
774 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahaaction\n"));
775
776 aha = (struct aha_softc *)cam_sim_softc(sim);
777
778 switch (ccb->ccb_h.func_code) {
779 /* Common cases first */
780 case XPT_SCSI_IO: /* Execute the requested I/O operation */
781 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
782 {
783 struct aha_ccb *bccb;
784 struct aha_hccb *hccb;
785
786 /*
787 * get a bccb to use.
788 */
789 if ((bccb = ahagetccb(aha)) == NULL) {
790 int s;
791
792 s = splcam();
793 aha->resource_shortage = TRUE;
794 splx(s);
795 xpt_freeze_simq(aha->sim, /*count*/1);
796 ccb->ccb_h.status = CAM_REQUEUE_REQ;
797 xpt_done(ccb);
798 return;
799 }
800
801 hccb = &bccb->hccb;
802
803 /*
804 * So we can find the BCCB when an abort is requested
805 */
806 bccb->ccb = ccb;
807 ccb->ccb_h.ccb_bccb_ptr = bccb;
808 ccb->ccb_h.ccb_aha_ptr = aha;
809
810 /*
811 * Put all the arguments for the xfer in the bccb
812 */
813 hccb->target = ccb->ccb_h.target_id;
814 hccb->lun = ccb->ccb_h.target_lun;
815 hccb->ahastat = 0;
816 hccb->sdstat = 0;
817
818 if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
819 struct ccb_scsiio *csio;
820 struct ccb_hdr *ccbh;
821
822 csio = &ccb->csio;
823 ccbh = &csio->ccb_h;
824 hccb->opcode = INITIATOR_CCB_WRESID;
825 hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) != 0;
826 hccb->dataout = (ccb->ccb_h.flags & CAM_DIR_OUT) != 0;
827 hccb->cmd_len = csio->cdb_len;
828 if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) {
829 ccb->ccb_h.status = CAM_REQ_INVALID;
830 ahafreeccb(aha, bccb);
831 xpt_done(ccb);
832 return;
833 }
834 hccb->sense_len = csio->sense_len;
835 if ((ccbh->flags & CAM_CDB_POINTER) != 0) {
836 if ((ccbh->flags & CAM_CDB_PHYS) == 0) {
837 bcopy(csio->cdb_io.cdb_ptr,
838 hccb->scsi_cdb, hccb->cmd_len);
839 } else {
840 /* I guess I could map it in... */
841 ccbh->status = CAM_REQ_INVALID;
842 ahafreeccb(aha, bccb);
843 xpt_done(ccb);
844 return;
845 }
846 } else {
847 bcopy(csio->cdb_io.cdb_bytes,
848 hccb->scsi_cdb, hccb->cmd_len);
849 }
850 /*
851 * If we have any data to send with this command,
852 * map it into bus space.
853 */
854 /* Only use S/G if there is a transfer */
855 if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
856 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) {
857 /*
858 * We've been given a pointer
859 * to a single buffer.
860 */
861 if ((ccbh->flags & CAM_DATA_PHYS)==0) {
862 int s;
863 int error;
864
865 s = splsoftvm();
866 error = bus_dmamap_load(
867 aha->buffer_dmat,
868 bccb->dmamap,
869 csio->data_ptr,
870 csio->dxfer_len,
871 ahaexecuteccb,
872 bccb,
873 /*flags*/0);
874 if (error == EINPROGRESS) {
875 /*
876 * So as to maintain
877 * ordering, freeze the
878 * controller queue
879 * until our mapping is
880 * returned.
881 */
882 xpt_freeze_simq(aha->sim,
883 1);
884 csio->ccb_h.status |=
885 CAM_RELEASE_SIMQ;
886 }
887 splx(s);
888 } else {
889 struct bus_dma_segment seg;
890
891 /* Pointer to physical buffer */
892 seg.ds_addr =
893 (bus_addr_t)csio->data_ptr;
894 seg.ds_len = csio->dxfer_len;
895 ahaexecuteccb(bccb, &seg, 1, 0);
896 }
897 } else {
898 struct bus_dma_segment *segs;
899
900 if ((ccbh->flags & CAM_DATA_PHYS) != 0)
901 panic("ahaaction - Physical "
902 "segment pointers "
903 "unsupported");
904
905 if ((ccbh->flags&CAM_SG_LIST_PHYS)==0)
906 panic("ahaaction - Virtual "
907 "segment addresses "
908 "unsupported");
909
910 /* Just use the segments provided */
911 segs = (struct bus_dma_segment *)
912 csio->data_ptr;
913 ahaexecuteccb(bccb, segs,
914 csio->sglist_cnt, 0);
915 }
916 } else {
917 ahaexecuteccb(bccb, NULL, 0, 0);
918 }
919 } else {
920 hccb->opcode = INITIATOR_BUS_DEV_RESET;
921 /* No data transfer */
922 hccb->datain = TRUE;
923 hccb->dataout = TRUE;
924 hccb->cmd_len = 0;
925 hccb->sense_len = 0;
926 ahaexecuteccb(bccb, NULL, 0, 0);
927 }
928 break;
929 }
930 case XPT_EN_LUN: /* Enable LUN as a target */
931 case XPT_TARGET_IO: /* Execute target I/O request */
932 case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
933 case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/
934 case XPT_ABORT: /* Abort the specified CCB */
935 /* XXX Implement */
936 ccb->ccb_h.status = CAM_REQ_INVALID;
937 xpt_done(ccb);
938 break;
939 case XPT_SET_TRAN_SETTINGS:
940 {
941 /* XXX Implement */
942 ccb->ccb_h.status = CAM_REQ_CMP;
943 xpt_done(ccb);
944 break;
945 }
946 case XPT_GET_TRAN_SETTINGS:
947 /* Get default/user set transfer settings for the target */
948 {
949 struct ccb_trans_settings *cts;
950 u_int target_mask;
951
952 cts = &ccb->cts;
953 target_mask = 0x01 << ccb->ccb_h.target_id;
954 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
955 cts->flags = 0;
956 if ((aha->disc_permitted & target_mask) != 0)
957 cts->flags |= CCB_TRANS_DISC_ENB;
958 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
959 if ((aha->sync_permitted & target_mask) != 0)
960 cts->sync_period = 50;
961 else
962 cts->sync_period = 0;
963
964 if (cts->sync_period != 0)
965 cts->sync_offset = 15;
966
967 cts->valid = CCB_TRANS_SYNC_RATE_VALID
968 | CCB_TRANS_SYNC_OFFSET_VALID
969 | CCB_TRANS_BUS_WIDTH_VALID
970 | CCB_TRANS_DISC_VALID
971 | CCB_TRANS_TQ_VALID;
972 } else {
973 ahafetchtransinfo(aha, cts);
974 }
975
976 ccb->ccb_h.status = CAM_REQ_CMP;
977 xpt_done(ccb);
978 break;
979 }
980 case XPT_CALC_GEOMETRY:
981 {
982 struct ccb_calc_geometry *ccg;
983 u_int32_t size_mb;
984 u_int32_t secs_per_cylinder;
985
986 ccg = &ccb->ccg;
987 size_mb = ccg->volume_size
988 / ((1024L * 1024L) / ccg->block_size);
989
990 if (size_mb >= 1024 && (aha->extended_trans != 0)) {
991 if (size_mb >= 2048) {
992 ccg->heads = 255;
993 ccg->secs_per_track = 63;
994 } else {
995 ccg->heads = 128;
996 ccg->secs_per_track = 32;
997 }
998 } else {
999 ccg->heads = 64;
1000 ccg->secs_per_track = 32;
1001 }
1002 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
1003 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
1004 ccb->ccb_h.status = CAM_REQ_CMP;
1005 xpt_done(ccb);
1006 break;
1007 }
1008 case XPT_RESET_BUS: /* Reset the specified SCSI bus */
1009 {
1010 ahareset(aha, /*hardreset*/TRUE);
1011 ccb->ccb_h.status = CAM_REQ_CMP;
1012 xpt_done(ccb);
1013 break;
1014 }
1015 case XPT_TERM_IO: /* Terminate the I/O process */
1016 /* XXX Implement */
1017 ccb->ccb_h.status = CAM_REQ_INVALID;
1018 xpt_done(ccb);
1019 break;
1020 case XPT_PATH_INQ: /* Path routing inquiry */
1021 {
1022 struct ccb_pathinq *cpi = &ccb->cpi;
1023
1024 cpi->version_num = 1; /* XXX??? */
1025 cpi->hba_inquiry = PI_SDTR_ABLE;
1026 cpi->target_sprt = 0;
1027 cpi->hba_misc = 0;
1028 cpi->hba_eng_cnt = 0;
1029 cpi->max_target = 7;
1030 cpi->max_lun = 7;
1031 cpi->initiator_id = aha->scsi_id;
1032 cpi->bus_id = cam_sim_bus(sim);
1033 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1034 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
1035 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1036 cpi->unit_number = cam_sim_unit(sim);
1037 cpi->ccb_h.status = CAM_REQ_CMP;
1038 xpt_done(ccb);
1039 break;
1040 }
1041 default:
1042 ccb->ccb_h.status = CAM_REQ_INVALID;
1043 xpt_done(ccb);
1044 break;
1045 }
1046}
1047
1048static void
1049ahaexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
1050{
1051 struct aha_ccb *bccb;
1052 union ccb *ccb;
1053 struct aha_softc *aha;
1054 int s, i;
1055 u_int32_t paddr;
1056
1057 bccb = (struct aha_ccb *)arg;
1058 ccb = bccb->ccb;
1059 aha = (struct aha_softc *)ccb->ccb_h.ccb_aha_ptr;
1060
1061 if (error != 0) {
1062 if (error != EFBIG)
1063 printf("%s: Unexepected error 0x%x returned from "
1064 "bus_dmamap_load\n", aha_name(aha), error);
1065 if (ccb->ccb_h.status == CAM_REQ_INPROG) {
1066 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
1067 ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
1068 }
1069 ahafreeccb(aha, bccb);
1070 xpt_done(ccb);
1071 return;
1072 }
1073
1074 if (nseg != 0) {
1075 aha_sg_t *sg;
1076 bus_dma_segment_t *end_seg;
1077 bus_dmasync_op_t op;
1078
1079 end_seg = dm_segs + nseg;
1080
1081 /* Copy the segments into our SG list */
1082 sg = bccb->sg_list;
1083 while (dm_segs < end_seg) {
1084 ahautoa24(dm_segs->ds_len, sg->len);
1085 ahautoa24(dm_segs->ds_addr, sg->addr);
1086 sg++;
1087 dm_segs++;
1088 }
1089
1090 if (nseg > 1) {
1091 bccb->hccb.opcode = INITIATOR_SG_CCB_WRESID;
1092 ahautoa24((sizeof(aha_sg_t) * nseg),
1093 bccb->hccb.data_len);
1094 ahautoa24(bccb->sg_list_phys, bccb->hccb.data_addr);
1095 } else {
1096 bcopy(bccb->sg_list->len, bccb->hccb.data_len, 3);
1097 bcopy(bccb->sg_list->addr, bccb->hccb.data_addr, 3);
1098 }
1099
1100 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1101 op = BUS_DMASYNC_PREREAD;
1102 else
1103 op = BUS_DMASYNC_PREWRITE;
1104
1105 bus_dmamap_sync(aha->buffer_dmat, bccb->dmamap, op);
1106
1107 } else {
1108 bccb->hccb.opcode = INITIATOR_CCB_WRESID;
1109 ahautoa24(0, bccb->hccb.data_len);
1110 ahautoa24(0, bccb->hccb.data_addr);
1111 }
1112
1113 s = splcam();
1114
1115 /*
1116 * Last time we need to check if this CCB needs to
1117 * be aborted.
1118 */
1119 if (ccb->ccb_h.status != CAM_REQ_INPROG) {
1120 if (nseg != 0)
1121 bus_dmamap_unload(aha->buffer_dmat, bccb->dmamap);
1122 ahafreeccb(aha, bccb);
1123 xpt_done(ccb);
1124 splx(s);
1125 return;
1126 }
1127
1128 bccb->flags = BCCB_ACTIVE;
1129 ccb->ccb_h.status |= CAM_SIM_QUEUED;
1130 LIST_INSERT_HEAD(&aha->pending_ccbs, &ccb->ccb_h, sim_links.le);
1131
1132 ccb->ccb_h.timeout_ch =
1133 timeout(ahatimeout, (caddr_t)bccb,
1134 (ccb->ccb_h.timeout * hz) / 1000);
1135
1136 /* Tell the adapter about this command */
1137 paddr = ahaccbvtop(aha, bccb);
1138 ahautoa24(paddr, aha->cur_outbox->ccb_addr);
1139 if (aha->cur_outbox->action_code != BMBO_FREE)
1140 panic("%s: Too few mailboxes or to many ccbs???", aha_name(aha));
1141 aha->cur_outbox->action_code = BMBO_START;
1142 aha_outb(aha, COMMAND_REG, BOP_START_MBOX);
1143
1144 ahanextoutbox(aha);
1145 splx(s);
1146}
1147
1148void
1149aha_intr(void *arg)
1150{
1151 struct aha_softc *aha;
1152 u_int intstat;
1153
1154 aha = (struct aha_softc *)arg;
1155 while (((intstat = aha_inb(aha, INTSTAT_REG)) & INTR_PENDING) != 0) {
1156 if ((intstat & CMD_COMPLETE) != 0) {
1157 aha->latched_status = aha_inb(aha, STATUS_REG);
1158 aha->command_cmp = TRUE;
1159 }
1160
1161 aha_outb(aha, CONTROL_REG, RESET_INTR);
1162
1163 if ((intstat & IMB_LOADED) != 0) {
1164 while (aha->cur_inbox->comp_code != BMBI_FREE) {
1165 u_int32_t paddr;
1166 paddr = aha_a24tou(aha->cur_inbox->ccb_addr);
1167 ahadone(aha,
1168 ahaccbptov(aha, paddr),
1169 aha->cur_inbox->comp_code);
1170 aha->cur_inbox->comp_code = BMBI_FREE;
1171 ahanextinbox(aha);
1172 }
1173 }
1174
1175 if ((intstat & SCSI_BUS_RESET) != 0) {
1176 ahareset(aha, /*hardreset*/FALSE);
1177 }
1178 }
1179}
1180
1181static void
1182ahadone(struct aha_softc *aha, struct aha_ccb *bccb, aha_mbi_comp_code_t comp_code)
1183{
1184 union ccb *ccb;
1185 struct ccb_scsiio *csio;
1186
1187 ccb = bccb->ccb;
1188 csio = &bccb->ccb->csio;
1189
1190 if ((bccb->flags & BCCB_ACTIVE) == 0) {
1191 printf("%s: ahadone - Attempt to free non-active BCCB %p\n",
1192 aha_name(aha), (void *)bccb);
1193 return;
1194 }
1195
1196 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1197 bus_dmasync_op_t op;
1198
1199 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1200 op = BUS_DMASYNC_POSTREAD;
1201 else
1202 op = BUS_DMASYNC_POSTWRITE;
1203 bus_dmamap_sync(aha->buffer_dmat, bccb->dmamap, op);
1204 bus_dmamap_unload(aha->buffer_dmat, bccb->dmamap);
1205 }
1206
1207 if (bccb == aha->recovery_bccb) {
1208 /*
1209 * The recovery BCCB does not have a CCB associated
1210 * with it, so short circuit the normal error handling.
1211 * We now traverse our list of pending CCBs and process
1212 * any that were terminated by the recovery CCBs action.
1213 * We also reinstate timeouts for all remaining, pending,
1214 * CCBs.
1215 */
1216 struct cam_path *path;
1217 struct ccb_hdr *ccb_h;
1218 cam_status error;
1219
1220 /* Notify all clients that a BDR occured */
1221 error = xpt_create_path(&path, /*periph*/NULL,
1222 cam_sim_path(aha->sim),
1223 bccb->hccb.target,
1224 CAM_LUN_WILDCARD);
1225
1226 if (error == CAM_REQ_CMP)
1227 xpt_async(AC_SENT_BDR, path, NULL);
1228
1229 ccb_h = LIST_FIRST(&aha->pending_ccbs);
1230 while (ccb_h != NULL) {
1231 struct aha_ccb *pending_bccb;
1232
1233 pending_bccb = (struct aha_ccb *)ccb_h->ccb_bccb_ptr;
1234 if (pending_bccb->hccb.target == bccb->hccb.target) {
1235 pending_bccb->hccb.ahastat = AHASTAT_HA_BDR;
1236 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1237 ahadone(aha, pending_bccb, BMBI_ERROR);
1238 } else {
1239 ccb_h->timeout_ch =
1240 timeout(ahatimeout, (caddr_t)pending_bccb,
1241 (ccb_h->timeout * hz) / 1000);
1242 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1243 }
1244 }
1245 printf("%s: No longer in timeout\n", aha_name(aha));
1246 return;
1247 }
1248
1249 untimeout(ahatimeout, bccb, ccb->ccb_h.timeout_ch);
1250
1251 switch (comp_code) {
1252 case BMBI_FREE:
1253 printf("%s: ahadone - CCB completed with free status!\n",
1254 aha_name(aha));
1255 break;
1256 case BMBI_NOT_FOUND:
1257 printf("%s: ahadone - CCB Abort failed to find CCB\n",
1258 aha_name(aha));
1259 break;
1260 case BMBI_ABORT:
1261 case BMBI_ERROR:
1262 /* An error occured */
1263 switch(bccb->hccb.ahastat) {
1264 case AHASTAT_DATARUN_ERROR:
1265 if (bccb->hccb.data_len <= 0) {
1266 csio->ccb_h.status = CAM_DATA_RUN_ERR;
1267 break;
1268 }
1269 /* FALLTHROUGH */
1270 case AHASTAT_NOERROR:
1271 csio->scsi_status = bccb->hccb.sdstat;
1272 csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
1273 switch(csio->scsi_status) {
1274 case SCSI_STATUS_CHECK_COND:
1275 case SCSI_STATUS_CMD_TERMINATED:
1276 csio->ccb_h.status |= CAM_AUTOSNS_VALID;
1277 /*
1278 * The aha writes the sense data at different
1279 * offsets based on the scsi cmd len
1280 */
1281 bcopy((caddr_t) &bccb->hccb.scsi_cdb +
1282 bccb->hccb.cmd_len,
1283 (caddr_t) &csio->sense_data,
1284 bccb->hccb.sense_len);
1285 break;
1286 default:
1287 break;
1288 case SCSI_STATUS_OK:
1289 csio->ccb_h.status = CAM_REQ_CMP;
1290 break;
1291 }
1292 csio->resid = aha_a24tou(bccb->hccb.data_len);
1293 break;
1294 case AHASTAT_SELTIMEOUT:
1295 csio->ccb_h.status = CAM_SEL_TIMEOUT;
1296 break;
1297 case AHASTAT_UNEXPECTED_BUSFREE:
1298 csio->ccb_h.status = CAM_UNEXP_BUSFREE;
1299 break;
1300 case AHASTAT_INVALID_PHASE:
1301 csio->ccb_h.status = CAM_SEQUENCE_FAIL;
1302 break;
1303 case AHASTAT_INVALID_ACTION_CODE:
1304 panic("%s: Inavlid Action code", aha_name(aha));
1305 break;
1306 case AHASTAT_INVALID_OPCODE:
1307 panic("%s: Inavlid CCB Opcode code %x hccb = %p",
1308 aha_name(aha), bccb->hccb.opcode, &bccb->hccb);
1309 break;
1310 case AHASTAT_LINKED_CCB_LUN_MISMATCH:
1311 /* We don't even support linked commands... */
1312 panic("%s: Linked CCB Lun Mismatch", aha_name(aha));
1313 break;
1314 case AHASTAT_INVALID_CCB_OR_SG_PARAM:
1315 panic("%s: Invalid CCB or SG list", aha_name(aha));
1316 break;
1317 case AHASTAT_HA_SCSI_BUS_RESET:
1318 if ((csio->ccb_h.status & CAM_STATUS_MASK)
1319 != CAM_CMD_TIMEOUT)
1320 csio->ccb_h.status = CAM_SCSI_BUS_RESET;
1321 break;
1322 case AHASTAT_HA_BDR:
1323 if ((bccb->flags & BCCB_DEVICE_RESET) == 0)
1324 csio->ccb_h.status = CAM_BDR_SENT;
1325 else
1326 csio->ccb_h.status = CAM_CMD_TIMEOUT;
1327 break;
1328 }
1329 if (csio->ccb_h.status != CAM_REQ_CMP) {
1330 xpt_freeze_devq(csio->ccb_h.path, /*count*/1);
1331 csio->ccb_h.status |= CAM_DEV_QFRZN;
1332 }
1333 if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0)
1334 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1335 ahafreeccb(aha, bccb);
1336 xpt_done(ccb);
1337 break;
1338 case BMBI_OK:
1339 /* All completed without incident */
1340 /* XXX DO WE NEED TO COPY SENSE BYTES HERE???? XXX */
1341 ccb->ccb_h.status |= CAM_REQ_CMP;
1342 if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0)
1343 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1344 ahafreeccb(aha, bccb);
1345 xpt_done(ccb);
1346 break;
1347 }
1348}
1349
1350static int
1351ahareset(struct aha_softc* aha, int hard_reset)
1352{
1353 struct ccb_hdr *ccb_h;
1354 u_int status;
1355 u_int timeout;
1356 u_int8_t reset_type;
1357
1358 if (hard_reset != 0)
1359 reset_type = HARD_RESET;
1360 else
1361 reset_type = SOFT_RESET;
1362 aha_outb(aha, CONTROL_REG, reset_type);
1363
1364 /* Wait 5sec. for Diagnostic start */
1365 timeout = 5 * 10000;
1366 while (--timeout) {
1367 status = aha_inb(aha, STATUS_REG);
1368 if ((status & DIAG_ACTIVE) != 0)
1369 break;
1370 DELAY(100);
1371 }
1372 if (timeout == 0) {
316 return (ENXIO);
317 }
318 aha->fw_major = board_id.firmware_rev_major;
319 aha->fw_minor = board_id.firmware_rev_minor;
320 aha->boardid = board_id.board_type;
321
322 /*
323 * The Buslogic cards have an id of either 0x41 or 0x42. So
324 * if those come up in the probe, we test the geometry register
325 * of the board. Adaptec boards that are this old will not have
326 * this register, and return 0xff, while buslogic cards will return
327 * something different.
328 *
329 * XXX I'm not sure how this will impact other cloned cards.
330 */
331 if (aha->boardid <= 0x42) {
332 status = aha_inb(aha, GEOMETRY_REG);
333 if (status != 0xff)
334 return (ENXIO);
335 }
336
337 return (0);
338}
339
340/*
341 * Pull the boards setup information and record it in our softc.
342 */
343int
344aha_fetch_adapter_info(struct aha_softc *aha)
345{
346 setup_data_t setup_info;
347 config_data_t config_data;
348 u_int8_t length_param;
349 int error;
350 struct aha_extbios extbios;
351
352 switch (aha->boardid) {
353 case BOARD_1540_16HEAD_BIOS:
354 strcpy(aha->model, "1540 16 head BIOS");
355 break;
356 case BOARD_1540_64HEAD_BIOS:
357 strcpy(aha->model, "1540 64 head BIOS");
358 break;
359 case BOARD_1542:
360 strcpy(aha->model, "1540/1542 64 head BIOS");
361 break;
362 case BOARD_1640:
363 strcpy(aha->model, "1640");
364 break;
365 case BOARD_1740:
366 strcpy(aha->model, "1740A/1742A/1744");
367 break;
368 case BOARD_1542C:
369 strcpy(aha->model, "1542C");
370 break;
371 case BOARD_1542CF:
372 strcpy(aha->model, "1542CF");
373 break;
374 case BOARD_1542CP:
375 strcpy(aha->model, "1542CP");
376 break;
377 default:
378 strcpy(aha->model, "Unknown");
379 break;
380 }
381 /*
382 * If we are a new type of 1542 board (anything newer than a 1542C)
383 * then disable the extended bios so that the
384 * mailbox interface is unlocked.
385 * This is also true for the 1542B Version 3.20. First Adaptec
386 * board that supports >1Gb drives.
387 * No need to check the extended bios flags as some of the
388 * extensions that cause us problems are not flagged in that byte.
389 */
390 if (PROBABLY_NEW_BOARD(aha->boardid) ||
391 (aha->boardid == 0x41
392 && aha->fw_major == 0x31 &&
393 aha->fw_minor >= 0x34)) {
394 error = aha_cmd(aha, BOP_RETURN_EXT_BIOS_INFO, NULL,
395 /*paramlen*/0, (u_char *)&extbios, sizeof(extbios),
396 DEFAULT_CMD_TIMEOUT);
397 error = aha_cmd(aha, BOP_MBOX_IF_ENABLE, (u_int8_t *)&extbios,
398 /*paramlen*/2, NULL, 0, DEFAULT_CMD_TIMEOUT);
399 }
400 if (aha->boardid < 0x41)
401 printf("%s: Likely aha 1542A, which might not work properly\n",
402 aha_name(aha));
403
404 aha->max_sg = 17;
405 aha->diff_bus = 0;
406 aha->extended_lun = 0;
407 aha->extended_trans = 0;
408 aha->max_ccbs = 17; /* Need 17 to do 64k I/O */
409 /* Determine Sync/Wide/Disc settings */
410 length_param = sizeof(setup_info);
411 error = aha_cmd(aha, BOP_INQUIRE_SETUP_INFO, &length_param,
412 /*paramlen*/1, (u_int8_t*)&setup_info,
413 sizeof(setup_info), DEFAULT_CMD_TIMEOUT);
414 if (error != 0) {
415 printf("%s: aha_fetch_adapter_info - Failed "
416 "Get Setup Info\n", aha_name(aha));
417 return (error);
418 }
419 if (setup_info.initiate_sync != 0) {
420 aha->sync_permitted = ALL_TARGETS;
421 }
422 aha->disc_permitted = ALL_TARGETS;
423
424 /* We need as many mailboxes as we can have ccbs */
425 aha->num_boxes = aha->max_ccbs;
426
427 /* Determine our SCSI ID */
428
429 error = aha_cmd(aha, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
430 (u_int8_t*)&config_data, sizeof(config_data),
431 DEFAULT_CMD_TIMEOUT);
432 if (error != 0) {
433 printf("%s: aha_fetch_adapter_info - Failed Get Config\n",
434 aha_name(aha));
435 return (error);
436 }
437 aha->scsi_id = config_data.scsi_id;
438 return (0);
439}
440
441/*
442 * Start the board, ready for normal operation
443 */
444int
445aha_init(struct aha_softc* aha)
446{
447 /* Announce the Adapter */
448 printf("%s: AHA-%s FW Rev. %c.%c (ID=%x) ", aha_name(aha),
449 aha->model, aha->fw_major, aha->fw_minor, aha->boardid);
450
451 if (aha->diff_bus != 0)
452 printf("Diff ");
453
454 printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", aha->scsi_id,
455 aha->max_ccbs);
456
457 /*
458 * Create our DMA tags. These tags define the kinds of device
459 * accessable memory allocations and memory mappings we will
460 * need to perform during normal operation.
461 *
462 * Unless we need to further restrict the allocation, we rely
463 * on the restrictions of the parent dmat, hence the common
464 * use of MAXADDR and MAXSIZE.
465 */
466
467 /* DMA tag for mapping buffers into device visible space. */
468 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0,
469 /*lowaddr*/BUS_SPACE_MAXADDR,
470 /*highaddr*/BUS_SPACE_MAXADDR,
471 /*filter*/NULL, /*filterarg*/NULL,
472 /*maxsize*/MAXBSIZE, /*nsegments*/AHA_NSEG,
473 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
474 /*flags*/BUS_DMA_ALLOCNOW,
475 &aha->buffer_dmat) != 0) {
476 goto error_exit;
477 }
478
479 aha->init_level++;
480 /* DMA tag for our mailboxes */
481 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0,
482 /*lowaddr*/BUS_SPACE_MAXADDR,
483 /*highaddr*/BUS_SPACE_MAXADDR,
484 /*filter*/NULL, /*filterarg*/NULL,
485 aha->num_boxes * (sizeof(aha_mbox_in_t)
486 + sizeof(aha_mbox_out_t)),
487 /*nsegments*/1,
488 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
489 /*flags*/0, &aha->mailbox_dmat) != 0) {
490 goto error_exit;
491 }
492
493 aha->init_level++;
494
495 /* Allocation for our mailboxes */
496 if (bus_dmamem_alloc(aha->mailbox_dmat, (void **)&aha->out_boxes,
497 BUS_DMA_NOWAIT, &aha->mailbox_dmamap) != 0) {
498 goto error_exit;
499 }
500
501 aha->init_level++;
502
503 /* And permanently map them */
504 bus_dmamap_load(aha->mailbox_dmat, aha->mailbox_dmamap,
505 aha->out_boxes,
506 aha->num_boxes * (sizeof(aha_mbox_in_t)
507 + sizeof(aha_mbox_out_t)),
508 ahamapmboxes, aha, /*flags*/0);
509
510 aha->init_level++;
511
512 aha->in_boxes = (aha_mbox_in_t *)&aha->out_boxes[aha->num_boxes];
513
514 ahainitmboxes(aha);
515
516 /* DMA tag for our ccb structures */
517 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0,
518 /*lowaddr*/BUS_SPACE_MAXADDR,
519 /*highaddr*/BUS_SPACE_MAXADDR,
520 /*filter*/NULL, /*filterarg*/NULL,
521 aha->max_ccbs * sizeof(struct aha_ccb),
522 /*nsegments*/1,
523 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
524 /*flags*/0, &aha->ccb_dmat) != 0) {
525 goto error_exit;
526 }
527
528 aha->init_level++;
529
530 /* Allocation for our ccbs */
531 if (bus_dmamem_alloc(aha->ccb_dmat, (void **)&aha->aha_ccb_array,
532 BUS_DMA_NOWAIT, &aha->ccb_dmamap) != 0) {
533 goto error_exit;
534 }
535
536 aha->init_level++;
537
538 /* And permanently map them */
539 bus_dmamap_load(aha->ccb_dmat, aha->ccb_dmamap,
540 aha->aha_ccb_array,
541 aha->max_ccbs * sizeof(struct aha_ccb),
542 ahamapccbs, aha, /*flags*/0);
543
544 aha->init_level++;
545
546 /* DMA tag for our S/G structures. We allocate in page sized chunks */
547 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0,
548 /*lowaddr*/BUS_SPACE_MAXADDR,
549 /*highaddr*/BUS_SPACE_MAXADDR,
550 /*filter*/NULL, /*filterarg*/NULL,
551 PAGE_SIZE, /*nsegments*/1,
552 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
553 /*flags*/0, &aha->sg_dmat) != 0) {
554 goto error_exit;
555 }
556
557 aha->init_level++;
558
559 /* Perform initial CCB allocation */
560 bzero(aha->aha_ccb_array, aha->max_ccbs * sizeof(struct aha_ccb));
561 ahaallocccbs(aha);
562
563 if (aha->num_ccbs == 0) {
564 printf("%s: aha_init - Unable to allocate initial ccbs\n",
565 aha_name(aha));
566 goto error_exit;
567 }
568
569 /*
570 * Note that we are going and return (to probe)
571 */
572 return 0;
573
574error_exit:
575
576 return (ENXIO);
577}
578
579int
580aha_attach(struct aha_softc *aha)
581{
582 int tagged_dev_openings;
583 struct cam_devq *devq;
584
585 /*
586 * We reserve 1 ccb for error recovery, so don't
587 * tell the XPT about it.
588 */
589 tagged_dev_openings = 0;
590
591 /*
592 * Create the device queue for our SIM.
593 */
594 devq = cam_simq_alloc(aha->max_ccbs - 1);
595 if (devq == NULL)
596 return (ENOMEM);
597
598 /*
599 * Construct our SIM entry
600 */
601 aha->sim = cam_sim_alloc(ahaaction, ahapoll, "aha", aha, aha->unit,
602 2, tagged_dev_openings, devq);
603 if (aha->sim == NULL) {
604 cam_simq_free(devq);
605 return (ENOMEM);
606 }
607
608 if (xpt_bus_register(aha->sim, 0) != CAM_SUCCESS) {
609 cam_sim_free(aha->sim, /*free_devq*/TRUE);
610 return (ENXIO);
611 }
612
613 if (xpt_create_path(&aha->path, /*periph*/NULL,
614 cam_sim_path(aha->sim), CAM_TARGET_WILDCARD,
615 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
616 xpt_bus_deregister(cam_sim_path(aha->sim));
617 cam_sim_free(aha->sim, /*free_devq*/TRUE);
618 return (ENXIO);
619 }
620
621 return (0);
622}
623
624char *
625aha_name(struct aha_softc *aha)
626{
627 static char name[10];
628
629 sprintf(name, "aha%d", aha->unit);
630 return (name);
631}
632
633int
634aha_check_probed_iop(u_int ioport)
635{
636 u_int i;
637
638 for (i=0; i < AHA_NUM_ISAPORTS; i++) {
639 if (aha_isa_ports[i].addr == ioport) {
640 if (aha_isa_ports[i].probed != 0)
641 return (1);
642 else {
643 return (0);
644 }
645 }
646 }
647 return (1);
648}
649
650void
651aha_mark_probed_bio(isa_compat_io_t port)
652{
653 if (port < BIO_DISABLED)
654 aha_isa_ports[port].probed = 1;
655}
656
657void
658aha_mark_probed_iop(u_int ioport)
659{
660 u_int i;
661
662 for (i = 0; i < AHA_NUM_ISAPORTS; i++) {
663 if (ioport == aha_isa_ports[i].addr) {
664 aha_isa_ports[i].probed = 1;
665 break;
666 }
667 }
668}
669
670static void
671ahaallocccbs(struct aha_softc *aha)
672{
673 struct aha_ccb *next_ccb;
674 struct sg_map_node *sg_map;
675 bus_addr_t physaddr;
676 aha_sg_t *segs;
677 int newcount;
678 int i;
679
680 next_ccb = &aha->aha_ccb_array[aha->num_ccbs];
681
682 sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
683
684 if (sg_map == NULL)
685 return;
686
687 /* Allocate S/G space for the next batch of CCBS */
688 if (bus_dmamem_alloc(aha->sg_dmat, (void **)&sg_map->sg_vaddr,
689 BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {
690 free(sg_map, M_DEVBUF);
691 return;
692 }
693
694 SLIST_INSERT_HEAD(&aha->sg_maps, sg_map, links);
695
696 bus_dmamap_load(aha->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr,
697 PAGE_SIZE, ahamapsgs, aha, /*flags*/0);
698
699 segs = sg_map->sg_vaddr;
700 physaddr = sg_map->sg_physaddr;
701
702 newcount = (PAGE_SIZE / (AHA_NSEG * sizeof(aha_sg_t)));
703 for (i = 0; aha->num_ccbs < aha->max_ccbs && i < newcount; i++) {
704 int error;
705
706 next_ccb->sg_list = segs;
707 next_ccb->sg_list_phys = physaddr;
708 next_ccb->flags = BCCB_FREE;
709 error = bus_dmamap_create(aha->buffer_dmat, /*flags*/0,
710 &next_ccb->dmamap);
711 if (error != 0)
712 break;
713 SLIST_INSERT_HEAD(&aha->free_aha_ccbs, next_ccb, links);
714 segs += AHA_NSEG;
715 physaddr += (AHA_NSEG * sizeof(aha_sg_t));
716 next_ccb++;
717 aha->num_ccbs++;
718 }
719
720 /* Reserve a CCB for error recovery */
721 if (aha->recovery_bccb == NULL) {
722 aha->recovery_bccb = SLIST_FIRST(&aha->free_aha_ccbs);
723 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
724 }
725}
726
727static __inline void
728ahafreeccb(struct aha_softc *aha, struct aha_ccb *bccb)
729{
730 int s;
731
732 s = splcam();
733 if ((bccb->flags & BCCB_ACTIVE) != 0)
734 LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le);
735 if (aha->resource_shortage != 0
736 && (bccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
737 bccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
738 aha->resource_shortage = FALSE;
739 }
740 bccb->flags = BCCB_FREE;
741 SLIST_INSERT_HEAD(&aha->free_aha_ccbs, bccb, links);
742 splx(s);
743}
744
745static struct aha_ccb*
746ahagetccb(struct aha_softc *aha)
747{
748 struct aha_ccb* bccb;
749 int s;
750
751 s = splcam();
752 if ((bccb = SLIST_FIRST(&aha->free_aha_ccbs)) != NULL) {
753 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
754 } else if (aha->num_ccbs < aha->max_ccbs) {
755 ahaallocccbs(aha);
756 bccb = SLIST_FIRST(&aha->free_aha_ccbs);
757 if (bccb == NULL)
758 printf("%s: Can't malloc BCCB\n", aha_name(aha));
759 else
760 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
761 }
762 splx(s);
763
764 return (bccb);
765}
766
767static void
768ahaaction(struct cam_sim *sim, union ccb *ccb)
769{
770 struct aha_softc *aha;
771 int s;
772
773 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahaaction\n"));
774
775 aha = (struct aha_softc *)cam_sim_softc(sim);
776
777 switch (ccb->ccb_h.func_code) {
778 /* Common cases first */
779 case XPT_SCSI_IO: /* Execute the requested I/O operation */
780 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
781 {
782 struct aha_ccb *bccb;
783 struct aha_hccb *hccb;
784
785 /*
786 * get a bccb to use.
787 */
788 if ((bccb = ahagetccb(aha)) == NULL) {
789 int s;
790
791 s = splcam();
792 aha->resource_shortage = TRUE;
793 splx(s);
794 xpt_freeze_simq(aha->sim, /*count*/1);
795 ccb->ccb_h.status = CAM_REQUEUE_REQ;
796 xpt_done(ccb);
797 return;
798 }
799
800 hccb = &bccb->hccb;
801
802 /*
803 * So we can find the BCCB when an abort is requested
804 */
805 bccb->ccb = ccb;
806 ccb->ccb_h.ccb_bccb_ptr = bccb;
807 ccb->ccb_h.ccb_aha_ptr = aha;
808
809 /*
810 * Put all the arguments for the xfer in the bccb
811 */
812 hccb->target = ccb->ccb_h.target_id;
813 hccb->lun = ccb->ccb_h.target_lun;
814 hccb->ahastat = 0;
815 hccb->sdstat = 0;
816
817 if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
818 struct ccb_scsiio *csio;
819 struct ccb_hdr *ccbh;
820
821 csio = &ccb->csio;
822 ccbh = &csio->ccb_h;
823 hccb->opcode = INITIATOR_CCB_WRESID;
824 hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) != 0;
825 hccb->dataout = (ccb->ccb_h.flags & CAM_DIR_OUT) != 0;
826 hccb->cmd_len = csio->cdb_len;
827 if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) {
828 ccb->ccb_h.status = CAM_REQ_INVALID;
829 ahafreeccb(aha, bccb);
830 xpt_done(ccb);
831 return;
832 }
833 hccb->sense_len = csio->sense_len;
834 if ((ccbh->flags & CAM_CDB_POINTER) != 0) {
835 if ((ccbh->flags & CAM_CDB_PHYS) == 0) {
836 bcopy(csio->cdb_io.cdb_ptr,
837 hccb->scsi_cdb, hccb->cmd_len);
838 } else {
839 /* I guess I could map it in... */
840 ccbh->status = CAM_REQ_INVALID;
841 ahafreeccb(aha, bccb);
842 xpt_done(ccb);
843 return;
844 }
845 } else {
846 bcopy(csio->cdb_io.cdb_bytes,
847 hccb->scsi_cdb, hccb->cmd_len);
848 }
849 /*
850 * If we have any data to send with this command,
851 * map it into bus space.
852 */
853 /* Only use S/G if there is a transfer */
854 if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
855 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) {
856 /*
857 * We've been given a pointer
858 * to a single buffer.
859 */
860 if ((ccbh->flags & CAM_DATA_PHYS)==0) {
861 int s;
862 int error;
863
864 s = splsoftvm();
865 error = bus_dmamap_load(
866 aha->buffer_dmat,
867 bccb->dmamap,
868 csio->data_ptr,
869 csio->dxfer_len,
870 ahaexecuteccb,
871 bccb,
872 /*flags*/0);
873 if (error == EINPROGRESS) {
874 /*
875 * So as to maintain
876 * ordering, freeze the
877 * controller queue
878 * until our mapping is
879 * returned.
880 */
881 xpt_freeze_simq(aha->sim,
882 1);
883 csio->ccb_h.status |=
884 CAM_RELEASE_SIMQ;
885 }
886 splx(s);
887 } else {
888 struct bus_dma_segment seg;
889
890 /* Pointer to physical buffer */
891 seg.ds_addr =
892 (bus_addr_t)csio->data_ptr;
893 seg.ds_len = csio->dxfer_len;
894 ahaexecuteccb(bccb, &seg, 1, 0);
895 }
896 } else {
897 struct bus_dma_segment *segs;
898
899 if ((ccbh->flags & CAM_DATA_PHYS) != 0)
900 panic("ahaaction - Physical "
901 "segment pointers "
902 "unsupported");
903
904 if ((ccbh->flags&CAM_SG_LIST_PHYS)==0)
905 panic("ahaaction - Virtual "
906 "segment addresses "
907 "unsupported");
908
909 /* Just use the segments provided */
910 segs = (struct bus_dma_segment *)
911 csio->data_ptr;
912 ahaexecuteccb(bccb, segs,
913 csio->sglist_cnt, 0);
914 }
915 } else {
916 ahaexecuteccb(bccb, NULL, 0, 0);
917 }
918 } else {
919 hccb->opcode = INITIATOR_BUS_DEV_RESET;
920 /* No data transfer */
921 hccb->datain = TRUE;
922 hccb->dataout = TRUE;
923 hccb->cmd_len = 0;
924 hccb->sense_len = 0;
925 ahaexecuteccb(bccb, NULL, 0, 0);
926 }
927 break;
928 }
929 case XPT_EN_LUN: /* Enable LUN as a target */
930 case XPT_TARGET_IO: /* Execute target I/O request */
931 case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
932 case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/
933 case XPT_ABORT: /* Abort the specified CCB */
934 /* XXX Implement */
935 ccb->ccb_h.status = CAM_REQ_INVALID;
936 xpt_done(ccb);
937 break;
938 case XPT_SET_TRAN_SETTINGS:
939 {
940 /* XXX Implement */
941 ccb->ccb_h.status = CAM_REQ_CMP;
942 xpt_done(ccb);
943 break;
944 }
945 case XPT_GET_TRAN_SETTINGS:
946 /* Get default/user set transfer settings for the target */
947 {
948 struct ccb_trans_settings *cts;
949 u_int target_mask;
950
951 cts = &ccb->cts;
952 target_mask = 0x01 << ccb->ccb_h.target_id;
953 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
954 cts->flags = 0;
955 if ((aha->disc_permitted & target_mask) != 0)
956 cts->flags |= CCB_TRANS_DISC_ENB;
957 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
958 if ((aha->sync_permitted & target_mask) != 0)
959 cts->sync_period = 50;
960 else
961 cts->sync_period = 0;
962
963 if (cts->sync_period != 0)
964 cts->sync_offset = 15;
965
966 cts->valid = CCB_TRANS_SYNC_RATE_VALID
967 | CCB_TRANS_SYNC_OFFSET_VALID
968 | CCB_TRANS_BUS_WIDTH_VALID
969 | CCB_TRANS_DISC_VALID
970 | CCB_TRANS_TQ_VALID;
971 } else {
972 ahafetchtransinfo(aha, cts);
973 }
974
975 ccb->ccb_h.status = CAM_REQ_CMP;
976 xpt_done(ccb);
977 break;
978 }
979 case XPT_CALC_GEOMETRY:
980 {
981 struct ccb_calc_geometry *ccg;
982 u_int32_t size_mb;
983 u_int32_t secs_per_cylinder;
984
985 ccg = &ccb->ccg;
986 size_mb = ccg->volume_size
987 / ((1024L * 1024L) / ccg->block_size);
988
989 if (size_mb >= 1024 && (aha->extended_trans != 0)) {
990 if (size_mb >= 2048) {
991 ccg->heads = 255;
992 ccg->secs_per_track = 63;
993 } else {
994 ccg->heads = 128;
995 ccg->secs_per_track = 32;
996 }
997 } else {
998 ccg->heads = 64;
999 ccg->secs_per_track = 32;
1000 }
1001 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
1002 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
1003 ccb->ccb_h.status = CAM_REQ_CMP;
1004 xpt_done(ccb);
1005 break;
1006 }
1007 case XPT_RESET_BUS: /* Reset the specified SCSI bus */
1008 {
1009 ahareset(aha, /*hardreset*/TRUE);
1010 ccb->ccb_h.status = CAM_REQ_CMP;
1011 xpt_done(ccb);
1012 break;
1013 }
1014 case XPT_TERM_IO: /* Terminate the I/O process */
1015 /* XXX Implement */
1016 ccb->ccb_h.status = CAM_REQ_INVALID;
1017 xpt_done(ccb);
1018 break;
1019 case XPT_PATH_INQ: /* Path routing inquiry */
1020 {
1021 struct ccb_pathinq *cpi = &ccb->cpi;
1022
1023 cpi->version_num = 1; /* XXX??? */
1024 cpi->hba_inquiry = PI_SDTR_ABLE;
1025 cpi->target_sprt = 0;
1026 cpi->hba_misc = 0;
1027 cpi->hba_eng_cnt = 0;
1028 cpi->max_target = 7;
1029 cpi->max_lun = 7;
1030 cpi->initiator_id = aha->scsi_id;
1031 cpi->bus_id = cam_sim_bus(sim);
1032 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1033 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
1034 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1035 cpi->unit_number = cam_sim_unit(sim);
1036 cpi->ccb_h.status = CAM_REQ_CMP;
1037 xpt_done(ccb);
1038 break;
1039 }
1040 default:
1041 ccb->ccb_h.status = CAM_REQ_INVALID;
1042 xpt_done(ccb);
1043 break;
1044 }
1045}
1046
1047static void
1048ahaexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
1049{
1050 struct aha_ccb *bccb;
1051 union ccb *ccb;
1052 struct aha_softc *aha;
1053 int s, i;
1054 u_int32_t paddr;
1055
1056 bccb = (struct aha_ccb *)arg;
1057 ccb = bccb->ccb;
1058 aha = (struct aha_softc *)ccb->ccb_h.ccb_aha_ptr;
1059
1060 if (error != 0) {
1061 if (error != EFBIG)
1062 printf("%s: Unexepected error 0x%x returned from "
1063 "bus_dmamap_load\n", aha_name(aha), error);
1064 if (ccb->ccb_h.status == CAM_REQ_INPROG) {
1065 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
1066 ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
1067 }
1068 ahafreeccb(aha, bccb);
1069 xpt_done(ccb);
1070 return;
1071 }
1072
1073 if (nseg != 0) {
1074 aha_sg_t *sg;
1075 bus_dma_segment_t *end_seg;
1076 bus_dmasync_op_t op;
1077
1078 end_seg = dm_segs + nseg;
1079
1080 /* Copy the segments into our SG list */
1081 sg = bccb->sg_list;
1082 while (dm_segs < end_seg) {
1083 ahautoa24(dm_segs->ds_len, sg->len);
1084 ahautoa24(dm_segs->ds_addr, sg->addr);
1085 sg++;
1086 dm_segs++;
1087 }
1088
1089 if (nseg > 1) {
1090 bccb->hccb.opcode = INITIATOR_SG_CCB_WRESID;
1091 ahautoa24((sizeof(aha_sg_t) * nseg),
1092 bccb->hccb.data_len);
1093 ahautoa24(bccb->sg_list_phys, bccb->hccb.data_addr);
1094 } else {
1095 bcopy(bccb->sg_list->len, bccb->hccb.data_len, 3);
1096 bcopy(bccb->sg_list->addr, bccb->hccb.data_addr, 3);
1097 }
1098
1099 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1100 op = BUS_DMASYNC_PREREAD;
1101 else
1102 op = BUS_DMASYNC_PREWRITE;
1103
1104 bus_dmamap_sync(aha->buffer_dmat, bccb->dmamap, op);
1105
1106 } else {
1107 bccb->hccb.opcode = INITIATOR_CCB_WRESID;
1108 ahautoa24(0, bccb->hccb.data_len);
1109 ahautoa24(0, bccb->hccb.data_addr);
1110 }
1111
1112 s = splcam();
1113
1114 /*
1115 * Last time we need to check if this CCB needs to
1116 * be aborted.
1117 */
1118 if (ccb->ccb_h.status != CAM_REQ_INPROG) {
1119 if (nseg != 0)
1120 bus_dmamap_unload(aha->buffer_dmat, bccb->dmamap);
1121 ahafreeccb(aha, bccb);
1122 xpt_done(ccb);
1123 splx(s);
1124 return;
1125 }
1126
1127 bccb->flags = BCCB_ACTIVE;
1128 ccb->ccb_h.status |= CAM_SIM_QUEUED;
1129 LIST_INSERT_HEAD(&aha->pending_ccbs, &ccb->ccb_h, sim_links.le);
1130
1131 ccb->ccb_h.timeout_ch =
1132 timeout(ahatimeout, (caddr_t)bccb,
1133 (ccb->ccb_h.timeout * hz) / 1000);
1134
1135 /* Tell the adapter about this command */
1136 paddr = ahaccbvtop(aha, bccb);
1137 ahautoa24(paddr, aha->cur_outbox->ccb_addr);
1138 if (aha->cur_outbox->action_code != BMBO_FREE)
1139 panic("%s: Too few mailboxes or to many ccbs???", aha_name(aha));
1140 aha->cur_outbox->action_code = BMBO_START;
1141 aha_outb(aha, COMMAND_REG, BOP_START_MBOX);
1142
1143 ahanextoutbox(aha);
1144 splx(s);
1145}
1146
1147void
1148aha_intr(void *arg)
1149{
1150 struct aha_softc *aha;
1151 u_int intstat;
1152
1153 aha = (struct aha_softc *)arg;
1154 while (((intstat = aha_inb(aha, INTSTAT_REG)) & INTR_PENDING) != 0) {
1155 if ((intstat & CMD_COMPLETE) != 0) {
1156 aha->latched_status = aha_inb(aha, STATUS_REG);
1157 aha->command_cmp = TRUE;
1158 }
1159
1160 aha_outb(aha, CONTROL_REG, RESET_INTR);
1161
1162 if ((intstat & IMB_LOADED) != 0) {
1163 while (aha->cur_inbox->comp_code != BMBI_FREE) {
1164 u_int32_t paddr;
1165 paddr = aha_a24tou(aha->cur_inbox->ccb_addr);
1166 ahadone(aha,
1167 ahaccbptov(aha, paddr),
1168 aha->cur_inbox->comp_code);
1169 aha->cur_inbox->comp_code = BMBI_FREE;
1170 ahanextinbox(aha);
1171 }
1172 }
1173
1174 if ((intstat & SCSI_BUS_RESET) != 0) {
1175 ahareset(aha, /*hardreset*/FALSE);
1176 }
1177 }
1178}
1179
1180static void
1181ahadone(struct aha_softc *aha, struct aha_ccb *bccb, aha_mbi_comp_code_t comp_code)
1182{
1183 union ccb *ccb;
1184 struct ccb_scsiio *csio;
1185
1186 ccb = bccb->ccb;
1187 csio = &bccb->ccb->csio;
1188
1189 if ((bccb->flags & BCCB_ACTIVE) == 0) {
1190 printf("%s: ahadone - Attempt to free non-active BCCB %p\n",
1191 aha_name(aha), (void *)bccb);
1192 return;
1193 }
1194
1195 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1196 bus_dmasync_op_t op;
1197
1198 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1199 op = BUS_DMASYNC_POSTREAD;
1200 else
1201 op = BUS_DMASYNC_POSTWRITE;
1202 bus_dmamap_sync(aha->buffer_dmat, bccb->dmamap, op);
1203 bus_dmamap_unload(aha->buffer_dmat, bccb->dmamap);
1204 }
1205
1206 if (bccb == aha->recovery_bccb) {
1207 /*
1208 * The recovery BCCB does not have a CCB associated
1209 * with it, so short circuit the normal error handling.
1210 * We now traverse our list of pending CCBs and process
1211 * any that were terminated by the recovery CCBs action.
1212 * We also reinstate timeouts for all remaining, pending,
1213 * CCBs.
1214 */
1215 struct cam_path *path;
1216 struct ccb_hdr *ccb_h;
1217 cam_status error;
1218
1219 /* Notify all clients that a BDR occured */
1220 error = xpt_create_path(&path, /*periph*/NULL,
1221 cam_sim_path(aha->sim),
1222 bccb->hccb.target,
1223 CAM_LUN_WILDCARD);
1224
1225 if (error == CAM_REQ_CMP)
1226 xpt_async(AC_SENT_BDR, path, NULL);
1227
1228 ccb_h = LIST_FIRST(&aha->pending_ccbs);
1229 while (ccb_h != NULL) {
1230 struct aha_ccb *pending_bccb;
1231
1232 pending_bccb = (struct aha_ccb *)ccb_h->ccb_bccb_ptr;
1233 if (pending_bccb->hccb.target == bccb->hccb.target) {
1234 pending_bccb->hccb.ahastat = AHASTAT_HA_BDR;
1235 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1236 ahadone(aha, pending_bccb, BMBI_ERROR);
1237 } else {
1238 ccb_h->timeout_ch =
1239 timeout(ahatimeout, (caddr_t)pending_bccb,
1240 (ccb_h->timeout * hz) / 1000);
1241 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1242 }
1243 }
1244 printf("%s: No longer in timeout\n", aha_name(aha));
1245 return;
1246 }
1247
1248 untimeout(ahatimeout, bccb, ccb->ccb_h.timeout_ch);
1249
1250 switch (comp_code) {
1251 case BMBI_FREE:
1252 printf("%s: ahadone - CCB completed with free status!\n",
1253 aha_name(aha));
1254 break;
1255 case BMBI_NOT_FOUND:
1256 printf("%s: ahadone - CCB Abort failed to find CCB\n",
1257 aha_name(aha));
1258 break;
1259 case BMBI_ABORT:
1260 case BMBI_ERROR:
1261 /* An error occured */
1262 switch(bccb->hccb.ahastat) {
1263 case AHASTAT_DATARUN_ERROR:
1264 if (bccb->hccb.data_len <= 0) {
1265 csio->ccb_h.status = CAM_DATA_RUN_ERR;
1266 break;
1267 }
1268 /* FALLTHROUGH */
1269 case AHASTAT_NOERROR:
1270 csio->scsi_status = bccb->hccb.sdstat;
1271 csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
1272 switch(csio->scsi_status) {
1273 case SCSI_STATUS_CHECK_COND:
1274 case SCSI_STATUS_CMD_TERMINATED:
1275 csio->ccb_h.status |= CAM_AUTOSNS_VALID;
1276 /*
1277 * The aha writes the sense data at different
1278 * offsets based on the scsi cmd len
1279 */
1280 bcopy((caddr_t) &bccb->hccb.scsi_cdb +
1281 bccb->hccb.cmd_len,
1282 (caddr_t) &csio->sense_data,
1283 bccb->hccb.sense_len);
1284 break;
1285 default:
1286 break;
1287 case SCSI_STATUS_OK:
1288 csio->ccb_h.status = CAM_REQ_CMP;
1289 break;
1290 }
1291 csio->resid = aha_a24tou(bccb->hccb.data_len);
1292 break;
1293 case AHASTAT_SELTIMEOUT:
1294 csio->ccb_h.status = CAM_SEL_TIMEOUT;
1295 break;
1296 case AHASTAT_UNEXPECTED_BUSFREE:
1297 csio->ccb_h.status = CAM_UNEXP_BUSFREE;
1298 break;
1299 case AHASTAT_INVALID_PHASE:
1300 csio->ccb_h.status = CAM_SEQUENCE_FAIL;
1301 break;
1302 case AHASTAT_INVALID_ACTION_CODE:
1303 panic("%s: Inavlid Action code", aha_name(aha));
1304 break;
1305 case AHASTAT_INVALID_OPCODE:
1306 panic("%s: Inavlid CCB Opcode code %x hccb = %p",
1307 aha_name(aha), bccb->hccb.opcode, &bccb->hccb);
1308 break;
1309 case AHASTAT_LINKED_CCB_LUN_MISMATCH:
1310 /* We don't even support linked commands... */
1311 panic("%s: Linked CCB Lun Mismatch", aha_name(aha));
1312 break;
1313 case AHASTAT_INVALID_CCB_OR_SG_PARAM:
1314 panic("%s: Invalid CCB or SG list", aha_name(aha));
1315 break;
1316 case AHASTAT_HA_SCSI_BUS_RESET:
1317 if ((csio->ccb_h.status & CAM_STATUS_MASK)
1318 != CAM_CMD_TIMEOUT)
1319 csio->ccb_h.status = CAM_SCSI_BUS_RESET;
1320 break;
1321 case AHASTAT_HA_BDR:
1322 if ((bccb->flags & BCCB_DEVICE_RESET) == 0)
1323 csio->ccb_h.status = CAM_BDR_SENT;
1324 else
1325 csio->ccb_h.status = CAM_CMD_TIMEOUT;
1326 break;
1327 }
1328 if (csio->ccb_h.status != CAM_REQ_CMP) {
1329 xpt_freeze_devq(csio->ccb_h.path, /*count*/1);
1330 csio->ccb_h.status |= CAM_DEV_QFRZN;
1331 }
1332 if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0)
1333 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1334 ahafreeccb(aha, bccb);
1335 xpt_done(ccb);
1336 break;
1337 case BMBI_OK:
1338 /* All completed without incident */
1339 /* XXX DO WE NEED TO COPY SENSE BYTES HERE???? XXX */
1340 ccb->ccb_h.status |= CAM_REQ_CMP;
1341 if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0)
1342 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1343 ahafreeccb(aha, bccb);
1344 xpt_done(ccb);
1345 break;
1346 }
1347}
1348
1349static int
1350ahareset(struct aha_softc* aha, int hard_reset)
1351{
1352 struct ccb_hdr *ccb_h;
1353 u_int status;
1354 u_int timeout;
1355 u_int8_t reset_type;
1356
1357 if (hard_reset != 0)
1358 reset_type = HARD_RESET;
1359 else
1360 reset_type = SOFT_RESET;
1361 aha_outb(aha, CONTROL_REG, reset_type);
1362
1363 /* Wait 5sec. for Diagnostic start */
1364 timeout = 5 * 10000;
1365 while (--timeout) {
1366 status = aha_inb(aha, STATUS_REG);
1367 if ((status & DIAG_ACTIVE) != 0)
1368 break;
1369 DELAY(100);
1370 }
1371 if (timeout == 0) {
1373 if (bootverbose)
1374 printf("%s: ahareset - Diagnostic Active failed to "
1375 "assert. status = 0x%x\n", aha_name(aha),
1376 status);
1372 PRVERB(("%s: ahareset - Diagnostic Active failed to "
1373 "assert. status = 0x%x\n", aha_name(aha),
1374 status));
1377 return (ETIMEDOUT);
1378 }
1379
1380 /* Wait 10sec. for Diagnostic end */
1381 timeout = 10 * 10000;
1382 while (--timeout) {
1383 status = aha_inb(aha, STATUS_REG);
1384 if ((status & DIAG_ACTIVE) == 0)
1385 break;
1386 DELAY(100);
1387 }
1388 if (timeout == 0) {
1389 panic("%s: ahareset - Diagnostic Active failed to drop. "
1390 "status = 0x%x\n", aha_name(aha), status);
1391 return (ETIMEDOUT);
1392 }
1393
1394 /* Wait for the host adapter to become ready or report a failure */
1395 timeout = 10000;
1396 while (--timeout) {
1397 status = aha_inb(aha, STATUS_REG);
1398 if ((status & (DIAG_FAIL|HA_READY|DATAIN_REG_READY)) != 0)
1399 break;
1400 DELAY(100);
1401 }
1402 if (timeout == 0) {
1403 printf("%s: ahareset - Host adapter failed to come ready. "
1404 "status = 0x%x\n", aha_name(aha), status);
1405 return (ETIMEDOUT);
1406 }
1407
1408 /* If the diagnostics failed, tell the user */
1409 if ((status & DIAG_FAIL) != 0
1410 || (status & HA_READY) == 0) {
1411 printf("%s: ahareset - Adapter failed diagnostics\n",
1412 aha_name(aha));
1413
1414 if ((status & DATAIN_REG_READY) != 0)
1415 printf("%s: ahareset - Host Adapter Error "
1416 "code = 0x%x\n", aha_name(aha),
1417 aha_inb(aha, DATAIN_REG));
1418 return (ENXIO);
1419 }
1420
1421 /* If we've allocated mailboxes, initialize them */
1422 if (aha->init_level > 4)
1423 ahainitmboxes(aha);
1424
1425 /* If we've attached to the XPT, tell it about the event */
1426 if (aha->path != NULL)
1427 xpt_async(AC_BUS_RESET, aha->path, NULL);
1428
1429 /*
1430 * Perform completion processing for all outstanding CCBs.
1431 */
1432 while ((ccb_h = LIST_FIRST(&aha->pending_ccbs)) != NULL) {
1433 struct aha_ccb *pending_bccb;
1434
1435 pending_bccb = (struct aha_ccb *)ccb_h->ccb_bccb_ptr;
1436 pending_bccb->hccb.ahastat = AHASTAT_HA_SCSI_BUS_RESET;
1437 ahadone(aha, pending_bccb, BMBI_ERROR);
1438 }
1439
1440 return (0);
1441}
1442
1443/*
1444 * Send a command to the adapter.
1445 */
1446int
1447aha_cmd(struct aha_softc *aha, aha_op_t opcode, u_int8_t *params,
1448 u_int param_len, u_int8_t *reply_data, u_int reply_len,
1449 u_int cmd_timeout)
1450{
1451 u_int timeout;
1452 u_int status;
1453 u_int intstat;
1454 u_int reply_buf_size;
1455 int s;
1456
1457 /* No data returned to start */
1458 reply_buf_size = reply_len;
1459 reply_len = 0;
1460 intstat = 0;
1461
1462 aha->command_cmp = 0;
1463 /*
1464 * Wait up to 1 sec. for the adapter to become
1465 * ready to accept commands.
1466 */
1467 timeout = 10000;
1468 while (--timeout) {
1469
1470 status = aha_inb(aha, STATUS_REG);
1471 if ((status & HA_READY) != 0
1472 && (status & CMD_REG_BUSY) == 0)
1473 break;
1474 DELAY(100);
1475 }
1476 if (timeout == 0) {
1477 printf("%s: aha_cmd: Timeout waiting for adapter ready, "
1478 "status = 0x%x\n", aha_name(aha), status);
1479 return (ETIMEDOUT);
1480 }
1481
1482 /*
1483 * Send the opcode followed by any necessary parameter bytes.
1484 */
1485 aha_outb(aha, COMMAND_REG, opcode);
1486
1487 /*
1488 * Wait for up to 1sec to get the parameter list sent
1489 */
1490 timeout = 10000;
1491 while (param_len && --timeout) {
1492 DELAY(100);
1493 status = aha_inb(aha, STATUS_REG);
1494 intstat = aha_inb(aha, INTSTAT_REG);
1495 if ((intstat & (INTR_PENDING|CMD_COMPLETE))
1496 == (INTR_PENDING|CMD_COMPLETE))
1497 break;
1498 if (aha->command_cmp != 0) {
1499 status = aha->latched_status;
1500 break;
1501 }
1502 if ((status & DATAIN_REG_READY) != 0)
1503 break;
1504 if ((status & CMD_REG_BUSY) == 0) {
1505 aha_outb(aha, COMMAND_REG, *params++);
1506 param_len--;
1507 }
1508 }
1509 if (timeout == 0) {
1510 printf("%s: aha_cmd: Timeout sending parameters, "
1511 "status = 0x%x\n", aha_name(aha), status);
1512 return (ETIMEDOUT);
1513 }
1514
1515 /*
1516 * For all other commands, we wait for any output data
1517 * and the final comand completion interrupt.
1518 */
1519 while (--cmd_timeout) {
1520
1521 status = aha_inb(aha, STATUS_REG);
1522 intstat = aha_inb(aha, INTSTAT_REG);
1523 if ((intstat & (INTR_PENDING|CMD_COMPLETE))
1524 == (INTR_PENDING|CMD_COMPLETE))
1525 break;
1526
1527 if (aha->command_cmp != 0) {
1528 status = aha->latched_status;
1529 break;
1530 }
1531
1532 if ((status & DATAIN_REG_READY) != 0) {
1533 u_int8_t data;
1534
1535 data = aha_inb(aha, DATAIN_REG);
1536 if (reply_len < reply_buf_size) {
1537 *reply_data++ = data;
1538 } else {
1539 printf("%s: aha_cmd - Discarded reply data byte "
1540 "for opcode 0x%x\n", aha_name(aha),
1541 opcode);
1542 }
1543 reply_len++;
1544 }
1545
1546 DELAY(100);
1547 }
1548 if (timeout == 0) {
1549 printf("%s: aha_cmd: Timeout waiting for reply data and "
1550 "command complete.\n%s: status = 0x%x, intstat = 0x%x, "
1551 "reply_len = %d\n", aha_name(aha), aha_name(aha), status,
1552 intstat, reply_len);
1553 return (ETIMEDOUT);
1554 }
1555
1556 /*
1557 * Clear any pending interrupts. Block interrupts so our
1558 * interrupt handler is not re-entered.
1559 */
1560 s = splcam();
1561 aha_intr(aha);
1562 splx(s);
1563
1564 /*
1565 * If the command was rejected by the controller, tell the caller.
1566 */
1567 if ((status & CMD_INVALID) != 0) {
1375 return (ETIMEDOUT);
1376 }
1377
1378 /* Wait 10sec. for Diagnostic end */
1379 timeout = 10 * 10000;
1380 while (--timeout) {
1381 status = aha_inb(aha, STATUS_REG);
1382 if ((status & DIAG_ACTIVE) == 0)
1383 break;
1384 DELAY(100);
1385 }
1386 if (timeout == 0) {
1387 panic("%s: ahareset - Diagnostic Active failed to drop. "
1388 "status = 0x%x\n", aha_name(aha), status);
1389 return (ETIMEDOUT);
1390 }
1391
1392 /* Wait for the host adapter to become ready or report a failure */
1393 timeout = 10000;
1394 while (--timeout) {
1395 status = aha_inb(aha, STATUS_REG);
1396 if ((status & (DIAG_FAIL|HA_READY|DATAIN_REG_READY)) != 0)
1397 break;
1398 DELAY(100);
1399 }
1400 if (timeout == 0) {
1401 printf("%s: ahareset - Host adapter failed to come ready. "
1402 "status = 0x%x\n", aha_name(aha), status);
1403 return (ETIMEDOUT);
1404 }
1405
1406 /* If the diagnostics failed, tell the user */
1407 if ((status & DIAG_FAIL) != 0
1408 || (status & HA_READY) == 0) {
1409 printf("%s: ahareset - Adapter failed diagnostics\n",
1410 aha_name(aha));
1411
1412 if ((status & DATAIN_REG_READY) != 0)
1413 printf("%s: ahareset - Host Adapter Error "
1414 "code = 0x%x\n", aha_name(aha),
1415 aha_inb(aha, DATAIN_REG));
1416 return (ENXIO);
1417 }
1418
1419 /* If we've allocated mailboxes, initialize them */
1420 if (aha->init_level > 4)
1421 ahainitmboxes(aha);
1422
1423 /* If we've attached to the XPT, tell it about the event */
1424 if (aha->path != NULL)
1425 xpt_async(AC_BUS_RESET, aha->path, NULL);
1426
1427 /*
1428 * Perform completion processing for all outstanding CCBs.
1429 */
1430 while ((ccb_h = LIST_FIRST(&aha->pending_ccbs)) != NULL) {
1431 struct aha_ccb *pending_bccb;
1432
1433 pending_bccb = (struct aha_ccb *)ccb_h->ccb_bccb_ptr;
1434 pending_bccb->hccb.ahastat = AHASTAT_HA_SCSI_BUS_RESET;
1435 ahadone(aha, pending_bccb, BMBI_ERROR);
1436 }
1437
1438 return (0);
1439}
1440
1441/*
1442 * Send a command to the adapter.
1443 */
1444int
1445aha_cmd(struct aha_softc *aha, aha_op_t opcode, u_int8_t *params,
1446 u_int param_len, u_int8_t *reply_data, u_int reply_len,
1447 u_int cmd_timeout)
1448{
1449 u_int timeout;
1450 u_int status;
1451 u_int intstat;
1452 u_int reply_buf_size;
1453 int s;
1454
1455 /* No data returned to start */
1456 reply_buf_size = reply_len;
1457 reply_len = 0;
1458 intstat = 0;
1459
1460 aha->command_cmp = 0;
1461 /*
1462 * Wait up to 1 sec. for the adapter to become
1463 * ready to accept commands.
1464 */
1465 timeout = 10000;
1466 while (--timeout) {
1467
1468 status = aha_inb(aha, STATUS_REG);
1469 if ((status & HA_READY) != 0
1470 && (status & CMD_REG_BUSY) == 0)
1471 break;
1472 DELAY(100);
1473 }
1474 if (timeout == 0) {
1475 printf("%s: aha_cmd: Timeout waiting for adapter ready, "
1476 "status = 0x%x\n", aha_name(aha), status);
1477 return (ETIMEDOUT);
1478 }
1479
1480 /*
1481 * Send the opcode followed by any necessary parameter bytes.
1482 */
1483 aha_outb(aha, COMMAND_REG, opcode);
1484
1485 /*
1486 * Wait for up to 1sec to get the parameter list sent
1487 */
1488 timeout = 10000;
1489 while (param_len && --timeout) {
1490 DELAY(100);
1491 status = aha_inb(aha, STATUS_REG);
1492 intstat = aha_inb(aha, INTSTAT_REG);
1493 if ((intstat & (INTR_PENDING|CMD_COMPLETE))
1494 == (INTR_PENDING|CMD_COMPLETE))
1495 break;
1496 if (aha->command_cmp != 0) {
1497 status = aha->latched_status;
1498 break;
1499 }
1500 if ((status & DATAIN_REG_READY) != 0)
1501 break;
1502 if ((status & CMD_REG_BUSY) == 0) {
1503 aha_outb(aha, COMMAND_REG, *params++);
1504 param_len--;
1505 }
1506 }
1507 if (timeout == 0) {
1508 printf("%s: aha_cmd: Timeout sending parameters, "
1509 "status = 0x%x\n", aha_name(aha), status);
1510 return (ETIMEDOUT);
1511 }
1512
1513 /*
1514 * For all other commands, we wait for any output data
1515 * and the final comand completion interrupt.
1516 */
1517 while (--cmd_timeout) {
1518
1519 status = aha_inb(aha, STATUS_REG);
1520 intstat = aha_inb(aha, INTSTAT_REG);
1521 if ((intstat & (INTR_PENDING|CMD_COMPLETE))
1522 == (INTR_PENDING|CMD_COMPLETE))
1523 break;
1524
1525 if (aha->command_cmp != 0) {
1526 status = aha->latched_status;
1527 break;
1528 }
1529
1530 if ((status & DATAIN_REG_READY) != 0) {
1531 u_int8_t data;
1532
1533 data = aha_inb(aha, DATAIN_REG);
1534 if (reply_len < reply_buf_size) {
1535 *reply_data++ = data;
1536 } else {
1537 printf("%s: aha_cmd - Discarded reply data byte "
1538 "for opcode 0x%x\n", aha_name(aha),
1539 opcode);
1540 }
1541 reply_len++;
1542 }
1543
1544 DELAY(100);
1545 }
1546 if (timeout == 0) {
1547 printf("%s: aha_cmd: Timeout waiting for reply data and "
1548 "command complete.\n%s: status = 0x%x, intstat = 0x%x, "
1549 "reply_len = %d\n", aha_name(aha), aha_name(aha), status,
1550 intstat, reply_len);
1551 return (ETIMEDOUT);
1552 }
1553
1554 /*
1555 * Clear any pending interrupts. Block interrupts so our
1556 * interrupt handler is not re-entered.
1557 */
1558 s = splcam();
1559 aha_intr(aha);
1560 splx(s);
1561
1562 /*
1563 * If the command was rejected by the controller, tell the caller.
1564 */
1565 if ((status & CMD_INVALID) != 0) {
1568 if (bootverbose)
1569 printf("%s: Invalid Command 0x%x\n", aha_name(aha),
1570 opcode);
1566 PRVERB(("%s: Invalid Command 0x%x\n", aha_name(aha), opcode));
1571 /*
1572 * Some early adapters may not recover properly from
1573 * an invalid command. If it appears that the controller
1574 * has wedged (i.e. status was not cleared by our interrupt
1575 * reset above), perform a soft reset.
1576 */
1577 DELAY(1000);
1578 status = aha_inb(aha, STATUS_REG);
1579 if ((status & (CMD_INVALID|STATUS_REG_RSVD|DATAIN_REG_READY|
1580 CMD_REG_BUSY|DIAG_FAIL|DIAG_ACTIVE)) != 0
1581 || (status & (HA_READY|INIT_REQUIRED))
1582 != (HA_READY|INIT_REQUIRED)) {
1583 ahareset(aha, /*hard_reset*/FALSE);
1584 }
1585 return (EINVAL);
1586 }
1587
1588
1589 if (param_len > 0) {
1590 /* The controller did not accept the full argument list */
1591 return (E2BIG);
1592 }
1593
1594 if (reply_len != reply_buf_size) {
1595 /* Too much or too little data received */
1596 return (EMSGSIZE);
1597 }
1598
1599 /* We were successful */
1600 return (0);
1601}
1602
1603static int
1604ahainitmboxes(struct aha_softc *aha)
1605{
1606 int error;
1607 init_24b_mbox_params_t init_mbox;
1608
1609 bzero(aha->in_boxes, sizeof(aha_mbox_in_t) * aha->num_boxes);
1610 bzero(aha->out_boxes, sizeof(aha_mbox_out_t) * aha->num_boxes);
1611 aha->cur_inbox = aha->in_boxes;
1612 aha->last_inbox = aha->in_boxes + aha->num_boxes - 1;
1613 aha->cur_outbox = aha->out_boxes;
1614 aha->last_outbox = aha->out_boxes + aha->num_boxes - 1;
1615
1616 /* Tell the adapter about them */
1617 init_mbox.num_mboxes = aha->num_boxes;
1618 ahautoa24(aha->mailbox_physbase, init_mbox.base_addr);
1619 error = aha_cmd(aha, BOP_INITIALIZE_MBOX, (u_int8_t *)&init_mbox,
1620 /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL,
1621 /*reply_len*/0, DEFAULT_CMD_TIMEOUT);
1622
1623 if (error != 0)
1624 printf("ahainitmboxes: Initialization command failed\n");
1625 return (error);
1626}
1627
1628/*
1629 * Update the XPT's idea of the negotiated transfer
1630 * parameters for a particular target.
1631 */
1632static void
1633ahafetchtransinfo(struct aha_softc *aha, struct ccb_trans_settings* cts)
1634{
1635 setup_data_t setup_info;
1636 u_int target;
1637 u_int targ_offset;
1638 u_int sync_period;
1639 int error;
1640 u_int8_t param;
1641 targ_syncinfo_t sync_info;
1642
1643 target = cts->ccb_h.target_id;
1644 targ_offset = (target & 0x7);
1645
1646 /*
1647 * Inquire Setup Information. This command retreives the
1648 * Wide negotiation status for recent adapters as well as
1649 * the sync info for older models.
1650 */
1651 param = sizeof(setup_info);
1652 error = aha_cmd(aha, BOP_INQUIRE_SETUP_INFO, &param, /*paramlen*/1,
1653 (u_int8_t*)&setup_info, sizeof(setup_info),
1654 DEFAULT_CMD_TIMEOUT);
1655
1656 if (error != 0) {
1657 printf("%s: ahafetchtransinfo - Inquire Setup Info Failed\n",
1658 aha_name(aha));
1659 return;
1660 }
1661
1662 sync_info = setup_info.syncinfo[targ_offset];
1663
1664 if (sync_info.sync == 0)
1665 cts->sync_offset = 0;
1666 else
1667 cts->sync_offset = sync_info.offset;
1668
1669 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1670
1671 sync_period = 2000 + (500 * sync_info.period);
1672
1673 /* Convert ns value to standard SCSI sync rate */
1674 if (cts->sync_offset != 0)
1675 cts->sync_period = scsi_calc_syncparam(sync_period);
1676 else
1677 cts->sync_period = 0;
1678
1679 cts->valid = CCB_TRANS_SYNC_RATE_VALID
1680 | CCB_TRANS_SYNC_OFFSET_VALID
1681 | CCB_TRANS_BUS_WIDTH_VALID;
1682 xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts);
1683}
1684
1685static void
1686ahamapmboxes(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1687{
1688 struct aha_softc* aha;
1689
1690 aha = (struct aha_softc*)arg;
1691 aha->mailbox_physbase = segs->ds_addr;
1692}
1693
1694static void
1695ahamapccbs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1696{
1697 struct aha_softc* aha;
1698
1699 aha = (struct aha_softc*)arg;
1700 aha->aha_ccb_physbase = segs->ds_addr;
1701}
1702
1703static void
1704ahamapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1705{
1706
1707 struct aha_softc* aha;
1708
1709 aha = (struct aha_softc*)arg;
1710 SLIST_FIRST(&aha->sg_maps)->sg_physaddr = segs->ds_addr;
1711}
1712
1713static void
1714ahapoll(struct cam_sim *sim)
1715{
1716}
1717
1718void
1719ahatimeout(void *arg)
1720{
1721 struct aha_ccb *bccb;
1722 union ccb *ccb;
1723 struct aha_softc *aha;
1724 int s;
1725 u_int32_t paddr;
1726
1727 bccb = (struct aha_ccb *)arg;
1728 ccb = bccb->ccb;
1729 aha = (struct aha_softc *)ccb->ccb_h.ccb_aha_ptr;
1730 xpt_print_path(ccb->ccb_h.path);
1731 printf("CCB %p - timed out\n", (void *)bccb);
1732
1733 s = splcam();
1734
1735 if ((bccb->flags & BCCB_ACTIVE) == 0) {
1736 xpt_print_path(ccb->ccb_h.path);
1737 printf("CCB %p - timed out CCB already completed\n",
1738 (void *)bccb);
1739 splx(s);
1740 return;
1741 }
1742
1743 /*
1744 * In order to simplify the recovery process, we ask the XPT
1745 * layer to halt the queue of new transactions and we traverse
1746 * the list of pending CCBs and remove their timeouts. This
1747 * means that the driver attempts to clear only one error
1748 * condition at a time. In general, timeouts that occur
1749 * close together are related anyway, so there is no benefit
1750 * in attempting to handle errors in parrallel. Timeouts will
1751 * be reinstated when the recovery process ends.
1752 */
1753 if ((bccb->flags & BCCB_DEVICE_RESET) == 0) {
1754 struct ccb_hdr *ccb_h;
1755
1756 if ((bccb->flags & BCCB_RELEASE_SIMQ) == 0) {
1757 xpt_freeze_simq(aha->sim, /*count*/1);
1758 bccb->flags |= BCCB_RELEASE_SIMQ;
1759 }
1760
1761 ccb_h = LIST_FIRST(&aha->pending_ccbs);
1762 while (ccb_h != NULL) {
1763 struct aha_ccb *pending_bccb;
1764
1765 pending_bccb = (struct aha_ccb *)ccb_h->ccb_bccb_ptr;
1766 untimeout(ahatimeout, pending_bccb, ccb_h->timeout_ch);
1767 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1768 }
1769 }
1770
1771 if ((bccb->flags & BCCB_DEVICE_RESET) != 0
1772 || aha->cur_outbox->action_code != BMBO_FREE) {
1773 /*
1774 * Try a full host adapter/SCSI bus reset.
1775 * We do this only if we have already attempted
1776 * to clear the condition with a BDR, or we cannot
1777 * attempt a BDR for lack of mailbox resources.
1778 */
1779 ccb->ccb_h.status = CAM_CMD_TIMEOUT;
1780 ahareset(aha, /*hardreset*/TRUE);
1781 printf("%s: No longer in timeout\n", aha_name(aha));
1782 } else {
1783 /*
1784 * Send a Bus Device Reset message:
1785 * The target that is holding up the bus may not
1786 * be the same as the one that triggered this timeout
1787 * (different commands have different timeout lengths),
1788 * but we have no way of determining this from our
1789 * timeout handler. Our strategy here is to queue a
1790 * BDR message to the target of the timed out command.
1791 * If this fails, we'll get another timeout 2 seconds
1792 * later which will attempt a bus reset.
1793 */
1794 bccb->flags |= BCCB_DEVICE_RESET;
1795 ccb->ccb_h.timeout_ch = timeout(ahatimeout, (caddr_t)bccb, 2 * hz);
1796 aha->recovery_bccb->hccb.opcode = INITIATOR_BUS_DEV_RESET;
1797
1798 /* No Data Transfer */
1799 aha->recovery_bccb->hccb.datain = TRUE;
1800 aha->recovery_bccb->hccb.dataout = TRUE;
1801 aha->recovery_bccb->hccb.ahastat = 0;
1802 aha->recovery_bccb->hccb.sdstat = 0;
1803 aha->recovery_bccb->hccb.target = ccb->ccb_h.target_id;
1804
1805 /* Tell the adapter about this command */
1806 paddr = ahaccbvtop(aha, aha->recovery_bccb);
1807 ahautoa24(paddr, aha->cur_outbox->ccb_addr);
1808 aha->cur_outbox->action_code = BMBO_START;
1809 aha_outb(aha, COMMAND_REG, BOP_START_MBOX);
1810 ahanextoutbox(aha);
1811 }
1812
1813 splx(s);
1814}
1567 /*
1568 * Some early adapters may not recover properly from
1569 * an invalid command. If it appears that the controller
1570 * has wedged (i.e. status was not cleared by our interrupt
1571 * reset above), perform a soft reset.
1572 */
1573 DELAY(1000);
1574 status = aha_inb(aha, STATUS_REG);
1575 if ((status & (CMD_INVALID|STATUS_REG_RSVD|DATAIN_REG_READY|
1576 CMD_REG_BUSY|DIAG_FAIL|DIAG_ACTIVE)) != 0
1577 || (status & (HA_READY|INIT_REQUIRED))
1578 != (HA_READY|INIT_REQUIRED)) {
1579 ahareset(aha, /*hard_reset*/FALSE);
1580 }
1581 return (EINVAL);
1582 }
1583
1584
1585 if (param_len > 0) {
1586 /* The controller did not accept the full argument list */
1587 return (E2BIG);
1588 }
1589
1590 if (reply_len != reply_buf_size) {
1591 /* Too much or too little data received */
1592 return (EMSGSIZE);
1593 }
1594
1595 /* We were successful */
1596 return (0);
1597}
1598
1599static int
1600ahainitmboxes(struct aha_softc *aha)
1601{
1602 int error;
1603 init_24b_mbox_params_t init_mbox;
1604
1605 bzero(aha->in_boxes, sizeof(aha_mbox_in_t) * aha->num_boxes);
1606 bzero(aha->out_boxes, sizeof(aha_mbox_out_t) * aha->num_boxes);
1607 aha->cur_inbox = aha->in_boxes;
1608 aha->last_inbox = aha->in_boxes + aha->num_boxes - 1;
1609 aha->cur_outbox = aha->out_boxes;
1610 aha->last_outbox = aha->out_boxes + aha->num_boxes - 1;
1611
1612 /* Tell the adapter about them */
1613 init_mbox.num_mboxes = aha->num_boxes;
1614 ahautoa24(aha->mailbox_physbase, init_mbox.base_addr);
1615 error = aha_cmd(aha, BOP_INITIALIZE_MBOX, (u_int8_t *)&init_mbox,
1616 /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL,
1617 /*reply_len*/0, DEFAULT_CMD_TIMEOUT);
1618
1619 if (error != 0)
1620 printf("ahainitmboxes: Initialization command failed\n");
1621 return (error);
1622}
1623
1624/*
1625 * Update the XPT's idea of the negotiated transfer
1626 * parameters for a particular target.
1627 */
1628static void
1629ahafetchtransinfo(struct aha_softc *aha, struct ccb_trans_settings* cts)
1630{
1631 setup_data_t setup_info;
1632 u_int target;
1633 u_int targ_offset;
1634 u_int sync_period;
1635 int error;
1636 u_int8_t param;
1637 targ_syncinfo_t sync_info;
1638
1639 target = cts->ccb_h.target_id;
1640 targ_offset = (target & 0x7);
1641
1642 /*
1643 * Inquire Setup Information. This command retreives the
1644 * Wide negotiation status for recent adapters as well as
1645 * the sync info for older models.
1646 */
1647 param = sizeof(setup_info);
1648 error = aha_cmd(aha, BOP_INQUIRE_SETUP_INFO, &param, /*paramlen*/1,
1649 (u_int8_t*)&setup_info, sizeof(setup_info),
1650 DEFAULT_CMD_TIMEOUT);
1651
1652 if (error != 0) {
1653 printf("%s: ahafetchtransinfo - Inquire Setup Info Failed\n",
1654 aha_name(aha));
1655 return;
1656 }
1657
1658 sync_info = setup_info.syncinfo[targ_offset];
1659
1660 if (sync_info.sync == 0)
1661 cts->sync_offset = 0;
1662 else
1663 cts->sync_offset = sync_info.offset;
1664
1665 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1666
1667 sync_period = 2000 + (500 * sync_info.period);
1668
1669 /* Convert ns value to standard SCSI sync rate */
1670 if (cts->sync_offset != 0)
1671 cts->sync_period = scsi_calc_syncparam(sync_period);
1672 else
1673 cts->sync_period = 0;
1674
1675 cts->valid = CCB_TRANS_SYNC_RATE_VALID
1676 | CCB_TRANS_SYNC_OFFSET_VALID
1677 | CCB_TRANS_BUS_WIDTH_VALID;
1678 xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts);
1679}
1680
1681static void
1682ahamapmboxes(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1683{
1684 struct aha_softc* aha;
1685
1686 aha = (struct aha_softc*)arg;
1687 aha->mailbox_physbase = segs->ds_addr;
1688}
1689
1690static void
1691ahamapccbs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1692{
1693 struct aha_softc* aha;
1694
1695 aha = (struct aha_softc*)arg;
1696 aha->aha_ccb_physbase = segs->ds_addr;
1697}
1698
1699static void
1700ahamapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1701{
1702
1703 struct aha_softc* aha;
1704
1705 aha = (struct aha_softc*)arg;
1706 SLIST_FIRST(&aha->sg_maps)->sg_physaddr = segs->ds_addr;
1707}
1708
1709static void
1710ahapoll(struct cam_sim *sim)
1711{
1712}
1713
1714void
1715ahatimeout(void *arg)
1716{
1717 struct aha_ccb *bccb;
1718 union ccb *ccb;
1719 struct aha_softc *aha;
1720 int s;
1721 u_int32_t paddr;
1722
1723 bccb = (struct aha_ccb *)arg;
1724 ccb = bccb->ccb;
1725 aha = (struct aha_softc *)ccb->ccb_h.ccb_aha_ptr;
1726 xpt_print_path(ccb->ccb_h.path);
1727 printf("CCB %p - timed out\n", (void *)bccb);
1728
1729 s = splcam();
1730
1731 if ((bccb->flags & BCCB_ACTIVE) == 0) {
1732 xpt_print_path(ccb->ccb_h.path);
1733 printf("CCB %p - timed out CCB already completed\n",
1734 (void *)bccb);
1735 splx(s);
1736 return;
1737 }
1738
1739 /*
1740 * In order to simplify the recovery process, we ask the XPT
1741 * layer to halt the queue of new transactions and we traverse
1742 * the list of pending CCBs and remove their timeouts. This
1743 * means that the driver attempts to clear only one error
1744 * condition at a time. In general, timeouts that occur
1745 * close together are related anyway, so there is no benefit
1746 * in attempting to handle errors in parrallel. Timeouts will
1747 * be reinstated when the recovery process ends.
1748 */
1749 if ((bccb->flags & BCCB_DEVICE_RESET) == 0) {
1750 struct ccb_hdr *ccb_h;
1751
1752 if ((bccb->flags & BCCB_RELEASE_SIMQ) == 0) {
1753 xpt_freeze_simq(aha->sim, /*count*/1);
1754 bccb->flags |= BCCB_RELEASE_SIMQ;
1755 }
1756
1757 ccb_h = LIST_FIRST(&aha->pending_ccbs);
1758 while (ccb_h != NULL) {
1759 struct aha_ccb *pending_bccb;
1760
1761 pending_bccb = (struct aha_ccb *)ccb_h->ccb_bccb_ptr;
1762 untimeout(ahatimeout, pending_bccb, ccb_h->timeout_ch);
1763 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1764 }
1765 }
1766
1767 if ((bccb->flags & BCCB_DEVICE_RESET) != 0
1768 || aha->cur_outbox->action_code != BMBO_FREE) {
1769 /*
1770 * Try a full host adapter/SCSI bus reset.
1771 * We do this only if we have already attempted
1772 * to clear the condition with a BDR, or we cannot
1773 * attempt a BDR for lack of mailbox resources.
1774 */
1775 ccb->ccb_h.status = CAM_CMD_TIMEOUT;
1776 ahareset(aha, /*hardreset*/TRUE);
1777 printf("%s: No longer in timeout\n", aha_name(aha));
1778 } else {
1779 /*
1780 * Send a Bus Device Reset message:
1781 * The target that is holding up the bus may not
1782 * be the same as the one that triggered this timeout
1783 * (different commands have different timeout lengths),
1784 * but we have no way of determining this from our
1785 * timeout handler. Our strategy here is to queue a
1786 * BDR message to the target of the timed out command.
1787 * If this fails, we'll get another timeout 2 seconds
1788 * later which will attempt a bus reset.
1789 */
1790 bccb->flags |= BCCB_DEVICE_RESET;
1791 ccb->ccb_h.timeout_ch = timeout(ahatimeout, (caddr_t)bccb, 2 * hz);
1792 aha->recovery_bccb->hccb.opcode = INITIATOR_BUS_DEV_RESET;
1793
1794 /* No Data Transfer */
1795 aha->recovery_bccb->hccb.datain = TRUE;
1796 aha->recovery_bccb->hccb.dataout = TRUE;
1797 aha->recovery_bccb->hccb.ahastat = 0;
1798 aha->recovery_bccb->hccb.sdstat = 0;
1799 aha->recovery_bccb->hccb.target = ccb->ccb_h.target_id;
1800
1801 /* Tell the adapter about this command */
1802 paddr = ahaccbvtop(aha, aha->recovery_bccb);
1803 ahautoa24(paddr, aha->cur_outbox->ccb_addr);
1804 aha->cur_outbox->action_code = BMBO_START;
1805 aha_outb(aha, COMMAND_REG, BOP_START_MBOX);
1806 ahanextoutbox(aha);
1807 }
1808
1809 splx(s);
1810}