Line data Source code
1 : /* $OpenBSD: arc.c,v 1.107 2015/09/10 18:10:33 deraadt Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
5 : *
6 : * Permission to use, copy, modify, and distribute this software for any
7 : * purpose with or without fee is hereby granted, provided that the above
8 : * copyright notice and this permission notice appear in all copies.
9 : *
10 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 : */
18 :
19 : /*
20 : * Ching Huang Support ARC1880,1882,1213,1223,1214
21 : */
22 : #include "bio.h"
23 :
24 : #include <sys/param.h>
25 : #include <sys/systm.h>
26 : #include <sys/buf.h>
27 : #include <sys/kernel.h>
28 : #include <sys/malloc.h>
29 : #include <sys/mutex.h>
30 : #include <sys/device.h>
31 : #include <sys/rwlock.h>
32 : #include <sys/task.h>
33 :
34 : #include <machine/bus.h>
35 :
36 : #include <dev/pci/pcireg.h>
37 : #include <dev/pci/pcivar.h>
38 : #include <dev/pci/pcidevs.h>
39 :
40 : #include <scsi/scsi_all.h>
41 : #include <scsi/scsiconf.h>
42 :
43 : #include <sys/sensors.h>
44 : #if NBIO > 0
45 : #include <sys/ioctl.h>
46 : #include <dev/biovar.h>
47 : #endif
48 :
49 : #ifdef ARC_DEBUG
50 : #define ARC_D_INIT (1<<0)
51 : #define ARC_D_RW (1<<1)
52 : #define ARC_D_DB (1<<2)
53 :
54 : int arcdebug = 0;
55 :
56 : #define DPRINTF(p...) do { if (arcdebug) printf(p); } while (0)
57 : #define DNPRINTF(n, p...) do { if ((n) & arcdebug) printf(p); } while (0)
58 :
59 : #else
60 : #define DPRINTF(p...) /* p */
61 : #define DNPRINTF(n, p...) /* n, p */
62 : #endif
63 :
64 : #define ARC_HBA_TYPE_A 0x00000001
65 : #define ARC_HBA_TYPE_B 0x00000002
66 : #define ARC_HBA_TYPE_C 0x00000003
67 : #define ARC_HBA_TYPE_D 0x00000004
68 :
69 : #define ARC_RA_PCI_BAR PCI_MAPREG_START
70 : #define ARC_RB_DOORBELL_BAR PCI_MAPREG_START
71 : #define ARC_RB_RWBUFFER_BAR PCI_MAPREG_PPB_END
72 : #define ARC_RC_PCI_BAR PCI_MAPREG_PCB_END
73 : #define ARC_RD_PCI_BAR PCI_MAPREG_START
74 :
75 : #define ARCMSR_MAX_CCB_COUNT 264
76 : #define ARCMSR_MAX_HBB_POSTQUEUE 264
77 : #define ARCMSR_MAX_HBD_POSTQUEUE 256
78 :
79 : /* Areca boards using the Intel IOP are Type A (RA) */
80 :
81 : #define ARC_RA_INB_MSG0 0x0010
82 : #define ARC_RA_INB_MSG0_NOP (0x00000000)
83 : #define ARC_RA_INB_MSG0_GET_CONFIG (0x00000001)
84 : #define ARC_RA_INB_MSG0_SET_CONFIG (0x00000002)
85 : #define ARC_RA_INB_MSG0_ABORT_CMD (0x00000003)
86 : #define ARC_RA_INB_MSG0_STOP_BGRB (0x00000004)
87 : #define ARC_RA_INB_MSG0_FLUSH_CACHE (0x00000005)
88 : #define ARC_RA_INB_MSG0_START_BGRB (0x00000006)
89 : #define ARC_RA_INB_MSG0_CHK331PENDING (0x00000007)
90 : #define ARC_RA_INB_MSG0_SYNC_TIMER (0x00000008)
91 : #define ARC_RA_INB_MSG1 0x0014
92 : #define ARC_RA_OUTB_ADDR0 0x0018
93 : #define ARC_RA_OUTB_ADDR1 0x001c
94 : #define ARC_RA_OUTB_ADDR1_FIRMWARE_OK (1<<31)
95 : #define ARC_RA_INB_DOORBELL 0x0020
96 : #define ARC_RA_INB_DOORBELL_WRITE_OK (1<<0)
97 : #define ARC_RA_INB_DOORBELL_READ_OK (1<<1)
98 : #define ARC_RA_OUTB_DOORBELL 0x002c
99 : #define ARC_RA_OUTB_DOORBELL_WRITE_OK (1<<0)
100 : #define ARC_RA_OUTB_DOORBELL_READ_OK (1<<1)
101 : #define ARC_RA_INTRSTAT 0x0030
102 : #define ARC_RA_INTRSTAT_MSG0 (1<<0)
103 : #define ARC_RA_INTRSTAT_MSG1 (1<<1)
104 : #define ARC_RA_INTRSTAT_DOORBELL (1<<2)
105 : #define ARC_RA_INTRSTAT_POSTQUEUE (1<<3)
106 : #define ARC_RA_INTRSTAT_PCI (1<<4)
107 : #define ARC_RA_INTR_STAT_ALL 0x1F
108 : #define ARC_RA_INTRMASK 0x0034
109 : #define ARC_RA_INTRMASK_MSG0 (1<<0)
110 : #define ARC_RA_INTRMASK_MSG1 (1<<1)
111 : #define ARC_RA_INTRMASK_DOORBELL (1<<2)
112 : #define ARC_RA_INTRMASK_POSTQUEUE (1<<3)
113 : #define ARC_RA_INTRMASK_PCI (1<<4)
114 : #define ARC_RA_INTR_MASK_ALL 0x1F
115 : #define ARC_RA_POST_QUEUE 0x0040
116 : #define ARC_RA_POST_QUEUE_ADDR_SHIFT 5
117 : #define ARC_RA_POST_QUEUE_IAMBIOS (1<<30)
118 : #define ARC_RA_POST_QUEUE_BIGFRAME (1<<31)
119 : #define ARC_RA_REPLY_QUEUE 0x0044
120 : #define ARC_RA_REPLY_QUEUE_ADDR_SHIFT 5
121 : #define ARC_RA_REPLY_QUEUE_ERR (1<<28)
122 : #define ARC_RA_REPLY_QUEUE_IAMBIOS (1<<30)
123 : #define ARC_RA_MSGBUF 0x0a00
124 : #define ARC_RA_MSGBUF_LEN 1024
125 : #define ARC_RA_IOC_WBUF_LEN 0x0e00
126 : #define ARC_RA_IOC_WBUF 0x0e04
127 : #define ARC_RA_IOC_RBUF_LEN 0x0f00
128 : #define ARC_RA_IOC_RBUF 0x0f04
129 : #define ARC_RA_IOC_RWBUF_MAXLEN 124 /* for both RBUF and WBUF */
130 :
131 : /* Areca boards using the Marvel IOP0 are Type B (RB) */
132 :
133 : #define ARC_RB_DRV2IOP_DOORBELL 0x00020400
134 : #define ARC_RB_DRV2IOP_DOORBELL_MASK 0x00020404
135 : #define ARC_RB_IOP2DRV_DOORBELL 0x00020408
136 : #define ARC_RB_IOP2DRV_DOORBELL_FIRMWARE_OK (1<<31)
137 : #define ARC_RB_IOP2DRV_DOORBELL_MASK 0x0002040c
138 :
139 : /* Areca boards using the LSI IOP are Type C (RC) */
140 :
141 : #define ARC_RC_INB_DOORBELL 0x20
142 : #define ARC_RC_INTR_STAT 0x30
143 : #define ARC_RC_INTR_MASK 0x34
144 : #define ARC_RC_OUTB_DOORBELL 0x9C
145 : #define ARC_RC_OUTB_DOORBELL_CLR 0xA0
146 : #define ARC_RC_D2I_MSG_CMD_DONE 0x08
147 : #define ARC_RC_I2D_MSG_CMD_DONE 0x08
148 : #define ARC_RC_I2D_MSG_CMD_DONE_CLR 0x08
149 : #define ARC_RC_INB_MSGADDR0 0xB0
150 : #define ARC_RC_INB_MSGADDR1 0xB4
151 : #define ARC_RC_OUTB_MSGADDR0 0xB8
152 : #define ARC_RC_OUTB_MSGADDR1 0xBC
153 : #define ARC_RC_OUTB_MSG_FIRMWARE_OK 0x80000000
154 : #define ARC_RC_INB_POSTQ_LOW 0xC0
155 : #define ARC_RC_INB_POSTQ_HIGH 0xC4
156 : #define ARC_RC_OUTB_REPLYQ_LOW 0xC8
157 : #define ARC_RC_OUTB_REPLYQ_HIGH 0xCC
158 : #define ARC_RC_MSG_WBUF_LEN 0x2000
159 : #define ARC_RC_MSG_WBUF 0x2004
160 : #define ARC_RC_MSG_RBUF_LEN 0x2100
161 : #define ARC_RC_MSG_RBUF 0x2104
162 : #define ARC_RC_MSG_RWBUF 0x2200
163 :
164 : #define ARC_RC_INB_MSG0_NOP (0x00000000)
165 : #define ARC_RC_INB_MSG0_GET_CONFIG (0x00000001)
166 : #define ARC_RC_INB_MSG0_SET_CONFIG (0x00000002)
167 : #define ARC_RC_INB_MSG0_ABORT_CMD (0x00000003)
168 : #define ARC_RC_INB_MSG0_STOP_BGRB (0x00000004)
169 : #define ARC_RC_INB_MSG0_FLUSH_CACHE (0x00000005)
170 : #define ARC_RC_INB_MSG0_START_BGRB (0x00000006)
171 : #define ARC_RC_INB_MSG0_CHK331PENDING (0x00000007)
172 : #define ARC_RC_INB_MSG0_SYNC_TIMER (0x00000008)
173 :
174 : #define ARC_RC_D2I_DATA_WRITE_OK 0x00000002
175 : #define ARC_RC_D2I_DATA_READ_OK 0x00000004
176 : #define ARC_RC_D2I_MESSAGE_CMD_DONE 0x00000008
177 : #define ARC_RC_D2I_POSTQUEUE_THROTTLING 0x00000010
178 : #define ARC_RC_I2D_DATA_WRITE_OK 0x00000002
179 : #define ARC_RC_I2D_DATA_WRITE_OK_CLEAR 0x00000002
180 : #define ARC_RC_I2D_DATA_READ_OK 0x00000004
181 : #define ARC_RC_I2D_DATA_READ_OK_CLEAR 0x00000004
182 : #define ARC_RC_I2D_MESSAGE_CMD_DONE 0x00000008
183 : #define ARC_RC_I2D_MESSAGE_CMD_DONE_CLEAR 0x00000008
184 : #define ARC_RC_MESSAGE_FIRMWARE_OK 0x80000000
185 :
186 : #define ARC_RC_INTR_STAT_UTILITY_A (1<<0)
187 : #define ARC_RC_INTR_STAT_DOORBELL (1<<2)
188 : #define ARC_RC_INTR_STAT_POSTQUEUE (1<<3)
189 : #define ARC_RC_INTR_MASK_ALL 0x0000000D
190 : #define ARC_RC_INTR_MASK_UTILITY_A (1<<0)
191 : #define ARC_RC_INTR_MASK_DOORBELL (1<<2)
192 : #define ARC_RC_INTR_MASK_POSTQUEUE (1<<3)
193 : #define ARC_RC_REPLY_QUEUE_ERR 1
194 : #define ARC_RC_THROTTLE 12
195 :
196 : /* Areca boards using the Marvell IOP 9580 are Type D (RD) */
197 :
198 : #define ARC_RD_INTR_STAT 0x200
199 : #define ARC_RD_HOST_INT_ENABLE 0x204
200 : #define ARC_RD_INTR_ENABLE 0x20C
201 : #define ARC_RD_D2I_MSG_CMD_DONE 0x08
202 : #define ARC_RD_I2D_MSG_CMD_DONE 0x2000000
203 : #define ARC_RD_I2D_MSG_CMD_DONE_CLR 0x2000000
204 : #define ARC_RD_INB_MSGADDR0 0x400
205 : #define ARC_RD_INB_MSGADDR1 0x404
206 : #define ARC_RD_OUTB_MSGADDR0 0x420
207 : #define ARC_RD_OUTB_MSGADDR1 0x424
208 : #define ARC_RD_INB_DOORBELL 0x460
209 : #define ARC_RD_OUTB_DOORBELL 0x480
210 : #define ARC_RD_OUTB_DOORBELL_CLR 0x480
211 : #define ARC_RD_OUTB_DOORBELL_ENABLE 0x484
212 : #define ARC_RD_OUTB_MSG_FIRMWARE_OK 0x80000000
213 : #define ARC_RD_INB_POSTQ_LOW 0x1000
214 : #define ARC_RD_INB_POSTQ_HIGH 0x1004
215 : #define ARC_RD_OUTB_REPLYQ_LOW 0x1060
216 : #define ARC_RD_OUTB_REPLYQ_HIGH 0x1064
217 :
218 : #define ARC_RD_INB_WRITE_PTR 0x1018
219 : #define ARC_RD_INB_READ_PTR 0x101C
220 : #define ARC_RD_OUTB_COPY_PTR 0x106C
221 : #define ARC_RD_OUTB_READ_PTR 0x1070
222 : #define ARC_RD_OUTB_INTR_CAUSE 0x1088
223 : #define ARC_RD_OUTB_INT_ENABLE 0x108C
224 : #define ARC_RD_MSG_WBUF_LEN 0x2000
225 : #define ARC_RD_MSG_WBUF 0x2004
226 : #define ARC_RD_MSG_RBUF_LEN 0x2100
227 : #define ARC_RD_MSG_RBUF 0x2104
228 : #define ARC_RD_MSG_RWBUF 0x2200
229 :
230 : #define ARC_RD_INB_MSG0_NOP (0x00000000)
231 : #define ARC_RD_INB_MSG0_GET_CONFIG (0x00000001)
232 : #define ARC_RD_INB_MSG0_SET_CONFIG (0x00000002)
233 : #define ARC_RD_INB_MSG0_ABORT_CMD (0x00000003)
234 : #define ARC_RD_INB_MSG0_STOP_BGRB (0x00000004)
235 : #define ARC_RD_INB_MSG0_FLUSH_CACHE (0x00000005)
236 : #define ARC_RD_INB_MSG0_START_BGRB (0x00000006)
237 : #define ARC_RD_INB_MSG0_CHK331PENDING (0x00000007)
238 : #define ARC_RD_INB_MSG0_SYNC_TIMER (0x00000008)
239 :
240 : #define ARC_RD_D2I_DATA_WRITE_OK 0x00000001
241 : #define ARC_RD_D2I_DATA_READ_OK 0x00000002
242 : #define ARC_RD_D2I_MESSAGE_CMD_DONE 0x02000000
243 : #define ARC_RD_D2I_POSTQUEUE_THROTTLING 0x00000010
244 : #define ARC_RD_I2D_DATA_WRITE_OK 0x00000001
245 : #define ARC_RD_I2D_DATA_WRITE_CLEAR 0x00000001
246 : #define ARC_RD_I2D_DATA_READ_OK 0x00000002
247 : #define ARC_RD_I2D_DATA_READ_CLEAR 0x00000002
248 : #define ARC_RD_I2D_MESSAGE_CMD_DONE 0x02000000
249 : #define ARC_RD_I2D_MESSAGE_CMD_DONE_CLEAR 0x02000000
250 : #define ARC_RD_MESSAGE_FIRMWARE_OK 0x80000000
251 :
252 : #define ARC_RD_INTR_STAT_DOORBELL 0x00001000
253 : #define ARC_RD_INTR_STAT_POSTQUEUE 0x00000010
254 : #define ARC_RD_INTR_ENABLE_ALL 0x00001010
255 : #define ARC_RD_INTR_DISABLE_ALL 0x00000000
256 : #define ARC_RD_INTR_ENABLE_DOORBELL 0x00001000
257 : #define ARC_RD_INTR_ENABLE_POSTQUEUE 0x00000010
258 : #define ARC_RD_REPLY_QUEUE_ERR 1
259 : #define ARC_RD_OUTB_LIST_INT_CLR 1
260 :
261 : struct arc_msg_firmware_info {
262 : u_int32_t signature;
263 : #define ARC_FWINFO_SIGNATURE_GET_CONFIG (0x87974060)
264 : #define ARC_FWINFO_SIGNATURE_SET_CONFIG (0x87974063)
265 : u_int32_t request_len;
266 : u_int32_t queue_len;
267 : u_int32_t sdram_size;
268 : u_int32_t sata_ports;
269 : u_int8_t vendor[40];
270 : u_int8_t model[8];
271 : u_int8_t fw_version[16];
272 : u_int8_t device_map[16];
273 : u_int32_t cfgVersion;
274 : u_int8_t cfgSerial[16];
275 : u_int32_t cfgPicStatus;
276 : } __packed;
277 :
278 : /* definitions of the firmware commands sent via the doorbells */
279 :
280 : struct arc_fw_hdr {
281 : u_int8_t byte1;
282 : u_int8_t byte2;
283 : u_int8_t byte3;
284 : } __packed;
285 :
286 : /* the fw header must always equal this */
287 : struct arc_fw_hdr arc_fw_hdr = { 0x5e, 0x01, 0x61 };
288 :
289 : struct arc_fw_bufhdr {
290 : struct arc_fw_hdr hdr;
291 : u_int16_t len;
292 : } __packed;
293 :
294 : #define ARC_FW_RAIDINFO 0x20 /* opcode + raid# */
295 : #define ARC_FW_VOLINFO 0x21 /* opcode + vol# */
296 : #define ARC_FW_DISKINFO 0x22 /* opcode + physdisk# */
297 : #define ARC_FW_SYSINFO 0x23 /* opcode. reply is fw_sysinfo */
298 : #define ARC_FW_MUTE_ALARM 0x30 /* opcode only */
299 : #define ARC_FW_SET_ALARM 0x31 /* opcode + 1 byte for setting */
300 : #define ARC_FW_SET_ALARM_DISABLE 0x00
301 : #define ARC_FW_SET_ALARM_ENABLE 0x01
302 : #define ARC_FW_NOP 0x38 /* opcode only */
303 :
304 : #define ARC_FW_CMD_OK 0x41
305 : #define ARC_FW_BLINK 0x43
306 : #define ARC_FW_BLINK_ENABLE 0x00
307 : #define ARC_FW_BLINK_DISABLE 0x01
308 : #define ARC_FW_CMD_PASS_REQD 0x4d
309 :
310 : struct arc_fw_comminfo {
311 : u_int8_t baud_rate;
312 : u_int8_t data_bits;
313 : u_int8_t stop_bits;
314 : u_int8_t parity;
315 : u_int8_t flow_control;
316 : } __packed;
317 :
318 : struct arc_fw_scsiattr {
319 : u_int8_t channel; /* channel for SCSI target (0/1) */
320 : u_int8_t target;
321 : u_int8_t lun;
322 : u_int8_t tagged;
323 : u_int8_t cache;
324 : u_int8_t speed;
325 : } __packed;
326 :
327 : struct arc_fw_raidinfo {
328 : u_int8_t set_name[16];
329 : u_int32_t capacity;
330 : u_int32_t capacity2;
331 : u_int32_t fail_mask;
332 : u_int8_t device_array[32];
333 : u_int8_t member_devices;
334 : u_int8_t new_member_devices;
335 : u_int8_t raid_state;
336 : u_int8_t volumes;
337 : u_int8_t volume_list[16];
338 : u_int8_t reserved1[3];
339 : u_int8_t free_segments;
340 : u_int32_t raw_stripes[8];
341 : u_int32_t reserved2[3];
342 : u_int8_t vol_ListX[112];
343 : u_int8_t devEncArray[32];
344 : } __packed;
345 :
346 : struct arc_fw_volinfo {
347 : u_int8_t set_name[16];
348 : u_int32_t capacity;
349 : u_int32_t capacity2;
350 : u_int32_t fail_mask;
351 : u_int32_t stripe_size; /* in blocks */
352 : u_int32_t new_fail_mask;
353 : u_int32_t new_stripe_size;
354 : u_int32_t volume_status;
355 : #define ARC_FW_VOL_STATUS_NORMAL 0x00
356 : #define ARC_FW_VOL_STATUS_INITTING (1<<0)
357 : #define ARC_FW_VOL_STATUS_FAILED (1<<1)
358 : #define ARC_FW_VOL_STATUS_MIGRATING (1<<2)
359 : #define ARC_FW_VOL_STATUS_REBUILDING (1<<3)
360 : #define ARC_FW_VOL_STATUS_NEED_INIT (1<<4)
361 : #define ARC_FW_VOL_STATUS_NEED_MIGRATE (1<<5)
362 : #define ARC_FW_VOL_STATUS_INIT_FLAG (1<<6)
363 : #define ARC_FW_VOL_STATUS_NEED_REGEN (1<<7)
364 : #define ARC_FW_VOL_STATUS_CHECKING (1<<8)
365 : #define ARC_FW_VOL_STATUS_NEED_CHECK (1<<9)
366 : u_int32_t progress;
367 : struct arc_fw_scsiattr scsi_attr;
368 : u_int8_t member_disks;
369 : u_int8_t raid_level;
370 : #define ARC_FW_VOL_RAIDLEVEL_0 0x00
371 : #define ARC_FW_VOL_RAIDLEVEL_1 0x01
372 : #define ARC_FW_VOL_RAIDLEVEL_3 0x02
373 : #define ARC_FW_VOL_RAIDLEVEL_5 0x03
374 : #define ARC_FW_VOL_RAIDLEVEL_6 0x04
375 : #define ARC_FW_VOL_RAIDLEVEL_PASSTHRU 0x05
376 : u_int8_t new_member_disks;
377 : u_int8_t new_raid_level;
378 : u_int8_t raid_set_number;
379 : u_int8_t vol_state0;
380 : u_int32_t host_speed;
381 : u_int32_t vol_state;
382 : u_int8_t vol_array[16];
383 : u_int8_t num_5060volumes;
384 : u_int8_t reserved[43];
385 : } __packed;
386 :
387 : struct arc_fw_diskinfo {
388 : u_int8_t model[40];
389 : u_int8_t serial[20];
390 : u_int8_t firmware_rev[8];
391 : u_int32_t capacity;
392 : u_int32_t capacity2;
393 : u_int8_t device_state;
394 : u_int8_t pio_mode;
395 : u_int8_t current_udma_mode;
396 : u_int8_t udma_mode;
397 : u_int8_t hot_spare_type;
398 : u_int8_t raid_number; /* 0xff unowned */
399 : struct arc_fw_scsiattr scsi_attr;
400 : u_int8_t reserved[170];
401 : } __packed;
402 :
403 : struct arc_fw_sysinfo {
404 : u_int8_t vendor_name[40];
405 : u_int8_t serial_number[16];
406 : u_int8_t firmware_version[16];
407 : u_int8_t boot_version[16];
408 : u_int8_t mb_version[16];
409 : u_int8_t model_name[8];
410 :
411 : u_int8_t local_ip[4];
412 : u_int8_t current_ip[4];
413 :
414 : u_int32_t time_tick;
415 : u_int32_t cpu_speed;
416 : u_int32_t icache;
417 : u_int32_t dcache;
418 : u_int32_t scache;
419 : u_int32_t memory_size;
420 : u_int32_t memory_speed;
421 : u_int32_t events;
422 :
423 : u_int8_t gsiMacAddress[6];
424 : u_int8_t gsiDhcp;
425 : u_int8_t alarm;
426 : u_int8_t channel_usage;
427 : u_int8_t max_ata_mode;
428 : u_int8_t sdram_ecc;
429 : u_int8_t rebuild_priority;
430 : struct arc_fw_comminfo comm_a;
431 : struct arc_fw_comminfo comm_b;
432 : u_int8_t ide_channels;
433 : u_int8_t scsi_host_channels;
434 : u_int8_t ide_host_channels;
435 : u_int8_t max_volume_set;
436 : u_int8_t max_raid_set;
437 : u_int8_t ether_port;
438 : u_int8_t raid6_engine;
439 : u_int8_t reserved[75];
440 : } __packed;
441 :
442 : struct arc_iop;
443 : struct arc_ccb;
444 : SLIST_HEAD(arc_ccb_list, arc_ccb);
445 :
446 : struct InBound_SRB {
447 : u_int32_t addressLow; /* pointer to SRB block */
448 : u_int32_t addressHigh;
449 : u_int32_t length; /* in DWORDs */
450 : u_int32_t reserved0;
451 : };
452 :
453 : struct OutBound_SRB {
454 : u_int32_t addressLow; /* pointer to SRB block */
455 : u_int32_t addressHigh;
456 : };
457 :
458 : struct arc_HBD_Msgu {
459 : struct InBound_SRB post_qbuffer[ARCMSR_MAX_HBD_POSTQUEUE];
460 : struct OutBound_SRB done_qbuffer[ARCMSR_MAX_HBD_POSTQUEUE+1];
461 : u_int16_t postq_index;
462 : u_int16_t doneq_index;
463 : };
464 :
465 : #define ARC_MAX_CMDQ_PTR_LEN sizeof(struct arc_HBD_Msgu)
466 :
467 : struct arc_msg_scsicmd {
468 : u_int8_t bus;
469 : u_int8_t target;
470 : u_int8_t lun;
471 : u_int8_t function;
472 :
473 : u_int8_t cdb_len;
474 : u_int8_t sgl_len;
475 : u_int8_t flags;
476 : #define ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512 (1<<0)
477 : #define ARC_MSG_SCSICMD_FLAG_FROM_BIOS (1<<1)
478 : #define ARC_MSG_SCSICMD_FLAG_WRITE (1<<2)
479 : #define ARC_MSG_SCSICMD_FLAG_SIMPLEQ (0x00)
480 : #define ARC_MSG_SCSICMD_FLAG_HEADQ (0x08)
481 : #define ARC_MSG_SCSICMD_FLAG_ORDERQ (0x10)
482 : u_int8_t msgPages;
483 :
484 : u_int32_t context;
485 : u_int32_t data_len;
486 :
487 : #define ARC_MSG_CDBLEN 16
488 : u_int8_t cdb[ARC_MSG_CDBLEN];
489 :
490 : u_int8_t status;
491 : #define ARC_MSG_STATUS_SELTIMEOUT 0xf0
492 : #define ARC_MSG_STATUS_ABORTED 0xf1
493 : #define ARC_MSG_STATUS_INIT_FAIL 0xf2
494 : #define ARC_MSG_SENSELEN 15
495 : u_int8_t sense_data[ARC_MSG_SENSELEN];
496 :
497 : /* followed by an sgl */
498 : } __packed;
499 :
500 : struct arc_sge {
501 : u_int32_t sg_length;
502 : #define ARC_SGE_64BIT (1<<24)
503 : u_int32_t sg_lo_addr;
504 : u_int32_t sg_hi_addr;
505 : } __packed;
506 :
507 : #define ARC_MAX_TARGET 16
508 : #define ARC_MAX_LUN 8
509 : #define ARC_MAX_IOCMDLEN 512
510 : #define ARC_BLOCKSIZE 512
511 :
512 : /* the firmware deals with up to 256 or 512 byte command frames. */
513 : /* sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 38) == 508 */
514 : #define ARC_SGL_MAXLEN 38
515 : /* sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 17) == 252 */
516 : #define ARC_SGL_256LEN 17
517 :
518 : struct arc_io_cmd {
519 : struct arc_msg_scsicmd cmd;
520 : struct arc_sge sgl[ARC_SGL_MAXLEN];
521 : u_int32_t reserved1;
522 : struct arc_ccb *ccb;
523 : u_int32_t reserved2[6];
524 : } __packed;
525 :
526 : #define ARC_IO_CMD_LEN 512+32
527 :
528 : /* stuff to manage a scsi command */
529 : struct arc_ccb {
530 : struct arc_softc *ccb_sc;
531 :
532 : struct scsi_xfer *ccb_xs;
533 :
534 : bus_dmamap_t ccb_dmamap;
535 : bus_addr_t cmd_dma_offset;
536 : struct arc_io_cmd *ccb_cmd;
537 : u_int32_t ccb_cmd_post;
538 :
539 : SLIST_ENTRY(arc_ccb) ccb_link;
540 : u_int32_t arc_io_cmd_length;
541 : };
542 :
543 : struct arc_softc {
544 : struct device sc_dev;
545 : const struct arc_iop *sc_iop;
546 : struct scsi_link sc_link;
547 :
548 : pci_chipset_tag_t sc_pc;
549 : pcitag_t sc_tag;
550 :
551 : bus_space_tag_t sc_iot;
552 : bus_space_handle_t sc_ioh;
553 : bus_size_t sc_ios;
554 : bus_dma_tag_t sc_dmat;
555 :
556 : void *sc_ih;
557 :
558 : u_int32_t sc_req_count;
559 :
560 : struct arc_dmamem *sc_requests;
561 : struct arc_ccb *sc_ccbs;
562 : struct arc_ccb_list sc_ccb_free;
563 : struct mutex sc_ccb_mtx;
564 :
565 : struct scsi_iopool sc_iopool;
566 : struct scsibus_softc *sc_scsibus;
567 :
568 : struct rwlock sc_lock;
569 : volatile int sc_talking;
570 :
571 : struct ksensor *sc_sensors;
572 : struct ksensordev sc_sensordev;
573 : int sc_nsensors;
574 :
575 : u_int32_t sc_ledmask;
576 : u_int32_t sc_adp_type;
577 : u_int32_t sc_ccb_phys_hi;
578 : u_int32_t postQ_buffer;
579 : u_int32_t doneQ_buffer;
580 : bus_addr_t cmdQ_ptr_offset;
581 : struct arc_HBD_Msgu *pmu;
582 : };
583 : #define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
584 :
585 : /* wrap up the bus_dma api */
586 : struct arc_dmamem {
587 : bus_dmamap_t adm_map;
588 : bus_dma_segment_t adm_seg;
589 : size_t adm_size;
590 : caddr_t adm_kva;
591 : };
592 : #define ARC_DMA_MAP(_adm) ((_adm)->adm_map)
593 : #define ARC_DMA_DVA(_adm) ((_adm)->adm_map->dm_segs[0].ds_addr)
594 : #define ARC_DMA_KVA(_adm) ((void *)(_adm)->adm_kva)
595 :
596 : int arc_match(struct device *, void *, void *);
597 : void arc_attach(struct device *, struct device *, void *);
598 : int arc_detach(struct device *, int);
599 : int arc_activate(struct device *, int);
600 : int arc_intr(void *);
601 : int arc_intr_A(void *);
602 : int arc_intr_C(void *);
603 : int arc_intr_D(void *);
604 :
605 : /* interface for scsi midlayer to talk to */
606 : void arc_scsi_cmd(struct scsi_xfer *);
607 : void arc_minphys(struct buf *, struct scsi_link *);
608 :
609 : /* code to deal with getting bits in and out of the bus space */
610 : u_int32_t arc_read(struct arc_softc *, bus_size_t);
611 : void arc_read_region(struct arc_softc *, bus_size_t,
612 : void *, size_t);
613 : void arc_write(struct arc_softc *, bus_size_t, u_int32_t);
614 : void arc_write_region(struct arc_softc *, bus_size_t,
615 : void *, size_t);
616 : int arc_wait_eq(struct arc_softc *, bus_size_t,
617 : u_int32_t, u_int32_t);
618 : int arc_wait_ne(struct arc_softc *, bus_size_t,
619 : u_int32_t, u_int32_t);
620 : int arc_msg0(struct arc_softc *, u_int32_t);
621 :
622 : struct arc_dmamem *arc_dmamem_alloc(struct arc_softc *, size_t);
623 : void arc_dmamem_free(struct arc_softc *,
624 : struct arc_dmamem *);
625 : void arc_free_ccb_src(struct arc_softc *sc);
626 :
627 : int arc_alloc_ccbs(struct arc_softc *);
628 : struct arc_ccb *arc_get_ccb(struct arc_softc *);
629 : void arc_put_ccb(struct arc_softc *, struct arc_ccb *);
630 : int arc_load_xs(struct arc_ccb *);
631 : int arc_complete(struct arc_softc *, struct arc_ccb *,
632 : int);
633 : void arc_scsi_cmd_done(struct arc_softc *, struct arc_ccb *,
634 : u_int32_t);
635 :
636 : int arc_map_pci_resources(struct arc_softc *,
637 : struct pci_attach_args *);
638 : void arc_unmap_pci_resources(struct arc_softc *);
639 : int arc_chipA_firmware(struct arc_softc *);
640 : int arc_chipB_firmware(struct arc_softc *);
641 : int arc_chipC_firmware(struct arc_softc *);
642 : int arc_chipD_firmware(struct arc_softc *);
643 : void arc_enable_all_intr(struct arc_softc *);
644 : void arc_disable_all_intr(struct arc_softc *);
645 : void arc_stop_bgrb_proc(struct arc_softc *sc);
646 : void arc_flush_cache(struct arc_softc *sc);
647 : void arc_iop_set_conf(struct arc_softc *sc);
648 :
649 : #if NBIO > 0
650 : /* stuff to do messaging via the doorbells */
651 : void arc_lock(struct arc_softc *);
652 : void arc_unlock(struct arc_softc *);
653 : void arc_wait(struct arc_softc *);
654 : u_int8_t arc_msg_cksum(void *, u_int16_t);
655 : int arc_msgbuf(struct arc_softc *, void *, size_t,
656 : void *, size_t, int);
657 :
658 : /* bioctl */
659 : int arc_bioctl(struct device *, u_long, caddr_t);
660 : int arc_bio_inq(struct arc_softc *, struct bioc_inq *);
661 : int arc_bio_vol(struct arc_softc *, struct bioc_vol *);
662 : int arc_bio_disk(struct arc_softc *, struct bioc_disk *);
663 : int arc_bio_alarm(struct arc_softc *, struct bioc_alarm *);
664 : int arc_bio_alarm_state(struct arc_softc *,
665 : struct bioc_alarm *);
666 : int arc_bio_blink(struct arc_softc *, struct bioc_blink *);
667 :
668 : int arc_bio_getvol(struct arc_softc *, int,
669 : struct arc_fw_volinfo *);
670 :
671 : #ifndef SMALL_KERNEL
672 : struct arc_task {
673 : struct task t;
674 : struct arc_softc *sc;
675 : };
676 : /* sensors */
677 : void arc_create_sensors(void *);
678 : void arc_refresh_sensors(void *);
679 : #endif /* SMALL_KERNEL */
680 : #endif
681 :
682 : struct cfattach arc_ca = {
683 : sizeof(struct arc_softc), arc_match, arc_attach, arc_detach,
684 : arc_activate
685 : };
686 :
687 : struct cfdriver arc_cd = {
688 : NULL, "arc", DV_DULL
689 : };
690 :
691 : struct scsi_adapter arc_switch = {
692 : arc_scsi_cmd, arc_minphys, NULL, NULL, NULL
693 : };
694 :
695 : /* real stuff for dealing with the hardware */
696 : struct arc_iop {
697 : int (*iop_query_firmware)(struct arc_softc *);
698 : };
699 :
700 : static const struct arc_iop arc_intel = {
701 : arc_chipA_firmware
702 : };
703 :
704 : static const struct arc_iop arc_marvell = {
705 : arc_chipB_firmware
706 : };
707 :
708 : static const struct arc_iop arc_lsi = {
709 : arc_chipC_firmware
710 : };
711 :
712 : static const struct arc_iop arc_marvell2 = {
713 : arc_chipD_firmware
714 : };
715 :
716 : struct arc_board {
717 : pcireg_t ab_vendor;
718 : pcireg_t ab_product;
719 : const struct arc_iop *ab_iop;
720 : };
721 : const struct arc_board *arc_match_board(struct pci_attach_args *);
722 :
723 : static const struct arc_board arc_devices[] = {
724 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1110, &arc_intel },
725 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1120, &arc_intel },
726 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1130, &arc_intel },
727 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1160, &arc_intel },
728 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1170, &arc_intel },
729 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1200, &arc_intel },
730 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1200_B, &arc_marvell },
731 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1202, &arc_intel },
732 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1210, &arc_intel },
733 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1214, &arc_marvell2 },
734 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1220, &arc_intel },
735 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1230, &arc_intel },
736 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1260, &arc_intel },
737 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1270, &arc_intel },
738 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1280, &arc_intel },
739 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1380, &arc_intel },
740 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1381, &arc_intel },
741 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1680, &arc_intel },
742 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1681, &arc_intel },
743 : { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1880, &arc_lsi }
744 : };
745 :
746 : const struct arc_board *
747 0 : arc_match_board(struct pci_attach_args *pa)
748 : {
749 : const struct arc_board *ab;
750 : int i;
751 :
752 0 : for (i = 0; i < sizeof(arc_devices) / sizeof(arc_devices[0]); i++) {
753 0 : ab = &arc_devices[i];
754 :
755 0 : if (PCI_VENDOR(pa->pa_id) == ab->ab_vendor &&
756 0 : PCI_PRODUCT(pa->pa_id) == ab->ab_product)
757 0 : return (ab);
758 : }
759 :
760 0 : return (NULL);
761 0 : }
762 :
763 : int
764 0 : arc_match(struct device *parent, void *match, void *aux)
765 : {
766 0 : return ((arc_match_board(aux) == NULL) ? 0 : 1);
767 : }
768 :
769 : void
770 0 : arc_attach(struct device *parent, struct device *self, void *aux)
771 : {
772 0 : struct arc_softc *sc = (struct arc_softc *)self;
773 0 : struct pci_attach_args *pa = aux;
774 0 : struct scsibus_attach_args saa;
775 : struct device *child;
776 :
777 0 : sc->sc_talking = 0;
778 0 : rw_init(&sc->sc_lock, "arcmsg");
779 :
780 0 : sc->sc_iop = arc_match_board(pa)->ab_iop;
781 0 : if(sc->sc_iop == &arc_intel)
782 0 : sc->sc_adp_type = ARC_HBA_TYPE_A;
783 0 : else if(sc->sc_iop == &arc_marvell)
784 0 : sc->sc_adp_type = ARC_HBA_TYPE_B;
785 0 : else if(sc->sc_iop == &arc_lsi)
786 0 : sc->sc_adp_type = ARC_HBA_TYPE_C;
787 0 : else if(sc->sc_iop == &arc_marvell2)
788 0 : sc->sc_adp_type = ARC_HBA_TYPE_D;
789 0 : if (arc_map_pci_resources(sc, pa) != 0) {
790 : /* error message printed by arc_map_pci_resources */
791 0 : return;
792 : }
793 :
794 0 : if (arc_alloc_ccbs(sc) != 0) {
795 : /* error message printed by arc_alloc_ccbs */
796 : goto unmap_pci;
797 : }
798 :
799 0 : arc_iop_set_conf(sc);
800 :
801 0 : if (sc->sc_iop->iop_query_firmware(sc) != 0) {
802 : /* error message printed by arc_query_firmware */
803 : goto unmap_pci;
804 : }
805 :
806 0 : sc->sc_link.adapter = &arc_switch;
807 0 : sc->sc_link.adapter_softc = sc;
808 0 : sc->sc_link.adapter_target = ARC_MAX_TARGET;
809 0 : sc->sc_link.adapter_buswidth = ARC_MAX_TARGET;
810 0 : sc->sc_link.openings = sc->sc_req_count;
811 0 : sc->sc_link.pool = &sc->sc_iopool;
812 :
813 0 : bzero(&saa, sizeof(saa));
814 0 : saa.saa_sc_link = &sc->sc_link;
815 :
816 0 : child = config_found(self, &saa, scsiprint);
817 0 : sc->sc_scsibus = (struct scsibus_softc *)child;
818 :
819 : /* enable interrupts */
820 0 : arc_enable_all_intr(sc);
821 :
822 : #if NBIO > 0
823 0 : if (bio_register(self, arc_bioctl) != 0)
824 0 : panic("%s: bioctl registration failed", DEVNAME(sc));
825 :
826 : #ifndef SMALL_KERNEL
827 : /*
828 : * you need to talk to the firmware to get volume info. our firmware
829 : * interface relies on being able to sleep, so we need to use a thread
830 : * to do the work.
831 : */
832 : {
833 : struct arc_task *at;
834 0 : at = malloc(sizeof(*at), M_TEMP, M_WAITOK);
835 :
836 0 : at->sc = sc;
837 0 : task_set(&at->t, arc_create_sensors, at);
838 0 : task_add(systq, &at->t);
839 : }
840 : #endif
841 : #endif
842 :
843 0 : return;
844 : unmap_pci:
845 0 : arc_unmap_pci_resources(sc);
846 0 : }
847 :
848 : int
849 0 : arc_activate(struct device *self, int act)
850 : {
851 : int rv = 0;
852 :
853 0 : switch (act) {
854 : case DVACT_POWERDOWN:
855 : rv = config_activate_children(self, act);
856 0 : arc_detach(self, 0);
857 0 : break;
858 : default:
859 : rv = config_activate_children(self, act);
860 : break;
861 : }
862 0 : return (rv);
863 : }
864 :
865 : int
866 0 : arc_detach(struct device *self, int flags)
867 : {
868 0 : struct arc_softc *sc = (struct arc_softc *)self;
869 :
870 0 : arc_stop_bgrb_proc(sc);
871 0 : arc_flush_cache(sc);
872 :
873 0 : return (0);
874 : }
875 :
876 : int
877 0 : arc_intr_A(void *arg)
878 : {
879 0 : struct arc_softc *sc = arg;
880 : struct arc_ccb *ccb = NULL;
881 0 : char *kva = ARC_DMA_KVA(sc->sc_requests);
882 : struct arc_io_cmd *cmd;
883 : u_int32_t reg, intrstat, error;
884 : int ret = 0;
885 :
886 0 : intrstat = arc_read(sc, ARC_RA_INTRSTAT);
887 0 : intrstat &= ARC_RA_INTRSTAT_POSTQUEUE | ARC_RA_INTRSTAT_DOORBELL |
888 : ARC_RA_INTRSTAT_MSG0;
889 0 : arc_write(sc, ARC_RA_INTRSTAT, intrstat);
890 :
891 0 : if (intrstat & ARC_RA_INTRSTAT_DOORBELL) {
892 : ret = 1;
893 0 : if (sc->sc_talking) {
894 : /* if an ioctl is talking, wake it up */
895 0 : arc_write(sc, ARC_RA_INTRMASK,
896 : ~ARC_RA_INTRMASK_POSTQUEUE);
897 0 : wakeup(sc);
898 0 : } else {
899 : /* otherwise drop it */
900 0 : reg = arc_read(sc, ARC_RA_OUTB_DOORBELL);
901 0 : arc_write(sc, ARC_RA_OUTB_DOORBELL, reg);
902 0 : if (reg & ARC_RA_OUTB_DOORBELL_WRITE_OK)
903 0 : arc_write(sc, ARC_RA_INB_DOORBELL,
904 : ARC_RA_INB_DOORBELL_READ_OK);
905 : }
906 : }
907 :
908 0 : if (intrstat & ARC_RA_INTRSTAT_POSTQUEUE) {
909 0 : while ((reg = arc_read(sc, ARC_RA_REPLY_QUEUE)) != 0xffffffff) {
910 : ret = 1;
911 0 : cmd = (struct arc_io_cmd *)(kva +
912 0 : ((reg << ARC_RA_REPLY_QUEUE_ADDR_SHIFT) -
913 0 : (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
914 0 : ccb = cmd->ccb;
915 :
916 0 : bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
917 : ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
918 : BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
919 :
920 0 : error = (reg & ARC_RA_REPLY_QUEUE_ERR)? 1:0;
921 0 : arc_scsi_cmd_done(sc, ccb, error);
922 : }
923 : }
924 0 : return (ret);
925 : }
926 :
927 : int
928 0 : arc_intr_C(void *arg)
929 : {
930 0 : struct arc_softc *sc = arg;
931 : struct arc_ccb *ccb = NULL;
932 0 : char *kva = ARC_DMA_KVA(sc->sc_requests);
933 : struct arc_io_cmd *cmd;
934 : u_int32_t reg, intrstat, obmsg, error;
935 : int ret = 0, throttling;
936 :
937 0 : intrstat = arc_read(sc, ARC_RC_INTR_STAT);
938 0 : if (!(intrstat & (ARC_RC_INTR_STAT_POSTQUEUE |
939 : ARC_RC_INTR_STAT_DOORBELL)))
940 0 : return (ret);
941 :
942 0 : if (intrstat & ARC_RC_INTR_STAT_DOORBELL) {
943 : ret = 1;
944 0 : if (sc->sc_talking) {
945 : /* if an ioctl is talking, wake it up */
946 0 : arc_write(sc, ARC_RC_INTR_MASK,
947 : ~ARC_RC_INTR_MASK_POSTQUEUE);
948 0 : wakeup(sc);
949 0 : } else {
950 : /* otherwise drop it */
951 0 : reg = arc_read(sc, ARC_RC_OUTB_DOORBELL);
952 0 : arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR, reg);
953 0 : if (reg & ARC_RC_I2D_DATA_WRITE_OK) {
954 0 : arc_write(sc, ARC_RC_INB_DOORBELL,
955 : ARC_RC_I2D_DATA_READ_OK);
956 0 : }
957 : /* if (reg & ARC_RC_I2D_DATA_READ_OK) {
958 : arc_write(sc, ARC_RC_INB_DOORBELL,
959 : ARC_RC_D2I_DATA_WRITE_OK);
960 : }
961 : */
962 0 : if (reg & ARC_RC_I2D_MESSAGE_CMD_DONE) {
963 0 : arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR,
964 : ARC_RC_I2D_MSG_CMD_DONE_CLR);
965 0 : obmsg = arc_read(sc, ARC_RC_MSG_RWBUF);
966 : if (obmsg == ARC_FWINFO_SIGNATURE_GET_CONFIG)
967 : ; /* handle devices hot-plug */
968 0 : }
969 :
970 : }
971 : }
972 :
973 0 : if (intrstat & ARC_RC_INTR_STAT_POSTQUEUE) {
974 : ret = 1;
975 : throttling = 0;
976 0 : while (arc_read(sc, ARC_RC_INTR_STAT) &
977 : ARC_RC_INTR_STAT_POSTQUEUE) {
978 0 : reg = arc_read(sc, ARC_RC_OUTB_REPLYQ_LOW);
979 0 : cmd = (struct arc_io_cmd *)(kva + ((reg & 0xFFFFFFE0) -
980 0 : (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
981 0 : ccb = cmd->ccb;
982 :
983 0 : bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
984 : ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
985 : BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
986 :
987 0 : error = (reg & ARC_RC_REPLY_QUEUE_ERR);
988 0 : arc_scsi_cmd_done(sc, ccb, error);
989 0 : throttling++;
990 0 : if(throttling == ARC_RC_THROTTLE) {
991 0 : arc_write(sc, ARC_RC_INB_DOORBELL,
992 : ARC_RC_D2I_POSTQUEUE_THROTTLING);
993 : throttling = 0;
994 0 : }
995 : }
996 : }
997 :
998 0 : return (ret);
999 0 : }
1000 :
1001 : static u_int16_t
1002 0 : arcmsr_get_doneq_index(struct arc_HBD_Msgu *phbdmu)
1003 : {
1004 : u_int16_t doneq_index, index_stripped;
1005 :
1006 0 : doneq_index = phbdmu->doneq_index;
1007 0 : if (doneq_index & 0x4000) {
1008 0 : index_stripped = doneq_index & 0xFF;
1009 0 : index_stripped += 1;
1010 0 : index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
1011 0 : phbdmu->doneq_index = index_stripped ?
1012 0 : (index_stripped | 0x4000) : index_stripped;
1013 0 : } else {
1014 : index_stripped = doneq_index;
1015 0 : index_stripped += 1;
1016 0 : index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
1017 0 : phbdmu->doneq_index = index_stripped ?
1018 0 : index_stripped : (index_stripped | 0x4000);
1019 : }
1020 0 : return (phbdmu->doneq_index);
1021 : }
1022 :
1023 : int
1024 0 : arc_intr_D(void *arg)
1025 : {
1026 0 : struct arc_softc *sc = arg;
1027 : struct arc_ccb *ccb = NULL;
1028 0 : char *kva = ARC_DMA_KVA(sc->sc_requests);
1029 : struct arc_io_cmd *cmd;
1030 : u_int32_t reg, intrstat, obmsg, error;
1031 : u_int32_t ob_write_ptr;
1032 : u_int16_t doneq_index;
1033 : int ret = 0;
1034 : struct arc_HBD_Msgu *pmu;
1035 :
1036 0 : intrstat = arc_read(sc, ARC_RD_INTR_STAT);
1037 0 : if (!(intrstat & (ARC_RD_INTR_STAT_POSTQUEUE |
1038 : ARC_RD_INTR_STAT_DOORBELL)))
1039 0 : return (ret);
1040 :
1041 0 : if (intrstat & ARC_RD_INTR_STAT_DOORBELL) {
1042 : ret = 1;
1043 0 : if (sc->sc_talking) {
1044 : /* if an ioctl is talking, wake it up */
1045 0 : arc_write(sc, ARC_RD_INTR_ENABLE,
1046 : ARC_RD_INTR_ENABLE_POSTQUEUE);
1047 0 : wakeup(sc);
1048 0 : } else {
1049 : /* otherwise drop it */
1050 0 : reg = arc_read(sc, ARC_RD_OUTB_DOORBELL);
1051 0 : arc_write(sc, ARC_RD_OUTB_DOORBELL, reg);
1052 0 : if (reg & ARC_RD_I2D_DATA_WRITE_OK) {
1053 0 : arc_write(sc, ARC_RD_INB_DOORBELL,
1054 : ARC_RD_I2D_DATA_READ_OK);
1055 0 : }
1056 : /* if (reg & ARC_RD_I2D_DATA_READ_OK) {
1057 : arc_write(sc, ARC_RD_INB_DOORBELL,
1058 : ARC_RD_D2I_DATA_WRITE_OK);
1059 : }
1060 : */
1061 0 : if (reg & ARC_RD_I2D_MESSAGE_CMD_DONE) {
1062 0 : arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR,
1063 : ARC_RD_I2D_MSG_CMD_DONE_CLR);
1064 0 : obmsg = arc_read(sc, ARC_RD_MSG_RWBUF);
1065 : if (obmsg == ARC_FWINFO_SIGNATURE_GET_CONFIG)
1066 : ; /* handle devices hot-plug */
1067 0 : }
1068 :
1069 : }
1070 : }
1071 :
1072 0 : if (intrstat & ARC_RD_INTR_STAT_POSTQUEUE) {
1073 : ret = 1;
1074 0 : arc_write(sc, ARC_RD_OUTB_INTR_CAUSE, ARC_RD_OUTB_LIST_INT_CLR);
1075 0 : bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
1076 : sc->cmdQ_ptr_offset, ARC_MAX_CMDQ_PTR_LEN,
1077 : BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1078 0 : pmu = sc->pmu;
1079 0 : ob_write_ptr = pmu->done_qbuffer[0].addressLow;
1080 0 : doneq_index = pmu->doneq_index;
1081 0 : while ((doneq_index & 0xFF) != (ob_write_ptr & 0xFF)) {
1082 0 : doneq_index = arcmsr_get_doneq_index(pmu);
1083 0 : reg = pmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
1084 0 : cmd = (struct arc_io_cmd *)(kva + ((reg & 0xFFFFFFF0) -
1085 0 : (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
1086 0 : ccb = cmd->ccb;
1087 0 : bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
1088 : ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
1089 : BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1090 0 : error = (reg & ARC_RD_REPLY_QUEUE_ERR);
1091 0 : arc_scsi_cmd_done(sc, ccb, error);
1092 0 : arc_write(sc, ARC_RD_OUTB_READ_PTR, doneq_index);
1093 0 : ob_write_ptr = pmu->done_qbuffer[0].addressLow;
1094 : }
1095 : }
1096 :
1097 0 : return (ret);
1098 0 : }
1099 :
1100 : int
1101 0 : arc_intr(void *arg)
1102 : {
1103 0 : struct arc_softc *sc = arg;
1104 : int ret = 0;
1105 :
1106 0 : switch(sc->sc_adp_type) {
1107 : case ARC_HBA_TYPE_A:
1108 0 : ret = arc_intr_A(arg);
1109 0 : break;
1110 : case ARC_HBA_TYPE_C:
1111 0 : ret = arc_intr_C(arg);
1112 0 : break;
1113 : case ARC_HBA_TYPE_D:
1114 0 : ret = arc_intr_D(arg);
1115 0 : break;
1116 : }
1117 0 : return (ret);
1118 : }
1119 :
1120 : void
1121 0 : arc_scsi_cmd(struct scsi_xfer *xs)
1122 : {
1123 0 : struct scsi_link *link = xs->sc_link;
1124 0 : struct arc_softc *sc = link->adapter_softc;
1125 : struct arc_ccb *ccb;
1126 : struct arc_msg_scsicmd *cmd;
1127 : u_int32_t reg, cdb_len;
1128 : int s;
1129 : struct arc_HBD_Msgu *pmu;
1130 : u_int16_t index_stripped;
1131 : u_int16_t postq_index;
1132 : struct InBound_SRB *pinbound_srb;
1133 :
1134 0 : if (xs->cmdlen > ARC_MSG_CDBLEN) {
1135 0 : bzero(&xs->sense, sizeof(xs->sense));
1136 0 : xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
1137 0 : xs->sense.flags = SKEY_ILLEGAL_REQUEST;
1138 0 : xs->sense.add_sense_code = 0x20;
1139 0 : xs->error = XS_SENSE;
1140 0 : scsi_done(xs);
1141 0 : return;
1142 : }
1143 :
1144 0 : ccb = xs->io;
1145 0 : ccb->ccb_xs = xs;
1146 :
1147 0 : if (arc_load_xs(ccb) != 0) {
1148 0 : xs->error = XS_DRIVER_STUFFUP;
1149 0 : scsi_done(xs);
1150 0 : return;
1151 : }
1152 :
1153 0 : cmd = &ccb->ccb_cmd->cmd;
1154 0 : reg = ccb->ccb_cmd_post;
1155 0 : ccb->ccb_cmd->ccb = ccb;
1156 : /* bus is always 0 */
1157 0 : cmd->target = link->target;
1158 0 : cmd->lun = link->lun;
1159 0 : cmd->function = 1; /* XXX magic number */
1160 :
1161 0 : cmd->cdb_len = xs->cmdlen;
1162 0 : cmd->sgl_len = ccb->ccb_dmamap->dm_nsegs;
1163 0 : if (xs->flags & SCSI_DATA_OUT)
1164 0 : cmd->flags = ARC_MSG_SCSICMD_FLAG_WRITE;
1165 0 : if (ccb->ccb_dmamap->dm_nsegs > ARC_SGL_256LEN) {
1166 0 : cmd->flags |= ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512;
1167 : /* reg |= ARC_RA_POST_QUEUE_BIGFRAME; */
1168 0 : }
1169 :
1170 0 : cmd->data_len = htole32(xs->datalen);
1171 :
1172 0 : bcopy(xs->cmd, cmd->cdb, xs->cmdlen);
1173 :
1174 : /* we've built the command, let's put it on the hw */
1175 0 : bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
1176 : ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
1177 : BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1178 :
1179 0 : s = splbio();
1180 0 : switch(sc->sc_adp_type) {
1181 : case ARC_HBA_TYPE_A:
1182 0 : if (cmd->flags & ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512)
1183 0 : reg |= ARC_RA_POST_QUEUE_BIGFRAME;
1184 0 : arc_write(sc, ARC_RA_POST_QUEUE, reg);
1185 0 : break;
1186 : case ARC_HBA_TYPE_C:
1187 0 : cdb_len = sizeof(struct arc_msg_scsicmd) +
1188 0 : sizeof(struct arc_sge) * ccb->ccb_dmamap->dm_nsegs;
1189 0 : if (cdb_len > 0x300)
1190 : cdb_len = 0x300;
1191 0 : reg = reg | ((cdb_len - 1) >> 6) | 1;
1192 0 : if (sc->sc_ccb_phys_hi)
1193 0 : arc_write(sc, ARC_RC_INB_POSTQ_HIGH, sc->sc_ccb_phys_hi);
1194 0 : arc_write(sc, ARC_RC_INB_POSTQ_LOW, reg);
1195 0 : break;
1196 : case ARC_HBA_TYPE_D:
1197 0 : pmu = sc->pmu;
1198 0 : postq_index = pmu->postq_index;
1199 0 : pinbound_srb = (struct InBound_SRB *)&pmu->post_qbuffer[postq_index & 0xFF];
1200 :
1201 0 : pinbound_srb->addressHigh = sc->sc_ccb_phys_hi;
1202 0 : pinbound_srb->addressLow = ccb->ccb_cmd_post;
1203 0 : pinbound_srb->length = ccb->arc_io_cmd_length >> 2;
1204 0 : cmd->context = ccb->ccb_cmd_post;
1205 0 : if (postq_index & 0x4000) {
1206 0 : index_stripped = postq_index & 0xFF;
1207 0 : index_stripped += 1;
1208 0 : index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
1209 0 : pmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped;
1210 0 : } else {
1211 : index_stripped = postq_index;
1212 0 : index_stripped += 1;
1213 0 : index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
1214 0 : pmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000);
1215 : }
1216 0 : bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
1217 : sc->cmdQ_ptr_offset, ARC_MAX_CMDQ_PTR_LEN,
1218 : BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1219 0 : arc_write(sc, ARC_RD_INB_WRITE_PTR, postq_index);
1220 0 : break;
1221 : }
1222 0 : if (xs->flags & SCSI_POLL) {
1223 0 : if (arc_complete(sc, ccb, xs->timeout) != 0) {
1224 0 : xs->error = XS_DRIVER_STUFFUP;
1225 0 : scsi_done(xs);
1226 0 : }
1227 : }
1228 0 : splx(s);
1229 0 : }
1230 :
1231 : int
1232 0 : arc_load_xs(struct arc_ccb *ccb)
1233 : {
1234 0 : struct arc_softc *sc = ccb->ccb_sc;
1235 0 : struct scsi_xfer *xs = ccb->ccb_xs;
1236 0 : bus_dmamap_t dmap = ccb->ccb_dmamap;
1237 0 : struct arc_sge *sgl = ccb->ccb_cmd->sgl, *sge;
1238 : u_int64_t addr;
1239 : int i, error;
1240 : u_int32_t msg_length;
1241 :
1242 0 : if (xs->datalen == 0)
1243 : {
1244 0 : ccb->arc_io_cmd_length = sizeof(struct arc_msg_scsicmd);
1245 0 : ccb->ccb_cmd->cmd.msgPages = 1;
1246 0 : return (0);
1247 : }
1248 0 : error = bus_dmamap_load(sc->sc_dmat, dmap,
1249 : xs->data, xs->datalen, NULL,
1250 : (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
1251 0 : if (error != 0) {
1252 0 : printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
1253 0 : return (1);
1254 : }
1255 :
1256 0 : for (i = 0; i < dmap->dm_nsegs; i++) {
1257 0 : sge = &sgl[i];
1258 :
1259 0 : sge->sg_length = htole32(ARC_SGE_64BIT | dmap->dm_segs[i].ds_len);
1260 0 : addr = dmap->dm_segs[i].ds_addr;
1261 0 : sge->sg_hi_addr = htole32((u_int32_t)(addr >> 32));
1262 0 : sge->sg_lo_addr = htole32((u_int32_t)addr);
1263 : }
1264 0 : ccb->arc_io_cmd_length = sizeof(struct arc_msg_scsicmd) +
1265 0 : sizeof(struct arc_sge) * dmap->dm_nsegs;
1266 : msg_length = ccb->arc_io_cmd_length;
1267 0 : ccb->ccb_cmd->cmd.msgPages = (msg_length/256) + ((msg_length % 256) ? 1 : 0);
1268 :
1269 0 : bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
1270 : (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1271 : BUS_DMASYNC_PREWRITE);
1272 :
1273 0 : return (0);
1274 0 : }
1275 :
1276 : void
1277 0 : arc_scsi_cmd_done(struct arc_softc *sc, struct arc_ccb *ccb, u_int32_t error)
1278 : {
1279 0 : struct scsi_xfer *xs = ccb->ccb_xs;
1280 : struct arc_msg_scsicmd *cmd;
1281 :
1282 0 : if (xs->datalen != 0) {
1283 0 : bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
1284 : ccb->ccb_dmamap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?
1285 : BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1286 0 : bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
1287 0 : }
1288 :
1289 0 : if (error) {
1290 0 : cmd = &ccb->ccb_cmd->cmd;
1291 : DPRINTF("%s: arc_scsi_cmd_done error! target 0x%x, lun 0x%x, "
1292 : "status = 0x%x\n", DEVNAME(sc), cmd->target, cmd->lun,
1293 : cmd->status);
1294 : DPRINTF("%s: scsi cdb: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x"
1295 : ", 0x%x, 0x%x, 0x%x\n", DEVNAME(sc), cmd->cdb[0], cmd->cdb[1],
1296 : cmd->cdb[2], cmd->cdb[3],cmd->cdb[4], cmd->cdb[5],
1297 : cmd->cdb[6], cmd->cdb[7],cmd->cdb[8], cmd->cdb[9]);
1298 :
1299 0 : switch (cmd->status) {
1300 : case ARC_MSG_STATUS_SELTIMEOUT:
1301 : case ARC_MSG_STATUS_ABORTED:
1302 : case ARC_MSG_STATUS_INIT_FAIL:
1303 0 : xs->status = SCSI_OK;
1304 0 : xs->error = XS_SELTIMEOUT;
1305 0 : break;
1306 :
1307 : case SCSI_CHECK:
1308 0 : bzero(&xs->sense, sizeof(xs->sense));
1309 0 : bcopy(cmd->sense_data, &xs->sense,
1310 0 : min(ARC_MSG_SENSELEN, sizeof(xs->sense)));
1311 0 : xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
1312 0 : xs->status = SCSI_CHECK;
1313 0 : xs->error = XS_SENSE;
1314 0 : xs->resid = 0;
1315 0 : break;
1316 :
1317 : default:
1318 : /* unknown device status */
1319 0 : xs->error = XS_BUSY; /* try again later? */
1320 0 : xs->status = SCSI_BUSY;
1321 0 : break;
1322 : }
1323 : } else {
1324 0 : xs->status = SCSI_OK;
1325 0 : xs->error = XS_NOERROR;
1326 0 : xs->resid = 0;
1327 : }
1328 :
1329 0 : scsi_done(xs);
1330 0 : }
1331 :
1332 : int
1333 0 : arc_complete(struct arc_softc *sc, struct arc_ccb *nccb, int timeout)
1334 : {
1335 : struct arc_ccb *ccb = NULL;
1336 0 : char *kva = ARC_DMA_KVA(sc->sc_requests);
1337 : struct arc_io_cmd *cmd;
1338 : u_int32_t reg, error, write_ptr;
1339 : u_int16_t doneq_index;
1340 : struct arc_HBD_Msgu *phbdmu;
1341 : int ret = 0;
1342 :
1343 0 : arc_disable_all_intr(sc);
1344 0 : do {
1345 0 : switch(sc->sc_adp_type) {
1346 : case ARC_HBA_TYPE_A:
1347 0 : reg = arc_read(sc, ARC_RA_REPLY_QUEUE);
1348 0 : error = (reg & ARC_RA_REPLY_QUEUE_ERR)? 1:0;
1349 0 : break;
1350 : case ARC_HBA_TYPE_C:
1351 0 : reg = arc_read(sc, ARC_RC_OUTB_REPLYQ_LOW);
1352 0 : error = (reg & ARC_RC_REPLY_QUEUE_ERR);
1353 0 : break;
1354 : case ARC_HBA_TYPE_D:
1355 0 : phbdmu = sc->pmu;
1356 0 : write_ptr = phbdmu->done_qbuffer[0].addressLow;
1357 0 : doneq_index = phbdmu->doneq_index;
1358 0 : if((write_ptr & 0xff) == (doneq_index & 0xff)) {
1359 : Loop0:
1360 : reg = 0xffffffff;
1361 0 : }
1362 : else {
1363 0 : doneq_index = arcmsr_get_doneq_index(phbdmu);
1364 0 : reg = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
1365 0 : if (reg == 0)
1366 : goto Loop0;
1367 0 : arc_write(sc, ARC_RD_OUTB_READ_PTR, doneq_index);
1368 : }
1369 0 : error = (reg & ARC_RD_REPLY_QUEUE_ERR);
1370 0 : break;
1371 : }
1372 0 : if (reg == 0xffffffff) {
1373 0 : if (timeout-- == 0) {
1374 0 : return (1);
1375 : }
1376 0 : delay(1000);
1377 0 : continue;
1378 : }
1379 :
1380 0 : switch(sc->sc_adp_type) {
1381 : case ARC_HBA_TYPE_A:
1382 0 : cmd = (struct arc_io_cmd *)(kva +
1383 0 : ((reg << ARC_RA_REPLY_QUEUE_ADDR_SHIFT) -
1384 0 : ARC_DMA_DVA(sc->sc_requests)));
1385 0 : break;
1386 : case ARC_HBA_TYPE_C:
1387 : case ARC_HBA_TYPE_D:
1388 0 : cmd = (struct arc_io_cmd *)(kva + ((reg & 0xFFFFFFE0) -
1389 0 : ARC_DMA_DVA(sc->sc_requests)));
1390 0 : break;
1391 : }
1392 0 : ccb = cmd->ccb;
1393 :
1394 0 : bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
1395 : ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
1396 : BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1397 :
1398 0 : arc_scsi_cmd_done(sc, ccb, error);
1399 :
1400 0 : } while (nccb != ccb);
1401 0 : arc_enable_all_intr(sc);
1402 :
1403 0 : return (ret);
1404 0 : }
1405 :
1406 : void
1407 0 : arc_minphys(struct buf *bp, struct scsi_link *sl)
1408 : {
1409 0 : if (bp->b_bcount > MAXPHYS)
1410 0 : bp->b_bcount = MAXPHYS;
1411 0 : minphys(bp);
1412 0 : }
1413 :
1414 : void
1415 0 : arc_enable_all_intr(struct arc_softc *sc)
1416 : {
1417 : u_int32_t int_mask;
1418 :
1419 0 : switch(sc->sc_adp_type) {
1420 : case ARC_HBA_TYPE_A:
1421 0 : int_mask = arc_read(sc, ARC_RA_INTRMASK);
1422 0 : int_mask &= ~(ARC_RA_INTRMASK_POSTQUEUE |
1423 : ARC_RA_INTRMASK_DOORBELL | ARC_RA_INTRMASK_MSG0);
1424 0 : arc_write(sc, ARC_RA_INTRMASK, int_mask);
1425 0 : break;
1426 : case ARC_HBA_TYPE_C:
1427 0 : int_mask = arc_read(sc, ARC_RC_INTR_MASK);
1428 0 : int_mask &= ~(ARC_RC_INTR_MASK_POSTQUEUE |
1429 : ARC_RC_INTR_MASK_DOORBELL | ARC_RC_INTR_MASK_UTILITY_A);
1430 0 : arc_write(sc, ARC_RC_INTR_MASK, int_mask);
1431 0 : break;
1432 : case ARC_HBA_TYPE_D:
1433 0 : int_mask = arc_read(sc, ARC_RD_INTR_ENABLE);
1434 0 : int_mask |= ARC_RD_INTR_ENABLE_ALL;
1435 0 : arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
1436 0 : break;
1437 : }
1438 0 : }
1439 :
1440 : void
1441 0 : arc_disable_all_intr(struct arc_softc *sc)
1442 : {
1443 : u_int32_t int_mask;
1444 :
1445 0 : switch(sc->sc_adp_type) {
1446 : case ARC_HBA_TYPE_A:
1447 0 : int_mask = arc_read(sc, ARC_RA_INTRMASK);
1448 0 : int_mask |= ARC_RA_INTR_MASK_ALL;
1449 0 : arc_write(sc, ARC_RA_INTRMASK, int_mask);
1450 0 : break;
1451 : case ARC_HBA_TYPE_C:
1452 0 : int_mask = arc_read(sc, ARC_RC_INTR_MASK);
1453 0 : int_mask |= ARC_RC_INTR_MASK_ALL;
1454 0 : arc_write(sc, ARC_RC_INTR_MASK, int_mask);
1455 0 : break;
1456 : case ARC_HBA_TYPE_D:
1457 0 : int_mask = arc_read(sc, ARC_RD_INTR_ENABLE);
1458 : int_mask &= ~ARC_RD_INTR_ENABLE_ALL;
1459 0 : arc_write(sc, ARC_RD_INTR_ENABLE, ARC_RD_INTR_DISABLE_ALL);
1460 0 : break;
1461 : }
1462 0 : }
1463 :
1464 : int
1465 0 : arc_map_pci_resources(struct arc_softc *sc, struct pci_attach_args *pa)
1466 : {
1467 : pcireg_t memtype;
1468 0 : pci_intr_handle_t ih;
1469 :
1470 0 : sc->sc_pc = pa->pa_pc;
1471 0 : sc->sc_tag = pa->pa_tag;
1472 0 : sc->sc_dmat = pa->pa_dmat;
1473 :
1474 0 : switch(sc->sc_adp_type) {
1475 : case ARC_HBA_TYPE_A:
1476 0 : memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, ARC_RA_PCI_BAR);
1477 0 : if (pci_mapreg_map(pa, ARC_RA_PCI_BAR, memtype, 0, &sc->sc_iot,
1478 0 : &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
1479 0 : printf(": unable to map ARC_HBA_TYPE_A system"
1480 : " interface register\n");
1481 0 : return(1);
1482 : }
1483 : break;
1484 : case ARC_HBA_TYPE_C:
1485 0 : memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, ARC_RC_PCI_BAR);
1486 0 : if (pci_mapreg_map(pa, ARC_RC_PCI_BAR, memtype, 0, &sc->sc_iot,
1487 0 : &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
1488 0 : printf(": unable to map ARC_HBA_TYPE_C system"
1489 : " interface register\n");
1490 0 : return(1);
1491 : }
1492 : break;
1493 : case ARC_HBA_TYPE_D:
1494 0 : memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, ARC_RD_PCI_BAR);
1495 0 : if (pci_mapreg_map(pa, ARC_RD_PCI_BAR, memtype, 0, &sc->sc_iot,
1496 0 : &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
1497 0 : printf(": unable to map ARC_HBA_TYPE_D system"
1498 : " interface register\n");
1499 0 : return(1);
1500 : }
1501 : break;
1502 : }
1503 :
1504 0 : arc_disable_all_intr(sc);
1505 :
1506 0 : if (pci_intr_map(pa, &ih) != 0) {
1507 0 : printf(": unable to map interrupt\n");
1508 0 : goto unmap;
1509 : }
1510 0 : sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
1511 0 : arc_intr, sc, DEVNAME(sc));
1512 0 : if (sc->sc_ih == NULL) {
1513 0 : printf(": unable to map interrupt\n");
1514 0 : goto unmap;
1515 : }
1516 0 : printf(": %s\n", pci_intr_string(pa->pa_pc, ih));
1517 :
1518 0 : return (0);
1519 :
1520 : unmap:
1521 0 : bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
1522 0 : sc->sc_ios = 0;
1523 0 : return (1);
1524 0 : }
1525 :
1526 : void
1527 0 : arc_unmap_pci_resources(struct arc_softc *sc)
1528 : {
1529 0 : pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
1530 0 : bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
1531 0 : sc->sc_ios = 0;
1532 0 : }
1533 :
1534 : int
1535 0 : arc_chipA_firmware(struct arc_softc *sc)
1536 : {
1537 0 : struct arc_msg_firmware_info fwinfo;
1538 0 : char string[81]; /* sizeof(vendor)*2+1 */
1539 : u_int32_t ob_doorbell;
1540 :
1541 0 : if (arc_wait_eq(sc, ARC_RA_OUTB_ADDR1, ARC_RA_OUTB_ADDR1_FIRMWARE_OK,
1542 0 : ARC_RA_OUTB_ADDR1_FIRMWARE_OK) != 0) {
1543 0 : printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
1544 0 : return (1);
1545 : }
1546 :
1547 0 : if (arc_msg0(sc, ARC_RA_INB_MSG0_GET_CONFIG) != 0) {
1548 0 : printf("%s: timeout waiting for get config\n", DEVNAME(sc));
1549 0 : return (1);
1550 : }
1551 :
1552 0 : arc_read_region(sc, ARC_RA_MSGBUF, &fwinfo, sizeof(fwinfo));
1553 :
1554 : DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n", DEVNAME(sc),
1555 : letoh32(fwinfo.signature));
1556 :
1557 0 : if (letoh32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
1558 0 : printf("%s: invalid firmware info from iop\n", DEVNAME(sc));
1559 0 : return (1);
1560 : }
1561 :
1562 : DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n", DEVNAME(sc),
1563 : letoh32(fwinfo.request_len));
1564 : DNPRINTF(ARC_D_INIT, "%s: queue_len: %d\n", DEVNAME(sc),
1565 : letoh32(fwinfo.queue_len));
1566 : DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n", DEVNAME(sc),
1567 : letoh32(fwinfo.sdram_size));
1568 : DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n", DEVNAME(sc),
1569 : letoh32(fwinfo.sata_ports), letoh32(fwinfo.sata_ports));
1570 :
1571 0 : scsi_strvis(string, fwinfo.vendor, sizeof(fwinfo.vendor));
1572 : DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n", DEVNAME(sc), string);
1573 0 : scsi_strvis(string, fwinfo.model, sizeof(fwinfo.model));
1574 : DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
1575 :
1576 0 : scsi_strvis(string, fwinfo.fw_version, sizeof(fwinfo.fw_version));
1577 : DNPRINTF(ARC_D_INIT, "%s: firmware: \"%s\"\n", DEVNAME(sc), string);
1578 :
1579 0 : if (letoh32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
1580 0 : printf("%s: unexpected request frame size (%d != %d)\n",
1581 0 : DEVNAME(sc), letoh32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
1582 0 : return (1);
1583 : }
1584 :
1585 0 : sc->sc_req_count = letoh32(fwinfo.queue_len);
1586 :
1587 0 : if (arc_msg0(sc, ARC_RA_INB_MSG0_START_BGRB) != 0) {
1588 0 : printf("%s: timeout waiting to start bg rebuild\n",
1589 0 : DEVNAME(sc));
1590 0 : return (1);
1591 : }
1592 :
1593 : /* clear doorbell buffer */
1594 0 : ob_doorbell = arc_read(sc, ARC_RA_OUTB_DOORBELL);
1595 0 : arc_write(sc, ARC_RA_OUTB_DOORBELL, ob_doorbell);
1596 0 : arc_write(sc, ARC_RA_INB_DOORBELL, ARC_RA_INB_DOORBELL_READ_OK);
1597 :
1598 0 : printf("%s: %d ports, %dMB SDRAM, firmware %s\n",
1599 0 : DEVNAME(sc), letoh32(fwinfo.sata_ports),
1600 0 : letoh32(fwinfo.sdram_size), string);
1601 :
1602 0 : return (0);
1603 0 : }
1604 :
1605 : int
1606 0 : arc_chipB_firmware(struct arc_softc *sc)
1607 : {
1608 0 : if (arc_wait_eq(sc, ARC_RB_IOP2DRV_DOORBELL,
1609 : ARC_RA_OUTB_ADDR1_FIRMWARE_OK,
1610 0 : ARC_RA_OUTB_ADDR1_FIRMWARE_OK) != 0) {
1611 0 : printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
1612 0 : return (1);
1613 : }
1614 :
1615 0 : return (1);
1616 0 : }
1617 :
1618 : int
1619 0 : arc_chipC_firmware(struct arc_softc *sc)
1620 : {
1621 0 : struct arc_msg_firmware_info fwinfo;
1622 0 : char string[81]; /* sizeof(vendor)*2+1 */
1623 : u_int32_t ob_doorbell;
1624 :
1625 0 : if (arc_wait_eq(sc, ARC_RC_OUTB_MSGADDR1, ARC_RC_OUTB_MSG_FIRMWARE_OK,
1626 0 : ARC_RC_OUTB_MSG_FIRMWARE_OK) != 0) {
1627 0 : printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
1628 0 : return (1);
1629 : }
1630 :
1631 0 : if (arc_msg0(sc, ARC_RC_INB_MSG0_GET_CONFIG) != 0) {
1632 0 : printf("%s: timeout waiting for get config\n", DEVNAME(sc));
1633 0 : return (1);
1634 : }
1635 :
1636 0 : arc_read_region(sc, ARC_RC_MSG_RWBUF, &fwinfo, sizeof(fwinfo));
1637 :
1638 : DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n", DEVNAME(sc),
1639 : letoh32(fwinfo.signature));
1640 :
1641 0 : if (letoh32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
1642 0 : printf("%s: invalid firmware info from iop\n", DEVNAME(sc));
1643 0 : return (1);
1644 : }
1645 :
1646 : DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n", DEVNAME(sc),
1647 : letoh32(fwinfo.request_len));
1648 : DNPRINTF(ARC_D_INIT, "%s: queue_len: %d\n", DEVNAME(sc),
1649 : letoh32(fwinfo.queue_len));
1650 : DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n", DEVNAME(sc),
1651 : letoh32(fwinfo.sdram_size));
1652 : DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n", DEVNAME(sc),
1653 : letoh32(fwinfo.sata_ports), letoh32(fwinfo.sata_ports));
1654 :
1655 0 : scsi_strvis(string, fwinfo.vendor, sizeof(fwinfo.vendor));
1656 : DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n", DEVNAME(sc), string);
1657 0 : scsi_strvis(string, fwinfo.model, sizeof(fwinfo.model));
1658 : DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
1659 :
1660 0 : scsi_strvis(string, fwinfo.fw_version, sizeof(fwinfo.fw_version));
1661 : DNPRINTF(ARC_D_INIT, "%s: firmware: \"%s\"\n", DEVNAME(sc), string);
1662 :
1663 0 : if (letoh32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
1664 0 : printf("%s: unexpected request frame size (%d != %d)\n",
1665 0 : DEVNAME(sc), letoh32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
1666 0 : return (1);
1667 : }
1668 :
1669 0 : sc->sc_req_count = letoh32(fwinfo.queue_len);
1670 :
1671 0 : if (arc_msg0(sc, ARC_RC_INB_MSG0_START_BGRB) != 0) {
1672 0 : printf("%s: timeout waiting to start bg rebuild\n",
1673 0 : DEVNAME(sc));
1674 0 : return (1);
1675 : }
1676 :
1677 : /* clear doorbell buffer */
1678 0 : ob_doorbell = arc_read(sc, ARC_RC_OUTB_DOORBELL);
1679 0 : arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR, ob_doorbell);
1680 0 : arc_write(sc, ARC_RC_INB_DOORBELL, ARC_RC_D2I_DATA_READ_OK);
1681 :
1682 0 : printf("%s: %d ports, %dMB SDRAM, firmware %s\n",
1683 0 : DEVNAME(sc), letoh32(fwinfo.sata_ports),
1684 0 : letoh32(fwinfo.sdram_size), string);
1685 :
1686 0 : return (0);
1687 0 : }
1688 :
1689 : int
1690 0 : arc_chipD_firmware(struct arc_softc *sc)
1691 : {
1692 0 : struct arc_msg_firmware_info fwinfo;
1693 0 : char string[81]; /* sizeof(vendor)*2+1 */
1694 : u_int32_t ob_doorbell;
1695 :
1696 0 : if (arc_wait_eq(sc, ARC_RD_OUTB_MSGADDR1, ARC_RD_OUTB_MSG_FIRMWARE_OK,
1697 0 : ARC_RD_OUTB_MSG_FIRMWARE_OK) != 0) {
1698 0 : printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
1699 0 : return (1);
1700 : }
1701 :
1702 0 : if ((arc_read(sc, ARC_RD_OUTB_DOORBELL) & ARC_RD_I2D_MESSAGE_CMD_DONE))
1703 0 : arc_write(sc, ARC_RD_OUTB_DOORBELL, ARC_RD_I2D_MESSAGE_CMD_DONE_CLEAR);
1704 :
1705 0 : if (arc_msg0(sc, ARC_RD_INB_MSG0_GET_CONFIG) != 0) {
1706 0 : printf("%s: timeout waiting for get config\n", DEVNAME(sc));
1707 0 : return (1);
1708 : }
1709 :
1710 0 : arc_read_region(sc, ARC_RD_MSG_RWBUF, &fwinfo, sizeof(fwinfo));
1711 :
1712 : DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n", DEVNAME(sc),
1713 : letoh32(fwinfo.signature));
1714 :
1715 0 : if (letoh32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
1716 0 : printf("%s: invalid firmware info from iop\n", DEVNAME(sc));
1717 0 : return (1);
1718 : }
1719 :
1720 : DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n", DEVNAME(sc),
1721 : letoh32(fwinfo.request_len));
1722 : DNPRINTF(ARC_D_INIT, "%s: queue_len: %d\n", DEVNAME(sc),
1723 : letoh32(fwinfo.queue_len));
1724 : DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n", DEVNAME(sc),
1725 : letoh32(fwinfo.sdram_size));
1726 : DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n", DEVNAME(sc),
1727 : letoh32(fwinfo.sata_ports), letoh32(fwinfo.sata_ports));
1728 :
1729 0 : scsi_strvis(string, fwinfo.vendor, sizeof(fwinfo.vendor));
1730 : DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n", DEVNAME(sc), string);
1731 0 : scsi_strvis(string, fwinfo.model, sizeof(fwinfo.model));
1732 : DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
1733 :
1734 0 : scsi_strvis(string, fwinfo.fw_version, sizeof(fwinfo.fw_version));
1735 : DNPRINTF(ARC_D_INIT, "%s: firmware: \"%s\"\n", DEVNAME(sc), string);
1736 :
1737 0 : if (letoh32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
1738 0 : printf("%s: unexpected request frame size (%d != %d)\n",
1739 0 : DEVNAME(sc), letoh32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
1740 0 : return (1);
1741 : }
1742 :
1743 0 : sc->sc_req_count = letoh32(fwinfo.queue_len) - 1;
1744 :
1745 0 : if (arc_msg0(sc, ARC_RD_INB_MSG0_START_BGRB) != 0) {
1746 0 : printf("%s: timeout waiting to start bg rebuild\n",
1747 0 : DEVNAME(sc));
1748 0 : return (1);
1749 : }
1750 :
1751 : /* clear doorbell buffer */
1752 0 : ob_doorbell = arc_read(sc, ARC_RD_OUTB_DOORBELL);
1753 0 : arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR, ob_doorbell);
1754 0 : arc_write(sc, ARC_RD_INB_DOORBELL, ARC_RD_D2I_DATA_READ_OK);
1755 :
1756 0 : printf("%s: %d ports, %dMB SDRAM, firmware %s\n",
1757 0 : DEVNAME(sc), letoh32(fwinfo.sata_ports),
1758 0 : letoh32(fwinfo.sdram_size), string);
1759 :
1760 0 : return (0);
1761 0 : }
1762 :
1763 : void
1764 0 : arc_stop_bgrb_proc(struct arc_softc *sc)
1765 : {
1766 0 : switch(sc->sc_adp_type) {
1767 : case ARC_HBA_TYPE_A:
1768 0 : if (arc_msg0(sc, ARC_RA_INB_MSG0_STOP_BGRB) != 0)
1769 0 : printf("%s: timeout waiting to stop bg rebuild\n",
1770 0 : DEVNAME(sc));
1771 : break;
1772 : case ARC_HBA_TYPE_C:
1773 0 : if (arc_msg0(sc, ARC_RC_INB_MSG0_STOP_BGRB) != 0)
1774 0 : printf("%s: timeout waiting to stop bg rebuild\n",
1775 0 : DEVNAME(sc));
1776 : break;
1777 : case ARC_HBA_TYPE_D:
1778 0 : if (arc_msg0(sc, ARC_RD_INB_MSG0_STOP_BGRB) != 0)
1779 0 : printf("%s: timeout waiting to stop bg rebuild\n",
1780 0 : DEVNAME(sc));
1781 : break;
1782 : }
1783 0 : }
1784 :
1785 : void
1786 0 : arc_flush_cache(struct arc_softc *sc)
1787 : {
1788 0 : switch(sc->sc_adp_type) {
1789 : case ARC_HBA_TYPE_A:
1790 0 : if (arc_msg0(sc, ARC_RA_INB_MSG0_FLUSH_CACHE) != 0)
1791 0 : printf("%s: timeout waiting to flush cache\n",
1792 0 : DEVNAME(sc));
1793 : break;
1794 : case ARC_HBA_TYPE_C:
1795 0 : if (arc_msg0(sc, ARC_RC_INB_MSG0_FLUSH_CACHE) != 0)
1796 0 : printf("%s: timeout waiting to flush cache\n",
1797 0 : DEVNAME(sc));
1798 : break;
1799 : case ARC_HBA_TYPE_D:
1800 0 : if (arc_msg0(sc, ARC_RD_INB_MSG0_FLUSH_CACHE) != 0)
1801 0 : printf("%s: timeout waiting to flush cache\n",
1802 0 : DEVNAME(sc));
1803 : break;
1804 : }
1805 0 : }
1806 :
1807 : void
1808 0 : arc_iop_set_conf(struct arc_softc *sc)
1809 : {
1810 : u_int32_t ccb_phys_hi;
1811 : struct arc_HBD_Msgu *phbdmu;
1812 :
1813 0 : ccb_phys_hi = sc->sc_ccb_phys_hi;
1814 0 : switch (sc->sc_adp_type) {
1815 : case ARC_HBA_TYPE_A:
1816 0 : arc_write(sc, ARC_RA_MSGBUF, ARC_FWINFO_SIGNATURE_SET_CONFIG);
1817 0 : arc_write(sc, ARC_RA_MSGBUF+1, ccb_phys_hi);
1818 0 : arc_msg0(sc, ARC_RA_INB_MSG0_SET_CONFIG);
1819 0 : break;
1820 : case ARC_HBA_TYPE_C:
1821 0 : arc_write(sc, ARC_RC_MSG_RWBUF, ARC_FWINFO_SIGNATURE_SET_CONFIG);
1822 0 : arc_write(sc, ARC_RC_MSG_RWBUF+1, ccb_phys_hi);
1823 0 : arc_msg0(sc, ARC_RC_INB_MSG0_SET_CONFIG);
1824 0 : break;
1825 : case ARC_HBA_TYPE_D:
1826 0 : phbdmu = sc->pmu;
1827 0 : phbdmu->postq_index = 0;
1828 0 : phbdmu->doneq_index = 0x40FF;
1829 0 : arc_write(sc, ARC_RD_MSG_RWBUF, ARC_FWINFO_SIGNATURE_SET_CONFIG);
1830 0 : arc_write(sc, ARC_RD_MSG_RWBUF+4, ccb_phys_hi);
1831 0 : arc_write(sc, ARC_RD_MSG_RWBUF+8, sc->postQ_buffer);
1832 0 : arc_write(sc, ARC_RD_MSG_RWBUF+12, sc->doneQ_buffer);
1833 0 : arc_write(sc, ARC_RD_MSG_RWBUF+16, 0x100);
1834 0 : arc_msg0(sc, ARC_RD_INB_MSG0_SET_CONFIG);
1835 0 : break;
1836 : }
1837 0 : }
1838 :
1839 : #if NBIO > 0
1840 : int
1841 0 : arc_bioctl(struct device *self, u_long cmd, caddr_t addr)
1842 : {
1843 0 : struct arc_softc *sc = (struct arc_softc *)self;
1844 : int error = 0;
1845 :
1846 : DPRINTF("%s: arc_bioctl\n", DEVNAME(sc));
1847 0 : switch (cmd) {
1848 : case BIOCINQ:
1849 0 : error = arc_bio_inq(sc, (struct bioc_inq *)addr);
1850 0 : break;
1851 :
1852 : case BIOCVOL:
1853 0 : error = arc_bio_vol(sc, (struct bioc_vol *)addr);
1854 0 : break;
1855 :
1856 : case BIOCDISK:
1857 0 : error = arc_bio_disk(sc, (struct bioc_disk *)addr);
1858 0 : break;
1859 :
1860 : case BIOCALARM:
1861 0 : error = arc_bio_alarm(sc, (struct bioc_alarm *)addr);
1862 0 : break;
1863 :
1864 : case BIOCBLINK:
1865 0 : error = arc_bio_blink(sc, (struct bioc_blink *)addr);
1866 0 : break;
1867 :
1868 : default:
1869 : error = ENOTTY;
1870 0 : break;
1871 : }
1872 :
1873 0 : return (error);
1874 : }
1875 :
1876 : int
1877 0 : arc_bio_alarm(struct arc_softc *sc, struct bioc_alarm *ba)
1878 : {
1879 0 : u_int8_t request[2];
1880 0 : u_int8_t reply[1];
1881 : size_t len;
1882 : int error = 0;
1883 :
1884 : DPRINTF("%s: arc_bio_alarm\n", DEVNAME(sc));
1885 0 : switch (ba->ba_opcode) {
1886 : case BIOC_SAENABLE:
1887 : case BIOC_SADISABLE:
1888 0 : request[0] = ARC_FW_SET_ALARM;
1889 0 : request[1] = (ba->ba_opcode == BIOC_SAENABLE) ?
1890 : ARC_FW_SET_ALARM_ENABLE : ARC_FW_SET_ALARM_DISABLE;
1891 : len = sizeof(request);
1892 :
1893 0 : break;
1894 :
1895 : case BIOC_SASILENCE:
1896 0 : request[0] = ARC_FW_MUTE_ALARM;
1897 : len = 1;
1898 :
1899 0 : break;
1900 :
1901 : case BIOC_GASTATUS:
1902 : /* system info is too big/ugly to deal with here */
1903 0 : return (arc_bio_alarm_state(sc, ba));
1904 :
1905 : default:
1906 0 : return (EOPNOTSUPP);
1907 : }
1908 :
1909 0 : arc_lock(sc);
1910 0 : error = arc_msgbuf(sc, request, len, reply, sizeof(reply), 0);
1911 0 : arc_unlock(sc);
1912 :
1913 0 : if (error != 0)
1914 0 : return (error);
1915 :
1916 0 : switch (reply[0]) {
1917 : case ARC_FW_CMD_OK:
1918 0 : return (0);
1919 : case ARC_FW_CMD_PASS_REQD:
1920 0 : return (EPERM);
1921 : default:
1922 0 : return (EIO);
1923 : }
1924 0 : }
1925 :
1926 : int
1927 0 : arc_bio_alarm_state(struct arc_softc *sc, struct bioc_alarm *ba)
1928 : {
1929 0 : u_int8_t request = ARC_FW_SYSINFO;
1930 : struct arc_fw_sysinfo *sysinfo;
1931 : int error = 0;
1932 :
1933 0 : sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
1934 :
1935 0 : request = ARC_FW_SYSINFO;
1936 :
1937 0 : arc_lock(sc);
1938 0 : error = arc_msgbuf(sc, &request, sizeof(request),
1939 : sysinfo, sizeof(struct arc_fw_sysinfo), 0);
1940 0 : arc_unlock(sc);
1941 :
1942 0 : if (error != 0)
1943 : goto out;
1944 :
1945 0 : ba->ba_status = sysinfo->alarm;
1946 :
1947 : out:
1948 0 : free(sysinfo, M_TEMP, sizeof *sysinfo);
1949 0 : return (error);
1950 0 : }
1951 :
1952 :
1953 : int
1954 0 : arc_bio_inq(struct arc_softc *sc, struct bioc_inq *bi)
1955 : {
1956 0 : u_int8_t request[2];
1957 : struct arc_fw_sysinfo *sysinfo;
1958 : struct arc_fw_volinfo *volinfo;
1959 : int maxvols, nvols = 0, i;
1960 : int error = 0;
1961 0 : char string[20];
1962 :
1963 : DPRINTF("%s: arc_bio_inq\n", DEVNAME(sc));
1964 0 : sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
1965 0 : volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
1966 :
1967 0 : arc_lock(sc);
1968 :
1969 0 : request[0] = ARC_FW_SYSINFO;
1970 0 : error = arc_msgbuf(sc, request, 1, sysinfo,
1971 : sizeof(struct arc_fw_sysinfo), 0);
1972 0 : if (error != 0) {
1973 : DPRINTF("%s: arc_bio_inq get sysinfo failed!\n", DEVNAME(sc));
1974 : goto out;
1975 : }
1976 :
1977 0 : maxvols = sysinfo->max_volume_set;
1978 :
1979 0 : request[0] = ARC_FW_VOLINFO;
1980 0 : for (i = 0; i < maxvols; i++) {
1981 0 : request[1] = i;
1982 0 : error = arc_msgbuf(sc, request, sizeof(request), volinfo,
1983 : sizeof(struct arc_fw_volinfo), 0);
1984 0 : if (error != 0) {
1985 : DPRINTF("%s: arc_bio_inq get volinfo failed!\n", DEVNAME(sc));
1986 : goto out;
1987 : }
1988 :
1989 : /*
1990 : * I can't find an easy way to see if the volume exists or not
1991 : * except to say that if it has no capacity then it isn't there.
1992 : * Ignore passthru volumes, bioc_vol doesn't understand them.
1993 : */
1994 0 : if ((volinfo->capacity != 0 || volinfo->capacity2 != 0) &&
1995 0 : volinfo->raid_level != ARC_FW_VOL_RAIDLEVEL_PASSTHRU) {
1996 0 : nvols++;
1997 0 : scsi_strvis(string, volinfo->set_name, 16);
1998 : DPRINTF("%s: volume set: \"%s\"\n", DEVNAME(sc), string);
1999 0 : }
2000 : }
2001 :
2002 0 : strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
2003 0 : bi->bi_novol = nvols;
2004 : DPRINTF("%s: volume set number = %d\n", DEVNAME(sc), nvols);
2005 : out:
2006 0 : arc_unlock(sc);
2007 0 : free(volinfo, M_TEMP, sizeof *volinfo);
2008 0 : free(sysinfo, M_TEMP, sizeof *sysinfo);
2009 0 : return (error);
2010 0 : }
2011 :
2012 : int
2013 0 : arc_bio_blink(struct arc_softc *sc, struct bioc_blink *blink)
2014 : {
2015 0 : u_int8_t request[6];
2016 0 : u_int32_t mask;
2017 : int error = 0;
2018 :
2019 : DPRINTF("%s: arc_bio_blink\n", DEVNAME(sc));
2020 0 : request[0] = ARC_FW_BLINK;
2021 0 : request[1] = ARC_FW_BLINK_ENABLE;
2022 :
2023 0 : switch (blink->bb_status) {
2024 : case BIOC_SBUNBLINK:
2025 0 : sc->sc_ledmask &= ~(1 << blink->bb_target);
2026 0 : break;
2027 : case BIOC_SBBLINK:
2028 0 : sc->sc_ledmask |= (1 << blink->bb_target);
2029 0 : break;
2030 : default:
2031 0 : return (EINVAL);
2032 : }
2033 :
2034 0 : mask = htole32(sc->sc_ledmask);
2035 0 : bcopy(&mask, &request[2], 4);
2036 :
2037 0 : arc_lock(sc);
2038 0 : error = arc_msgbuf(sc, request, sizeof(request), NULL, 0, 0);
2039 0 : arc_unlock(sc);
2040 0 : if (error)
2041 0 : return (EIO);
2042 :
2043 0 : return (0);
2044 0 : }
2045 :
2046 : int
2047 0 : arc_bio_getvol(struct arc_softc *sc, int vol, struct arc_fw_volinfo *volinfo)
2048 : {
2049 0 : u_int8_t request[2];
2050 : struct arc_fw_sysinfo *sysinfo;
2051 : int error = 0;
2052 : int maxvols, nvols = 0, i;
2053 :
2054 : DPRINTF("%s: arc_bio_getvol\n", DEVNAME(sc));
2055 0 : sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
2056 :
2057 0 : request[0] = ARC_FW_SYSINFO;
2058 0 : error = arc_msgbuf(sc, request, 1, sysinfo,
2059 : sizeof(struct arc_fw_sysinfo), 0);
2060 0 : if (error != 0)
2061 : goto out;
2062 :
2063 0 : maxvols = sysinfo->max_volume_set;
2064 :
2065 0 : request[0] = ARC_FW_VOLINFO;
2066 0 : for (i = 0; i < maxvols; i++) {
2067 0 : request[1] = i;
2068 0 : error = arc_msgbuf(sc, request, sizeof(request), volinfo,
2069 : sizeof(struct arc_fw_volinfo), 0);
2070 0 : if (error != 0)
2071 : goto out;
2072 :
2073 0 : if ((volinfo->capacity == 0 && volinfo->capacity2 == 0) ||
2074 0 : volinfo->raid_level == ARC_FW_VOL_RAIDLEVEL_PASSTHRU)
2075 : continue;
2076 :
2077 0 : if (nvols == vol)
2078 : break;
2079 :
2080 0 : nvols++;
2081 0 : }
2082 :
2083 0 : if (nvols != vol ||
2084 0 : (volinfo->capacity == 0 && volinfo->capacity2 == 0) ||
2085 0 : volinfo->raid_level == ARC_FW_VOL_RAIDLEVEL_PASSTHRU) {
2086 : error = ENODEV;
2087 0 : goto out;
2088 : }
2089 :
2090 : out:
2091 0 : free(sysinfo, M_TEMP, sizeof *sysinfo);
2092 0 : return (error);
2093 0 : }
2094 :
2095 : int
2096 0 : arc_bio_vol(struct arc_softc *sc, struct bioc_vol *bv)
2097 : {
2098 : struct arc_fw_volinfo *volinfo;
2099 : struct scsi_link *sc_link;
2100 : struct device *dev;
2101 : u_int64_t blocks;
2102 : u_int32_t status;
2103 : int error = 0;
2104 :
2105 : DPRINTF("%s: arc_bio_vol\n", DEVNAME(sc));
2106 0 : volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
2107 :
2108 0 : arc_lock(sc);
2109 0 : error = arc_bio_getvol(sc, bv->bv_volid, volinfo);
2110 0 : arc_unlock(sc);
2111 :
2112 0 : if (error != 0)
2113 : goto out;
2114 :
2115 0 : bv->bv_percent = -1;
2116 0 : bv->bv_seconds = 0;
2117 :
2118 0 : status = letoh32(volinfo->volume_status);
2119 0 : if (status == 0x0) {
2120 0 : if (letoh32(volinfo->fail_mask) == 0x0)
2121 0 : bv->bv_status = BIOC_SVONLINE;
2122 : else
2123 0 : bv->bv_status = BIOC_SVDEGRADED;
2124 0 : } else if (status & ARC_FW_VOL_STATUS_NEED_REGEN)
2125 0 : bv->bv_status = BIOC_SVDEGRADED;
2126 0 : else if (status & ARC_FW_VOL_STATUS_FAILED)
2127 0 : bv->bv_status = BIOC_SVOFFLINE;
2128 0 : else if (status & ARC_FW_VOL_STATUS_INITTING) {
2129 0 : bv->bv_status = BIOC_SVBUILDING;
2130 0 : bv->bv_percent = letoh32(volinfo->progress) / 10;
2131 0 : } else if (status & ARC_FW_VOL_STATUS_REBUILDING) {
2132 0 : bv->bv_status = BIOC_SVREBUILD;
2133 0 : bv->bv_percent = letoh32(volinfo->progress) / 10;
2134 0 : }
2135 :
2136 0 : blocks = (u_int64_t)letoh32(volinfo->capacity2) << 32;
2137 0 : blocks += (u_int64_t)letoh32(volinfo->capacity);
2138 0 : bv->bv_size = blocks * ARC_BLOCKSIZE; /* XXX */
2139 :
2140 0 : switch (volinfo->raid_level) {
2141 : case ARC_FW_VOL_RAIDLEVEL_0:
2142 0 : bv->bv_level = 0;
2143 0 : break;
2144 : case ARC_FW_VOL_RAIDLEVEL_1:
2145 0 : bv->bv_level = 1;
2146 0 : break;
2147 : case ARC_FW_VOL_RAIDLEVEL_3:
2148 0 : bv->bv_level = 3;
2149 0 : break;
2150 : case ARC_FW_VOL_RAIDLEVEL_5:
2151 0 : bv->bv_level = 5;
2152 0 : break;
2153 : case ARC_FW_VOL_RAIDLEVEL_6:
2154 0 : bv->bv_level = 6;
2155 0 : break;
2156 : case ARC_FW_VOL_RAIDLEVEL_PASSTHRU:
2157 : default:
2158 0 : bv->bv_level = -1;
2159 0 : break;
2160 : }
2161 :
2162 0 : bv->bv_nodisk = volinfo->member_disks;
2163 0 : sc_link = scsi_get_link(sc->sc_scsibus, volinfo->scsi_attr.target,
2164 0 : volinfo->scsi_attr.lun);
2165 0 : if (sc_link != NULL) {
2166 0 : dev = sc_link->device_softc;
2167 0 : strlcpy(bv->bv_dev, dev->dv_xname, sizeof(bv->bv_dev));
2168 0 : }
2169 :
2170 : out:
2171 0 : free(volinfo, M_TEMP, sizeof *volinfo);
2172 0 : return (error);
2173 : }
2174 :
2175 : int
2176 0 : arc_bio_disk(struct arc_softc *sc, struct bioc_disk *bd)
2177 : {
2178 0 : u_int8_t request[2];
2179 : struct arc_fw_volinfo *volinfo;
2180 : struct arc_fw_raidinfo *raidinfo;
2181 : struct arc_fw_diskinfo *diskinfo;
2182 : int error = 0;
2183 : u_int64_t blocks;
2184 0 : char model[81];
2185 0 : char serial[41];
2186 0 : char rev[17];
2187 :
2188 : DPRINTF("%s: arc_bio_disk\n", DEVNAME(sc));
2189 0 : volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
2190 0 : raidinfo = malloc(sizeof(struct arc_fw_raidinfo), M_TEMP, M_WAITOK);
2191 0 : diskinfo = malloc(sizeof(struct arc_fw_diskinfo), M_TEMP, M_WAITOK);
2192 :
2193 0 : arc_lock(sc);
2194 :
2195 0 : error = arc_bio_getvol(sc, bd->bd_volid, volinfo);
2196 0 : if (error != 0)
2197 : goto out;
2198 :
2199 0 : request[0] = ARC_FW_RAIDINFO;
2200 0 : request[1] = volinfo->raid_set_number;
2201 0 : error = arc_msgbuf(sc, request, sizeof(request), raidinfo,
2202 : sizeof(struct arc_fw_raidinfo), 0);
2203 0 : if (error != 0)
2204 : goto out;
2205 :
2206 0 : if (bd->bd_diskid > raidinfo->member_devices) {
2207 : error = ENODEV;
2208 0 : goto out;
2209 : }
2210 :
2211 0 : if (raidinfo->device_array[bd->bd_diskid] == 0xff) {
2212 : /*
2213 : * the disk doesn't exist anymore. bio is too dumb to be
2214 : * able to display that, so put it on another bus
2215 : */
2216 0 : bd->bd_channel = 1;
2217 0 : bd->bd_target = 0;
2218 0 : bd->bd_lun = 0;
2219 0 : bd->bd_status = BIOC_SDOFFLINE;
2220 0 : strlcpy(bd->bd_vendor, "disk missing", sizeof(bd->bd_vendor));
2221 0 : goto out;
2222 : }
2223 :
2224 0 : request[0] = ARC_FW_DISKINFO;
2225 0 : request[1] = raidinfo->device_array[bd->bd_diskid];
2226 0 : error = arc_msgbuf(sc, request, sizeof(request), diskinfo,
2227 : sizeof(struct arc_fw_diskinfo), 1);
2228 0 : if (error != 0)
2229 : goto out;
2230 :
2231 : #if 0
2232 : bd->bd_channel = diskinfo->scsi_attr.channel;
2233 : bd->bd_target = diskinfo->scsi_attr.target;
2234 : bd->bd_lun = diskinfo->scsi_attr.lun;
2235 : #endif
2236 : /*
2237 : * the firwmare doesnt seem to fill scsi_attr in, so fake it with
2238 : * the diskid.
2239 : */
2240 0 : bd->bd_channel = 0;
2241 0 : bd->bd_target = raidinfo->device_array[bd->bd_diskid];
2242 0 : bd->bd_lun = 0;
2243 :
2244 0 : bd->bd_status = BIOC_SDONLINE;
2245 0 : blocks = (u_int64_t)letoh32(diskinfo->capacity2) << 32;
2246 0 : blocks += (u_int64_t)letoh32(diskinfo->capacity);
2247 0 : bd->bd_size = blocks * ARC_BLOCKSIZE; /* XXX */
2248 :
2249 0 : scsi_strvis(model, diskinfo->model, sizeof(diskinfo->model));
2250 0 : scsi_strvis(serial, diskinfo->serial, sizeof(diskinfo->serial));
2251 0 : scsi_strvis(rev, diskinfo->firmware_rev,
2252 : sizeof(diskinfo->firmware_rev));
2253 :
2254 0 : snprintf(bd->bd_vendor, sizeof(bd->bd_vendor), "%s %s",
2255 : model, rev);
2256 0 : strlcpy(bd->bd_serial, serial, sizeof(bd->bd_serial));
2257 :
2258 : out:
2259 0 : arc_unlock(sc);
2260 0 : free(diskinfo, M_TEMP, sizeof *diskinfo);
2261 0 : free(raidinfo, M_TEMP, sizeof *raidinfo);
2262 0 : free(volinfo, M_TEMP, sizeof *volinfo);
2263 0 : return (error);
2264 0 : }
2265 :
2266 : u_int8_t
2267 0 : arc_msg_cksum(void *cmd, u_int16_t len)
2268 : {
2269 : u_int8_t *buf = cmd;
2270 : u_int8_t cksum;
2271 : int i;
2272 :
2273 0 : cksum = (u_int8_t)(len >> 8) + (u_int8_t)len;
2274 0 : for (i = 0; i < len; i++)
2275 0 : cksum += buf[i];
2276 :
2277 0 : return (cksum);
2278 : }
2279 :
2280 : int
2281 0 : arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wbuflen, void *rptr,
2282 : size_t rbuflen, int sreadok)
2283 : {
2284 0 : u_int8_t rwbuf[ARC_RA_IOC_RWBUF_MAXLEN];
2285 : u_int8_t *wbuf, *rbuf, cksum;
2286 : int wlen, wdone = 0, rlen, rdone = 0;
2287 : u_int16_t rlenhdr = 0;
2288 : struct arc_fw_bufhdr *bufhdr;
2289 : u_int32_t reg, rwlen, write_ok, read_ok;
2290 : int error = 0;
2291 : #ifdef ARC_DEBUG
2292 : int i;
2293 : #endif
2294 :
2295 : DPRINTF("%s: arc_msgbuf wbuflen: %d rbuflen: %d\n",
2296 : DEVNAME(sc), wbuflen, rbuflen);
2297 :
2298 0 : switch(sc->sc_adp_type) {
2299 : case ARC_HBA_TYPE_A:
2300 0 : reg = arc_read(sc, ARC_RA_OUTB_DOORBELL);
2301 0 : break;
2302 : case ARC_HBA_TYPE_C:
2303 0 : reg = arc_read(sc, ARC_RC_OUTB_DOORBELL);
2304 0 : break;
2305 : case ARC_HBA_TYPE_D:
2306 0 : reg = arc_read(sc, ARC_RD_OUTB_DOORBELL);
2307 0 : break;
2308 : }
2309 : /* if (reg)
2310 : return (EBUSY); */
2311 :
2312 0 : wlen = sizeof(struct arc_fw_bufhdr) + wbuflen + 1; /* 1 for cksum */
2313 0 : wbuf = malloc(wlen, M_TEMP, M_WAITOK);
2314 :
2315 0 : rlen = sizeof(struct arc_fw_bufhdr) + rbuflen + 1; /* 1 for cksum */
2316 0 : rbuf = malloc(rlen, M_TEMP, M_WAITOK);
2317 :
2318 : DNPRINTF(ARC_D_DB, "%s: arc_msgbuf wlen: %d rlen: %d\n", DEVNAME(sc),
2319 : wlen, rlen);
2320 :
2321 0 : bufhdr = (struct arc_fw_bufhdr *)wbuf;
2322 0 : bufhdr->hdr = arc_fw_hdr;
2323 0 : bufhdr->len = htole16(wbuflen);
2324 0 : bcopy(wptr, wbuf + sizeof(struct arc_fw_bufhdr), wbuflen);
2325 0 : wbuf[wlen - 1] = arc_msg_cksum(wptr, wbuflen);
2326 :
2327 : /* reg = ARC_RA_OUTB_DOORBELL_READ_OK; */
2328 : read_ok = 1;
2329 0 : do {
2330 0 : if ((read_ok) && wdone < wlen) {
2331 0 : bzero(rwbuf, sizeof(rwbuf));
2332 0 : rwlen = (wlen - wdone) % sizeof(rwbuf);
2333 0 : bcopy(&wbuf[wdone], rwbuf, rwlen);
2334 :
2335 : #ifdef ARC_DEBUG
2336 : if (arcdebug & ARC_D_DB) {
2337 : printf("%s: write %d:", DEVNAME(sc), rwlen);
2338 : for (i = 0; i < rwlen; i++)
2339 : printf(" 0x%02x", rwbuf[i]);
2340 : printf("\n");
2341 : }
2342 : #endif
2343 :
2344 0 : switch(sc->sc_adp_type) {
2345 : case ARC_HBA_TYPE_A:
2346 : /* copy the chunk to the hw */
2347 0 : arc_write(sc, ARC_RA_IOC_WBUF_LEN, rwlen);
2348 0 : arc_write_region(sc, ARC_RA_IOC_WBUF, rwbuf,
2349 : sizeof(rwbuf));
2350 :
2351 : /* say we have a buffer for the hw */
2352 0 : arc_write(sc, ARC_RA_INB_DOORBELL,
2353 : ARC_RA_INB_DOORBELL_WRITE_OK);
2354 0 : break;
2355 : case ARC_HBA_TYPE_C:
2356 : /* copy the chunk to the hw */
2357 0 : arc_write(sc, ARC_RC_MSG_WBUF_LEN, rwlen);
2358 0 : arc_write_region(sc, ARC_RC_MSG_WBUF, rwbuf,
2359 : sizeof(rwbuf));
2360 :
2361 : /* say we have a buffer for the hw */
2362 0 : arc_write(sc, ARC_RC_INB_DOORBELL,
2363 : ARC_RC_D2I_DATA_WRITE_OK);
2364 0 : break;
2365 : case ARC_HBA_TYPE_D:
2366 : /* copy the chunk to the hw */
2367 0 : arc_write(sc, ARC_RD_MSG_WBUF_LEN, rwlen);
2368 0 : arc_write_region(sc, ARC_RD_MSG_WBUF, rwbuf,
2369 : sizeof(rwbuf));
2370 :
2371 : /* say we have a buffer for the hw */
2372 0 : arc_write(sc, ARC_RD_INB_DOORBELL,
2373 : ARC_RD_D2I_DATA_WRITE_OK);
2374 0 : break;
2375 : }
2376 0 : wdone += rwlen;
2377 0 : }
2378 :
2379 0 : if (rptr == NULL)
2380 : goto out;
2381 :
2382 0 : switch(sc->sc_adp_type) {
2383 : case ARC_HBA_TYPE_A:
2384 0 : while ((reg = arc_read(sc, ARC_RA_OUTB_DOORBELL)) == 0)
2385 0 : arc_wait(sc);
2386 0 : arc_write(sc, ARC_RA_OUTB_DOORBELL, reg);
2387 0 : write_ok = reg & ARC_RA_OUTB_DOORBELL_WRITE_OK;
2388 0 : read_ok = reg & ARC_RA_OUTB_DOORBELL_READ_OK;
2389 0 : break;
2390 : case ARC_HBA_TYPE_C:
2391 0 : while ((reg = arc_read(sc, ARC_RC_OUTB_DOORBELL)) == 0)
2392 0 : arc_wait(sc);
2393 0 : arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR, reg);
2394 0 : write_ok = reg & ARC_RC_I2D_DATA_WRITE_OK;
2395 0 : read_ok = reg & ARC_RC_I2D_DATA_READ_OK;
2396 0 : break;
2397 : case ARC_HBA_TYPE_D:
2398 0 : while ((reg = arc_read(sc, ARC_RD_OUTB_DOORBELL)) == 0)
2399 0 : arc_wait(sc);
2400 0 : arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR, reg);
2401 0 : write_ok = reg & ARC_RD_I2D_DATA_WRITE_OK;
2402 0 : read_ok = reg & ARC_RD_I2D_DATA_READ_OK;
2403 0 : break;
2404 : }
2405 : DNPRINTF(ARC_D_DB, "%s: reg: 0x%08x\n", DEVNAME(sc), reg);
2406 :
2407 0 : if ((write_ok) && rdone < rlen) {
2408 0 : switch(sc->sc_adp_type) {
2409 : case ARC_HBA_TYPE_A:
2410 0 : rwlen = arc_read(sc, ARC_RA_IOC_RBUF_LEN);
2411 0 : break;
2412 : case ARC_HBA_TYPE_C:
2413 0 : rwlen = arc_read(sc, ARC_RC_MSG_RBUF_LEN);
2414 0 : break;
2415 : case ARC_HBA_TYPE_D:
2416 0 : rwlen = arc_read(sc, ARC_RD_MSG_RBUF_LEN);
2417 0 : break;
2418 : }
2419 0 : if (rwlen > sizeof(rwbuf)) {
2420 : DNPRINTF(ARC_D_DB, "%s: rwlen too big\n",
2421 : DEVNAME(sc));
2422 : error = EIO;
2423 0 : goto out;
2424 : }
2425 :
2426 0 : switch(sc->sc_adp_type) {
2427 : case ARC_HBA_TYPE_A:
2428 0 : arc_read_region(sc, ARC_RA_IOC_RBUF, rwbuf,
2429 : sizeof(rwbuf));
2430 0 : arc_write(sc, ARC_RA_INB_DOORBELL,
2431 : ARC_RA_INB_DOORBELL_READ_OK);
2432 0 : break;
2433 : case ARC_HBA_TYPE_C:
2434 0 : arc_read_region(sc, ARC_RC_MSG_RBUF, rwbuf,
2435 : sizeof(rwbuf));
2436 0 : arc_write(sc, ARC_RC_INB_DOORBELL,
2437 : ARC_RC_I2D_DATA_READ_OK);
2438 0 : break;
2439 : case ARC_HBA_TYPE_D:
2440 0 : arc_read_region(sc, ARC_RD_MSG_RBUF, rwbuf,
2441 : sizeof(rwbuf));
2442 0 : arc_write(sc, ARC_RD_INB_DOORBELL,
2443 : ARC_RD_I2D_DATA_READ_OK);
2444 0 : break;
2445 : }
2446 0 : if ((rlen > 3) && (rdone == 3)) {
2447 0 : rlen = *(u_int16_t *)rwbuf;
2448 0 : rlen = sizeof(struct arc_fw_bufhdr) + rlen + 1;
2449 0 : }
2450 : #ifdef ARC_DEBUG
2451 : printf("%s: len: %d+%d=%d/%d\n", DEVNAME(sc),
2452 : rwlen, rdone, rwlen + rdone, rlen);
2453 : if (arcdebug & ARC_D_DB) {
2454 : printf("%s: read:", DEVNAME(sc));
2455 : for (i = 0; i < rwlen; i++)
2456 : printf(" 0x%02x", rwbuf[i]);
2457 : printf("\n");
2458 : }
2459 : #endif
2460 :
2461 0 : if ((rdone + rwlen) > rlen) {
2462 : DNPRINTF(ARC_D_DB, "%s: rwbuf too big\n",
2463 : DEVNAME(sc));
2464 : error = EIO;
2465 0 : goto out;
2466 : }
2467 :
2468 0 : bcopy(rwbuf, &rbuf[rdone], rwlen);
2469 : rdone += rwlen;
2470 :
2471 : /*
2472 : * Allow for short reads, by reading the length
2473 : * value from the response header and shrinking our
2474 : * idea of size, if required.
2475 : * This deals with the growth of diskinfo struct from
2476 : * 128 to 132 bytes.
2477 : */
2478 0 : if (sreadok && rdone >= sizeof(struct arc_fw_bufhdr) &&
2479 0 : rlenhdr == 0) {
2480 0 : bufhdr = (struct arc_fw_bufhdr *)rbuf;
2481 0 : rlenhdr = letoh16(bufhdr->len);
2482 0 : if (rlenhdr < rbuflen) {
2483 : rbuflen = rlenhdr;
2484 0 : rlen = sizeof(struct arc_fw_bufhdr) +
2485 0 : rbuflen + 1; /* 1 for cksum */
2486 0 : }
2487 : }
2488 : }
2489 0 : } while (rdone != rlen);
2490 :
2491 0 : bufhdr = (struct arc_fw_bufhdr *)rbuf;
2492 0 : if (memcmp(&bufhdr->hdr, &arc_fw_hdr, sizeof(bufhdr->hdr)) != 0) {
2493 : DNPRINTF(ARC_D_DB, "%s: rbuf hdr is wrong\n", DEVNAME(sc));
2494 : error = EIO;
2495 0 : goto out;
2496 : }
2497 :
2498 0 : if (bufhdr->len != htole16(rbuflen)) {
2499 : DNPRINTF(ARC_D_DB, "%s: get_len: 0x%x, req_len: 0x%x\n",
2500 : DEVNAME(sc), bufhdr->len, rbuflen);
2501 : }
2502 :
2503 0 : bcopy(rbuf + sizeof(struct arc_fw_bufhdr), rptr, bufhdr->len);
2504 0 : cksum = arc_msg_cksum(rptr, bufhdr->len);
2505 0 : if (rbuf[rlen - 1] != cksum) {
2506 : DNPRINTF(ARC_D_DB, "%s: invalid cksum, got :0x%x, calculated:"
2507 : " 0x%x\n", DEVNAME(sc), rbuf[rlen-1], cksum);
2508 : error = EIO;
2509 0 : goto out;
2510 : }
2511 :
2512 : out:
2513 0 : free(wbuf, M_TEMP, 0);
2514 0 : free(rbuf, M_TEMP, 0);
2515 :
2516 0 : return (error);
2517 0 : }
2518 :
2519 : void
2520 0 : arc_lock(struct arc_softc *sc)
2521 : {
2522 : int s;
2523 : u_int32_t int_mask;
2524 :
2525 0 : rw_enter_write(&sc->sc_lock);
2526 0 : s = splbio();
2527 0 : switch(sc->sc_adp_type) {
2528 : case ARC_HBA_TYPE_A:
2529 0 : int_mask = arc_read(sc, ARC_RA_INTRMASK) | ARC_RA_INTRMASK_DOORBELL;
2530 0 : arc_write(sc, ARC_RA_INTRMASK, int_mask);
2531 0 : break;
2532 : case ARC_HBA_TYPE_C:
2533 0 : int_mask = arc_read(sc, ARC_RC_INTR_MASK) | ARC_RC_INTR_MASK_DOORBELL;
2534 0 : arc_write(sc, ARC_RC_INTR_MASK, int_mask);
2535 0 : break;
2536 : case ARC_HBA_TYPE_D:
2537 0 : int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) & ~ARC_RD_INTR_ENABLE_DOORBELL;
2538 0 : arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
2539 0 : break;
2540 : }
2541 0 : sc->sc_talking = 1;
2542 0 : splx(s);
2543 0 : }
2544 :
2545 : void
2546 0 : arc_unlock(struct arc_softc *sc)
2547 : {
2548 : int s;
2549 : u_int32_t int_mask;
2550 :
2551 0 : s = splbio();
2552 0 : sc->sc_talking = 0;
2553 0 : switch(sc->sc_adp_type) {
2554 : case ARC_HBA_TYPE_A:
2555 0 : int_mask = arc_read(sc, ARC_RA_INTRMASK) & ~ARC_RA_INTRMASK_DOORBELL;
2556 0 : arc_write(sc, ARC_RA_INTRMASK, int_mask);
2557 0 : break;
2558 : case ARC_HBA_TYPE_C:
2559 0 : int_mask = arc_read(sc, ARC_RC_INTR_MASK) & ~ARC_RC_INTR_MASK_DOORBELL;
2560 0 : arc_write(sc, ARC_RC_INTR_MASK, int_mask);
2561 0 : break;
2562 : case ARC_HBA_TYPE_D:
2563 0 : int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) | ARC_RD_INTR_ENABLE_DOORBELL;
2564 0 : arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
2565 0 : break;
2566 : }
2567 0 : splx(s);
2568 0 : rw_exit_write(&sc->sc_lock);
2569 0 : }
2570 :
2571 : void
2572 0 : arc_wait(struct arc_softc *sc)
2573 : {
2574 : int s;
2575 : u_int32_t int_mask;
2576 :
2577 0 : s = splbio();
2578 0 : switch(sc->sc_adp_type) {
2579 : case ARC_HBA_TYPE_A:
2580 0 : int_mask = arc_read(sc, ARC_RA_INTRMASK) & ~ARC_RA_INTRMASK_DOORBELL;
2581 0 : arc_write(sc, ARC_RA_INTRMASK, int_mask);
2582 0 : if (tsleep(sc, PWAIT, "arcdb", hz) == EWOULDBLOCK) {
2583 0 : int_mask = arc_read(sc, ARC_RA_INTRMASK) | ARC_RA_INTRMASK_DOORBELL;
2584 0 : arc_write(sc, ARC_RA_INTRMASK, int_mask);
2585 0 : }
2586 : break;
2587 : case ARC_HBA_TYPE_C:
2588 0 : int_mask = arc_read(sc, ARC_RC_INTR_MASK) & ~ARC_RC_INTR_MASK_DOORBELL;
2589 0 : arc_write(sc, ARC_RC_INTR_MASK, int_mask);
2590 0 : if (tsleep(sc, PWAIT, "arcdb", hz) == EWOULDBLOCK) {
2591 0 : int_mask = arc_read(sc, ARC_RC_INTR_MASK) | ARC_RC_INTR_MASK_DOORBELL;
2592 0 : arc_write(sc, ARC_RC_INTR_MASK, int_mask);
2593 0 : }
2594 : break;
2595 : case ARC_HBA_TYPE_D:
2596 0 : int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) | ARC_RD_INTR_ENABLE_DOORBELL;
2597 0 : arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
2598 0 : if (tsleep(sc, PWAIT, "arcdb", hz) == EWOULDBLOCK) {
2599 0 : int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) & ~ARC_RD_INTR_ENABLE_DOORBELL;
2600 0 : arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
2601 0 : }
2602 : break;
2603 : }
2604 0 : splx(s);
2605 0 : }
2606 :
2607 : #ifndef SMALL_KERNEL
2608 : void
2609 0 : arc_create_sensors(void *xat)
2610 : {
2611 0 : struct arc_task *at = xat;
2612 0 : struct arc_softc *sc = at->sc;
2613 0 : struct bioc_inq bi;
2614 0 : struct bioc_vol bv;
2615 : int i;
2616 :
2617 0 : free(at, M_TEMP, sizeof(*at));
2618 :
2619 : DPRINTF("%s: arc_create_sensors\n", DEVNAME(sc));
2620 : /*
2621 : * XXX * this is bollocks. the firmware has garbage coming out of it
2622 : * so we have to wait a bit for it to finish spewing.
2623 : */
2624 0 : tsleep(sc, PWAIT, "arcspew", 2 * hz);
2625 :
2626 0 : bzero(&bi, sizeof(bi));
2627 0 : if (arc_bio_inq(sc, &bi) != 0) {
2628 0 : printf("%s: unable to query firmware for sensor info\n",
2629 0 : DEVNAME(sc));
2630 0 : return;
2631 : }
2632 0 : sc->sc_nsensors = bi.bi_novol;
2633 :
2634 0 : sc->sc_sensors = mallocarray(sc->sc_nsensors, sizeof(struct ksensor),
2635 : M_DEVBUF, M_WAITOK | M_ZERO);
2636 :
2637 0 : strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
2638 : sizeof(sc->sc_sensordev.xname));
2639 :
2640 0 : for (i = 0; i < sc->sc_nsensors; i++) {
2641 0 : bzero(&bv, sizeof(bv));
2642 0 : bv.bv_volid = i;
2643 0 : if (arc_bio_vol(sc, &bv) != 0) {
2644 : DPRINTF("%s: arc_bio_vol failed!\n", DEVNAME(sc));
2645 : goto bad;
2646 : }
2647 :
2648 0 : sc->sc_sensors[i].type = SENSOR_DRIVE;
2649 0 : sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
2650 :
2651 0 : strlcpy(sc->sc_sensors[i].desc, bv.bv_dev,
2652 : sizeof(sc->sc_sensors[i].desc));
2653 :
2654 0 : sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
2655 : }
2656 :
2657 0 : if (sensor_task_register(sc, arc_refresh_sensors, 120) == NULL) {
2658 : DPRINTF("%s: sensor_task_register failed!\n", DEVNAME(sc));
2659 : goto bad;
2660 : }
2661 :
2662 0 : sensordev_install(&sc->sc_sensordev);
2663 :
2664 0 : return;
2665 :
2666 : bad:
2667 0 : free(sc->sc_sensors, M_DEVBUF,
2668 0 : sc->sc_nsensors * sizeof(struct ksensor));
2669 0 : }
2670 :
2671 : void
2672 0 : arc_refresh_sensors(void *arg)
2673 : {
2674 0 : struct arc_softc *sc = arg;
2675 0 : struct bioc_vol bv;
2676 : int i;
2677 :
2678 0 : for (i = 0; i < sc->sc_nsensors; i++) {
2679 0 : bzero(&bv, sizeof(bv));
2680 0 : bv.bv_volid = i;
2681 0 : if (arc_bio_vol(sc, &bv)) {
2682 0 : sc->sc_sensors[i].flags = SENSOR_FINVALID;
2683 0 : return;
2684 : }
2685 :
2686 0 : switch(bv.bv_status) {
2687 : case BIOC_SVOFFLINE:
2688 0 : sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL;
2689 0 : sc->sc_sensors[i].status = SENSOR_S_CRIT;
2690 0 : break;
2691 :
2692 : case BIOC_SVDEGRADED:
2693 0 : sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL;
2694 0 : sc->sc_sensors[i].status = SENSOR_S_WARN;
2695 0 : break;
2696 :
2697 : case BIOC_SVSCRUB:
2698 : case BIOC_SVONLINE:
2699 0 : sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE;
2700 0 : sc->sc_sensors[i].status = SENSOR_S_OK;
2701 0 : break;
2702 :
2703 : case BIOC_SVINVALID:
2704 : /* FALLTRHOUGH */
2705 : default:
2706 0 : sc->sc_sensors[i].value = 0; /* unknown */
2707 0 : sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
2708 0 : }
2709 :
2710 : }
2711 0 : }
2712 : #endif /* SMALL_KERNEL */
2713 : #endif /* NBIO > 0 */
2714 :
2715 : u_int32_t
2716 0 : arc_read(struct arc_softc *sc, bus_size_t r)
2717 : {
2718 : u_int32_t v;
2719 :
2720 0 : bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
2721 : BUS_SPACE_BARRIER_READ);
2722 0 : v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
2723 :
2724 : DNPRINTF(ARC_D_RW, "%s: arc_read 0x%x 0x%08x\n", DEVNAME(sc), r, v);
2725 :
2726 0 : return (v);
2727 : }
2728 :
2729 : void
2730 0 : arc_read_region(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
2731 : {
2732 0 : bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, len,
2733 : BUS_SPACE_BARRIER_READ);
2734 0 : bus_space_read_raw_region_4(sc->sc_iot, sc->sc_ioh, r, buf, len);
2735 0 : }
2736 :
2737 : void
2738 0 : arc_write(struct arc_softc *sc, bus_size_t r, u_int32_t v)
2739 : {
2740 : DNPRINTF(ARC_D_RW, "%s: arc_write 0x%x 0x%08x\n", DEVNAME(sc), r, v);
2741 :
2742 0 : bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
2743 0 : bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
2744 : BUS_SPACE_BARRIER_WRITE);
2745 0 : }
2746 :
2747 : void
2748 0 : arc_write_region(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
2749 : {
2750 0 : bus_space_write_raw_region_4(sc->sc_iot, sc->sc_ioh, r, buf, len);
2751 0 : bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, len,
2752 : BUS_SPACE_BARRIER_WRITE);
2753 0 : }
2754 :
2755 : int
2756 0 : arc_wait_eq(struct arc_softc *sc, bus_size_t r, u_int32_t mask,
2757 : u_int32_t target)
2758 : {
2759 : int i;
2760 :
2761 : DNPRINTF(ARC_D_RW, "%s: arc_wait_eq 0x%x 0x%08x 0x%08x\n",
2762 : DEVNAME(sc), r, mask, target);
2763 :
2764 0 : for (i = 0; i < 10000; i++) {
2765 0 : if ((arc_read(sc, r) & mask) == target)
2766 0 : return (0);
2767 0 : delay(1000);
2768 : }
2769 :
2770 0 : return (1);
2771 0 : }
2772 :
2773 : int
2774 0 : arc_wait_ne(struct arc_softc *sc, bus_size_t r, u_int32_t mask,
2775 : u_int32_t target)
2776 : {
2777 : int i;
2778 :
2779 : DNPRINTF(ARC_D_RW, "%s: arc_wait_ne 0x%x 0x%08x 0x%08x\n",
2780 : DEVNAME(sc), r, mask, target);
2781 :
2782 0 : for (i = 0; i < 10000; i++) {
2783 0 : if ((arc_read(sc, r) & mask) != target)
2784 0 : return (0);
2785 0 : delay(1000);
2786 : }
2787 :
2788 0 : return (1);
2789 0 : }
2790 :
2791 : int
2792 0 : arc_msg0(struct arc_softc *sc, u_int32_t m)
2793 : {
2794 0 : switch(sc->sc_adp_type) {
2795 : case ARC_HBA_TYPE_A:
2796 : /* post message */
2797 0 : arc_write(sc, ARC_RA_INB_MSG0, m);
2798 : /* wait for the fw to do it */
2799 0 : if (arc_wait_eq(sc, ARC_RA_INTRSTAT, ARC_RA_INTRSTAT_MSG0,
2800 0 : ARC_RA_INTRSTAT_MSG0) != 0)
2801 0 : return (1);
2802 :
2803 : /* ack it */
2804 0 : arc_write(sc, ARC_RA_INTRSTAT, ARC_RA_INTRSTAT_MSG0);
2805 0 : break;
2806 :
2807 : case ARC_HBA_TYPE_C:
2808 : /* post message */
2809 0 : arc_write(sc, ARC_RC_INB_MSGADDR0, m);
2810 0 : arc_write(sc, ARC_RC_INB_DOORBELL, ARC_RC_D2I_MSG_CMD_DONE);
2811 : /* wait for the fw to do it */
2812 0 : if (arc_wait_eq(sc, ARC_RC_OUTB_DOORBELL, ARC_RC_I2D_MSG_CMD_DONE,
2813 0 : ARC_RC_I2D_MSG_CMD_DONE) != 0)
2814 0 : return (1);
2815 :
2816 : /* ack it */
2817 0 : arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR, ARC_RC_I2D_MSG_CMD_DONE_CLR);
2818 0 : break;
2819 :
2820 : case ARC_HBA_TYPE_D:
2821 : /* post message */
2822 0 : arc_write(sc, ARC_RD_INB_MSGADDR0, m);
2823 : /* wait for the fw to do it */
2824 0 : if (arc_wait_eq(sc, ARC_RD_OUTB_DOORBELL, ARC_RD_I2D_MSG_CMD_DONE,
2825 0 : ARC_RD_I2D_MSG_CMD_DONE) != 0)
2826 0 : return (1);
2827 :
2828 : /* ack it */
2829 0 : arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR, ARC_RD_I2D_MSG_CMD_DONE_CLR);
2830 0 : break;
2831 : }
2832 0 : return (0);
2833 0 : }
2834 :
2835 : struct arc_dmamem *
2836 0 : arc_dmamem_alloc(struct arc_softc *sc, size_t size)
2837 : {
2838 : struct arc_dmamem *adm;
2839 0 : int nsegs;
2840 :
2841 0 : adm = malloc(sizeof(*adm), M_DEVBUF, M_NOWAIT | M_ZERO);
2842 0 : if (adm == NULL)
2843 0 : return (NULL);
2844 :
2845 0 : adm->adm_size = size;
2846 :
2847 0 : if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
2848 0 : BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &adm->adm_map) != 0)
2849 : goto admfree;
2850 :
2851 0 : if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &adm->adm_seg,
2852 0 : 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
2853 : goto destroy;
2854 :
2855 0 : if (bus_dmamem_map(sc->sc_dmat, &adm->adm_seg, nsegs, size,
2856 0 : &adm->adm_kva, BUS_DMA_NOWAIT) != 0)
2857 : goto free;
2858 :
2859 0 : if (bus_dmamap_load(sc->sc_dmat, adm->adm_map, adm->adm_kva, size,
2860 0 : NULL, BUS_DMA_NOWAIT) != 0)
2861 : goto unmap;
2862 :
2863 0 : return (adm);
2864 :
2865 : unmap:
2866 0 : bus_dmamem_unmap(sc->sc_dmat, adm->adm_kva, size);
2867 : free:
2868 0 : bus_dmamem_free(sc->sc_dmat, &adm->adm_seg, 1);
2869 : destroy:
2870 0 : bus_dmamap_destroy(sc->sc_dmat, adm->adm_map);
2871 : admfree:
2872 0 : free(adm, M_DEVBUF, sizeof *adm);
2873 :
2874 0 : return (NULL);
2875 0 : }
2876 :
2877 : void
2878 0 : arc_dmamem_free(struct arc_softc *sc, struct arc_dmamem *adm)
2879 : {
2880 0 : bus_dmamap_unload(sc->sc_dmat, adm->adm_map);
2881 0 : bus_dmamem_unmap(sc->sc_dmat, adm->adm_kva, adm->adm_size);
2882 0 : bus_dmamem_free(sc->sc_dmat, &adm->adm_seg, 1);
2883 0 : bus_dmamap_destroy(sc->sc_dmat, adm->adm_map);
2884 0 : free(adm, M_DEVBUF, sizeof *adm);
2885 0 : }
2886 :
2887 : int
2888 0 : arc_alloc_ccbs(struct arc_softc *sc)
2889 : {
2890 : struct arc_ccb *ccb;
2891 : u_int8_t *cmd;
2892 : u_int32_t i, size, len;
2893 :
2894 0 : SLIST_INIT(&sc->sc_ccb_free);
2895 0 : mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
2896 :
2897 : size = sizeof(struct arc_ccb) * ARCMSR_MAX_CCB_COUNT;
2898 0 : sc->sc_ccbs = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
2899 :
2900 : len = ARC_IO_CMD_LEN;
2901 : size = ARCMSR_MAX_CCB_COUNT * len;
2902 0 : if(sc->sc_adp_type == ARC_HBA_TYPE_D)
2903 0 : size += sizeof(struct arc_HBD_Msgu);
2904 0 : sc->sc_requests = arc_dmamem_alloc(sc, size);
2905 0 : if (sc->sc_requests == NULL) {
2906 0 : printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
2907 0 : goto free_ccbs;
2908 : }
2909 0 : cmd = ARC_DMA_KVA(sc->sc_requests);
2910 :
2911 0 : for (i = 0; i < ARCMSR_MAX_CCB_COUNT; i++) {
2912 0 : ccb = &sc->sc_ccbs[i];
2913 :
2914 0 : if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, ARC_SGL_MAXLEN,
2915 0 : MAXPHYS, 0, 0, &ccb->ccb_dmamap) != 0) {
2916 0 : printf("%s: unable to create dmamap for ccb %d\n",
2917 0 : DEVNAME(sc), i);
2918 : goto free_maps;
2919 : }
2920 :
2921 0 : ccb->ccb_sc = sc;
2922 0 : ccb->cmd_dma_offset = len * i;
2923 :
2924 0 : ccb->ccb_cmd = (struct arc_io_cmd *)&cmd[ccb->cmd_dma_offset];
2925 0 : ccb->ccb_cmd_post = (ARC_DMA_DVA(sc->sc_requests) +
2926 0 : ccb->cmd_dma_offset);
2927 0 : if ((sc->sc_adp_type != ARC_HBA_TYPE_C) &&
2928 0 : (sc->sc_adp_type != ARC_HBA_TYPE_D))
2929 0 : ccb->ccb_cmd_post = ccb->ccb_cmd_post >>
2930 : ARC_RA_POST_QUEUE_ADDR_SHIFT;
2931 0 : arc_put_ccb(sc, ccb);
2932 : }
2933 0 : sc->sc_ccb_phys_hi = (u_int64_t)ARC_DMA_DVA(sc->sc_requests) >> 32;
2934 0 : if(sc->sc_adp_type == ARC_HBA_TYPE_D) {
2935 0 : sc->postQ_buffer = ARC_DMA_DVA(sc->sc_requests) +
2936 : (ARCMSR_MAX_CCB_COUNT * len);
2937 0 : sc->doneQ_buffer = sc->postQ_buffer + (sizeof(struct InBound_SRB) *
2938 : ARCMSR_MAX_HBD_POSTQUEUE);
2939 0 : sc->pmu = (struct arc_HBD_Msgu *)&cmd[ARCMSR_MAX_CCB_COUNT * len];
2940 0 : sc->cmdQ_ptr_offset = ARCMSR_MAX_CCB_COUNT * len;
2941 0 : }
2942 0 : scsi_iopool_init(&sc->sc_iopool, sc,
2943 : (void *(*)(void *))arc_get_ccb,
2944 : (void (*)(void *, void *))arc_put_ccb);
2945 :
2946 0 : return (0);
2947 :
2948 : free_maps:
2949 0 : while ((ccb = arc_get_ccb(sc)) != NULL)
2950 0 : bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
2951 0 : arc_dmamem_free(sc, sc->sc_requests);
2952 :
2953 : free_ccbs:
2954 0 : free(sc->sc_ccbs, M_DEVBUF, sizeof(struct arc_ccb) * ARCMSR_MAX_CCB_COUNT);
2955 :
2956 0 : return (1);
2957 0 : }
2958 :
2959 : void
2960 0 : arc_free_ccb_src(struct arc_softc *sc)
2961 : {
2962 : struct arc_ccb *ccb;
2963 :
2964 0 : while ((ccb = arc_get_ccb(sc)) != NULL)
2965 0 : bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
2966 0 : arc_dmamem_free(sc, sc->sc_requests);
2967 0 : free(sc->sc_ccbs, M_DEVBUF, 0);
2968 0 : }
2969 :
2970 : struct arc_ccb *
2971 0 : arc_get_ccb(struct arc_softc *sc)
2972 : {
2973 : struct arc_ccb *ccb;
2974 :
2975 0 : mtx_enter(&sc->sc_ccb_mtx);
2976 0 : ccb = SLIST_FIRST(&sc->sc_ccb_free);
2977 0 : if (ccb != NULL)
2978 0 : SLIST_REMOVE_HEAD(&sc->sc_ccb_free, ccb_link);
2979 0 : mtx_leave(&sc->sc_ccb_mtx);
2980 :
2981 0 : return (ccb);
2982 : }
2983 :
2984 : void
2985 0 : arc_put_ccb(struct arc_softc *sc, struct arc_ccb *ccb)
2986 : {
2987 0 : ccb->ccb_xs = NULL;
2988 0 : bzero(ccb->ccb_cmd, ARC_IO_CMD_LEN);
2989 0 : mtx_enter(&sc->sc_ccb_mtx);
2990 0 : SLIST_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_link);
2991 0 : mtx_leave(&sc->sc_ccb_mtx);
2992 0 : }
|