Line data Source code
1 : /* $OpenBSD: ips.c,v 1.113 2016/08/14 04:08:03 dlg Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2006, 2007, 2009 Alexander Yurchenko <grange@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 : * IBM (Adaptec) ServeRAID controllers driver.
21 : */
22 :
23 : #include "bio.h"
24 :
25 : #include <sys/param.h>
26 : #include <sys/systm.h>
27 : #include <sys/device.h>
28 : #include <sys/ioctl.h>
29 : #include <sys/kernel.h>
30 : #include <sys/malloc.h>
31 : #include <sys/sensors.h>
32 : #include <sys/timeout.h>
33 : #include <sys/queue.h>
34 :
35 : #include <machine/bus.h>
36 :
37 : #include <scsi/scsi_all.h>
38 : #include <scsi/scsi_disk.h>
39 : #include <scsi/scsiconf.h>
40 :
41 : #include <dev/biovar.h>
42 :
43 : #include <dev/pci/pcidevs.h>
44 : #include <dev/pci/pcireg.h>
45 : #include <dev/pci/pcivar.h>
46 :
47 : /* Debug levels */
48 : #define IPS_D_ERR 0x0001 /* errors */
49 : #define IPS_D_INFO 0x0002 /* information */
50 : #define IPS_D_XFER 0x0004 /* transfers */
51 :
52 : #ifdef IPS_DEBUG
53 : #define DPRINTF(a, b) do { if (ips_debug & (a)) printf b; } while (0)
54 : int ips_debug = IPS_D_ERR;
55 : #else
56 : #define DPRINTF(a, b)
57 : #endif
58 :
59 : #define IPS_MAXDRIVES 8
60 : #define IPS_MAXCHANS 4
61 : #define IPS_MAXTARGETS 16
62 : #define IPS_MAXCHUNKS 16
63 : #define IPS_MAXCMDS 128
64 :
65 : #define IPS_MAXFER (64 * 1024)
66 : #define IPS_MAXSGS 16
67 : #define IPS_MAXCDB 12
68 :
69 : #define IPS_SECSZ 512
70 : #define IPS_NVRAMPGSZ 128
71 : #define IPS_SQSZ (IPS_MAXCMDS * sizeof(u_int32_t))
72 :
73 : #define IPS_TIMEOUT 60000 /* ms */
74 :
75 : /* Command codes */
76 : #define IPS_CMD_READ 0x02
77 : #define IPS_CMD_WRITE 0x03
78 : #define IPS_CMD_DCDB 0x04
79 : #define IPS_CMD_GETADAPTERINFO 0x05
80 : #define IPS_CMD_FLUSH 0x0a
81 : #define IPS_CMD_REBUILDSTATUS 0x0c
82 : #define IPS_CMD_SETSTATE 0x10
83 : #define IPS_CMD_REBUILD 0x16
84 : #define IPS_CMD_ERRORTABLE 0x17
85 : #define IPS_CMD_GETDRIVEINFO 0x19
86 : #define IPS_CMD_RESETCHAN 0x1a
87 : #define IPS_CMD_DOWNLOAD 0x20
88 : #define IPS_CMD_RWBIOSFW 0x22
89 : #define IPS_CMD_READCONF 0x38
90 : #define IPS_CMD_GETSUBSYS 0x40
91 : #define IPS_CMD_CONFIGSYNC 0x58
92 : #define IPS_CMD_READ_SG 0x82
93 : #define IPS_CMD_WRITE_SG 0x83
94 : #define IPS_CMD_DCDB_SG 0x84
95 : #define IPS_CMD_EDCDB 0x95
96 : #define IPS_CMD_EDCDB_SG 0x96
97 : #define IPS_CMD_RWNVRAMPAGE 0xbc
98 : #define IPS_CMD_GETVERINFO 0xc6
99 : #define IPS_CMD_FFDC 0xd7
100 : #define IPS_CMD_SG 0x80
101 : #define IPS_CMD_RWNVRAM 0xbc
102 :
103 : /* DCDB attributes */
104 : #define IPS_DCDB_DATAIN 0x01 /* data input */
105 : #define IPS_DCDB_DATAOUT 0x02 /* data output */
106 : #define IPS_DCDB_XFER64K 0x08 /* 64K transfer */
107 : #define IPS_DCDB_TIMO10 0x10 /* 10 secs timeout */
108 : #define IPS_DCDB_TIMO60 0x20 /* 60 secs timeout */
109 : #define IPS_DCDB_TIMO20M 0x30 /* 20 mins timeout */
110 : #define IPS_DCDB_NOAUTOREQSEN 0x40 /* no auto request sense */
111 : #define IPS_DCDB_DISCON 0x80 /* disconnect allowed */
112 :
113 : /* Register definitions */
114 : #define IPS_REG_HIS 0x08 /* host interrupt status */
115 : #define IPS_REG_HIS_SCE 0x01 /* status channel enqueue */
116 : #define IPS_REG_HIS_EN 0x80 /* enable interrupts */
117 : #define IPS_REG_CCSA 0x10 /* command channel system address */
118 : #define IPS_REG_CCC 0x14 /* command channel control */
119 : #define IPS_REG_CCC_SEM 0x0008 /* semaphore */
120 : #define IPS_REG_CCC_START 0x101a /* start command */
121 : #define IPS_REG_SQH 0x20 /* status queue head */
122 : #define IPS_REG_SQT 0x24 /* status queue tail */
123 : #define IPS_REG_SQE 0x28 /* status queue end */
124 : #define IPS_REG_SQS 0x2c /* status queue start */
125 :
126 : #define IPS_REG_OIS 0x30 /* outbound interrupt status */
127 : #define IPS_REG_OIS_PEND 0x0008 /* interrupt is pending */
128 : #define IPS_REG_OIM 0x34 /* outbound interrupt mask */
129 : #define IPS_REG_OIM_DS 0x0008 /* disable interrupts */
130 : #define IPS_REG_IQP 0x40 /* inbound queue port */
131 : #define IPS_REG_OQP 0x44 /* outbound queue port */
132 :
133 : /* Status word fields */
134 : #define IPS_STAT_ID(x) (((x) >> 8) & 0xff) /* command id */
135 : #define IPS_STAT_BASIC(x) (((x) >> 16) & 0xff) /* basic status */
136 : #define IPS_STAT_EXT(x) (((x) >> 24) & 0xff) /* ext status */
137 : #define IPS_STAT_GSC(x) ((x) & 0x0f)
138 :
139 : /* Basic status codes */
140 : #define IPS_STAT_OK 0x00 /* success */
141 : #define IPS_STAT_RECOV 0x01 /* recovered error */
142 : #define IPS_STAT_INVOP 0x03 /* invalid opcode */
143 : #define IPS_STAT_INVCMD 0x04 /* invalid command block */
144 : #define IPS_STAT_INVPARM 0x05 /* invalid parameters block */
145 : #define IPS_STAT_BUSY 0x08 /* busy */
146 : #define IPS_STAT_CMPLERR 0x0c /* completed with error */
147 : #define IPS_STAT_LDERR 0x0d /* logical drive error */
148 : #define IPS_STAT_TIMO 0x0e /* timeout */
149 : #define IPS_STAT_PDRVERR 0x0f /* physical drive error */
150 :
151 : /* Extended status codes */
152 : #define IPS_ESTAT_SELTIMO 0xf0 /* select timeout */
153 : #define IPS_ESTAT_OURUN 0xf2 /* over/underrun */
154 : #define IPS_ESTAT_HOSTRST 0xf7 /* host reset */
155 : #define IPS_ESTAT_DEVRST 0xf8 /* device reset */
156 : #define IPS_ESTAT_RECOV 0xfc /* recovered error */
157 : #define IPS_ESTAT_CKCOND 0xff /* check condition */
158 :
159 : #define IPS_IOSIZE 128 /* max space size to map */
160 :
161 : /* Command frame */
162 : struct ips_cmd {
163 : u_int8_t code;
164 : u_int8_t id;
165 : u_int8_t drive;
166 : u_int8_t sgcnt;
167 : u_int32_t lba;
168 : u_int32_t sgaddr;
169 : u_int16_t seccnt;
170 : u_int8_t seg4g;
171 : u_int8_t esg;
172 : u_int32_t ccsar;
173 : u_int32_t cccr;
174 : };
175 :
176 : /* Direct CDB (SCSI pass-through) frame */
177 : struct ips_dcdb {
178 : u_int8_t device;
179 : u_int8_t attr;
180 : u_int16_t datalen;
181 : u_int32_t sgaddr;
182 : u_int8_t cdblen;
183 : u_int8_t senselen;
184 : u_int8_t sgcnt;
185 : u_int8_t __reserved1;
186 : u_int8_t cdb[IPS_MAXCDB];
187 : u_int8_t sense[64];
188 : u_int8_t status;
189 : u_int8_t __reserved2[3];
190 : };
191 :
192 : /* Scatter-gather array element */
193 : struct ips_sg {
194 : u_int32_t addr;
195 : u_int32_t size;
196 : };
197 :
198 : /* Command block */
199 : struct ips_cmdb {
200 : struct ips_cmd cmd;
201 : struct ips_dcdb dcdb;
202 : struct ips_sg sg[IPS_MAXSGS];
203 : };
204 :
205 : /* Data frames */
206 : struct ips_adapterinfo {
207 : u_int8_t drivecnt;
208 : u_int8_t miscflag;
209 : u_int8_t sltflag;
210 : u_int8_t bstflag;
211 : u_int8_t pwrchgcnt;
212 : u_int8_t wrongaddrcnt;
213 : u_int8_t unidentcnt;
214 : u_int8_t nvramdevchgcnt;
215 : u_int8_t firmware[8];
216 : u_int8_t bios[8];
217 : u_int32_t drivesize[IPS_MAXDRIVES];
218 : u_int8_t cmdcnt;
219 : u_int8_t maxphysdevs;
220 : u_int16_t flashrepgmcnt;
221 : u_int8_t defunctdiskcnt;
222 : u_int8_t rebuildflag;
223 : u_int8_t offdrivecnt;
224 : u_int8_t critdrivecnt;
225 : u_int16_t confupdcnt;
226 : u_int8_t blkflag;
227 : u_int8_t __reserved;
228 : u_int16_t deaddisk[IPS_MAXCHANS][IPS_MAXTARGETS];
229 : };
230 :
231 : struct ips_driveinfo {
232 : u_int8_t drivecnt;
233 : u_int8_t __reserved[3];
234 : struct ips_drive {
235 : u_int8_t id;
236 : u_int8_t __reserved;
237 : u_int8_t raid;
238 : u_int8_t state;
239 : #define IPS_DS_FREE 0x00
240 : #define IPS_DS_OFFLINE 0x02
241 : #define IPS_DS_ONLINE 0x03
242 : #define IPS_DS_DEGRADED 0x04
243 : #define IPS_DS_SYS 0x06
244 : #define IPS_DS_CRS 0x24
245 :
246 : u_int32_t seccnt;
247 : } drive[IPS_MAXDRIVES];
248 : };
249 :
250 : struct ips_conf {
251 : u_int8_t ldcnt;
252 : u_int8_t day;
253 : u_int8_t month;
254 : u_int8_t year;
255 : u_int8_t initid[4];
256 : u_int8_t hostid[12];
257 : u_int8_t time[8];
258 : u_int32_t useropt;
259 : u_int16_t userfield;
260 : u_int8_t rebuildrate;
261 : u_int8_t __reserved1;
262 :
263 : struct ips_hw {
264 : u_int8_t board[8];
265 : u_int8_t cpu[8];
266 : u_int8_t nchantype;
267 : u_int8_t nhostinttype;
268 : u_int8_t compression;
269 : u_int8_t nvramtype;
270 : u_int32_t nvramsize;
271 : } hw;
272 :
273 : struct ips_ld {
274 : u_int16_t userfield;
275 : u_int8_t state;
276 : u_int8_t raidcacheparam;
277 : u_int8_t chunkcnt;
278 : u_int8_t stripesize;
279 : u_int8_t params;
280 : u_int8_t __reserved;
281 : u_int32_t size;
282 :
283 : struct ips_chunk {
284 : u_int8_t channel;
285 : u_int8_t target;
286 : u_int16_t __reserved;
287 : u_int32_t startsec;
288 : u_int32_t seccnt;
289 : } chunk[IPS_MAXCHUNKS];
290 : } ld[IPS_MAXDRIVES];
291 :
292 : struct ips_dev {
293 : u_int8_t initiator;
294 : u_int8_t params;
295 : u_int8_t miscflag;
296 : u_int8_t state;
297 : #define IPS_DVS_STANDBY 0x01
298 : #define IPS_DVS_REBUILD 0x02
299 : #define IPS_DVS_SPARE 0x04
300 : #define IPS_DVS_MEMBER 0x08
301 : #define IPS_DVS_ONLINE 0x80
302 : #define IPS_DVS_READY (IPS_DVS_STANDBY | IPS_DVS_ONLINE)
303 :
304 : u_int32_t seccnt;
305 : u_int8_t devid[28];
306 : } dev[IPS_MAXCHANS][IPS_MAXTARGETS];
307 :
308 : u_int8_t reserved[512];
309 : };
310 :
311 : struct ips_rblstat {
312 : u_int8_t __unknown[20];
313 : struct {
314 : u_int8_t __unknown[4];
315 : u_int32_t total;
316 : u_int32_t remain;
317 : } ld[IPS_MAXDRIVES];
318 : };
319 :
320 : struct ips_pg5 {
321 : u_int32_t signature;
322 : u_int8_t __reserved1;
323 : u_int8_t slot;
324 : u_int16_t type;
325 : u_int8_t bioshi[4];
326 : u_int8_t bioslo[4];
327 : u_int16_t __reserved2;
328 : u_int8_t __reserved3;
329 : u_int8_t os;
330 : u_int8_t driverhi[4];
331 : u_int8_t driverlo[4];
332 : u_int8_t __reserved4[100];
333 : };
334 :
335 : struct ips_info {
336 : struct ips_adapterinfo adapter;
337 : struct ips_driveinfo drive;
338 : struct ips_conf conf;
339 : struct ips_rblstat rblstat;
340 : struct ips_pg5 pg5;
341 : };
342 :
343 : /* Command control block */
344 : struct ips_softc;
345 : struct ips_ccb {
346 : struct ips_softc * c_sc; /* driver softc */
347 : int c_id; /* command id */
348 : int c_flags; /* SCSI_* flags */
349 : enum {
350 : IPS_CCB_FREE,
351 : IPS_CCB_QUEUED,
352 : IPS_CCB_DONE
353 : } c_state; /* command state */
354 :
355 : void * c_cmdbva; /* command block virt addr */
356 : paddr_t c_cmdbpa; /* command block phys addr */
357 : bus_dmamap_t c_dmam; /* data buffer DMA map */
358 :
359 : struct scsi_xfer * c_xfer; /* corresponding SCSI xfer */
360 :
361 : u_int8_t c_stat; /* status byte copy */
362 : u_int8_t c_estat; /* ext status byte copy */
363 : int c_error; /* completion error */
364 :
365 : void (*c_done)(struct ips_softc *, /* cmd done */
366 : struct ips_ccb *); /* callback */
367 :
368 : SLIST_ENTRY(ips_ccb) c_link; /* queue link */
369 : };
370 :
371 : /* CCB queue */
372 : SLIST_HEAD(ips_ccbq, ips_ccb);
373 :
374 : /* DMA-able chunk of memory */
375 : struct dmamem {
376 : bus_dma_tag_t dm_tag;
377 : bus_dmamap_t dm_map;
378 : bus_dma_segment_t dm_seg;
379 : bus_size_t dm_size;
380 : void * dm_vaddr;
381 : #define dm_paddr dm_seg.ds_addr
382 : };
383 :
384 : struct ips_softc {
385 : struct device sc_dev;
386 :
387 : struct scsi_link sc_scsi_link;
388 : struct scsibus_softc * sc_scsibus;
389 :
390 : struct ips_pt {
391 : struct ips_softc * pt_sc;
392 : int pt_chan;
393 :
394 : struct scsi_link pt_link;
395 :
396 : int pt_proctgt;
397 : char pt_procdev[16];
398 : } sc_pt[IPS_MAXCHANS];
399 :
400 : struct ksensordev sc_sensordev;
401 : struct ksensor * sc_sensors;
402 :
403 : bus_space_tag_t sc_iot;
404 : bus_space_handle_t sc_ioh;
405 : bus_dma_tag_t sc_dmat;
406 :
407 : const struct ips_chipset *sc_chip;
408 :
409 : struct ips_info * sc_info;
410 : struct dmamem sc_infom;
411 :
412 : int sc_nunits;
413 :
414 : struct dmamem sc_cmdbm;
415 :
416 : struct ips_ccb * sc_ccb;
417 : int sc_nccbs;
418 : struct ips_ccbq sc_ccbq_free;
419 : struct mutex sc_ccb_mtx;
420 : struct scsi_iopool sc_iopool;
421 :
422 : struct dmamem sc_sqm;
423 : paddr_t sc_sqtail;
424 : u_int32_t * sc_sqbuf;
425 : int sc_sqidx;
426 : };
427 :
428 : int ips_match(struct device *, void *, void *);
429 : void ips_attach(struct device *, struct device *, void *);
430 :
431 : void ips_scsi_cmd(struct scsi_xfer *);
432 : void ips_scsi_pt_cmd(struct scsi_xfer *);
433 : int ips_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int);
434 :
435 : #if NBIO > 0
436 : int ips_ioctl(struct device *, u_long, caddr_t);
437 : int ips_ioctl_inq(struct ips_softc *, struct bioc_inq *);
438 : int ips_ioctl_vol(struct ips_softc *, struct bioc_vol *);
439 : int ips_ioctl_disk(struct ips_softc *, struct bioc_disk *);
440 : int ips_ioctl_setstate(struct ips_softc *, struct bioc_setstate *);
441 : #endif
442 :
443 : #ifndef SMALL_KERNEL
444 : void ips_sensors(void *);
445 : #endif
446 :
447 : int ips_load_xs(struct ips_softc *, struct ips_ccb *, struct scsi_xfer *);
448 : void ips_start_xs(struct ips_softc *, struct ips_ccb *, struct scsi_xfer *);
449 :
450 : int ips_cmd(struct ips_softc *, struct ips_ccb *);
451 : int ips_poll(struct ips_softc *, struct ips_ccb *);
452 : void ips_done(struct ips_softc *, struct ips_ccb *);
453 : void ips_done_xs(struct ips_softc *, struct ips_ccb *);
454 : void ips_done_pt(struct ips_softc *, struct ips_ccb *);
455 : void ips_done_mgmt(struct ips_softc *, struct ips_ccb *);
456 : int ips_error(struct ips_softc *, struct ips_ccb *);
457 : int ips_error_xs(struct ips_softc *, struct ips_ccb *);
458 : int ips_intr(void *);
459 : void ips_timeout(void *);
460 :
461 : int ips_getadapterinfo(struct ips_softc *, int);
462 : int ips_getdriveinfo(struct ips_softc *, int);
463 : int ips_getconf(struct ips_softc *, int);
464 : int ips_getpg5(struct ips_softc *, int);
465 :
466 : #if NBIO > 0
467 : int ips_getrblstat(struct ips_softc *, int);
468 : int ips_setstate(struct ips_softc *, int, int, int, int);
469 : int ips_rebuild(struct ips_softc *, int, int, int, int, int);
470 : #endif
471 :
472 : void ips_copperhead_exec(struct ips_softc *, struct ips_ccb *);
473 : void ips_copperhead_intren(struct ips_softc *);
474 : int ips_copperhead_isintr(struct ips_softc *);
475 : u_int32_t ips_copperhead_status(struct ips_softc *);
476 :
477 : void ips_morpheus_exec(struct ips_softc *, struct ips_ccb *);
478 : void ips_morpheus_intren(struct ips_softc *);
479 : int ips_morpheus_isintr(struct ips_softc *);
480 : u_int32_t ips_morpheus_status(struct ips_softc *);
481 :
482 : struct ips_ccb *ips_ccb_alloc(struct ips_softc *, int);
483 : void ips_ccb_free(struct ips_softc *, struct ips_ccb *, int);
484 : void *ips_ccb_get(void *);
485 : void ips_ccb_put(void *, void *);
486 :
487 : int ips_dmamem_alloc(struct dmamem *, bus_dma_tag_t, bus_size_t);
488 : void ips_dmamem_free(struct dmamem *);
489 :
490 : struct cfattach ips_ca = {
491 : sizeof(struct ips_softc),
492 : ips_match,
493 : ips_attach
494 : };
495 :
496 : struct cfdriver ips_cd = {
497 : NULL, "ips", DV_DULL
498 : };
499 :
500 : static struct scsi_adapter ips_scsi_adapter = {
501 : ips_scsi_cmd,
502 : scsi_minphys,
503 : NULL,
504 : NULL,
505 : ips_scsi_ioctl
506 : };
507 :
508 : static struct scsi_adapter ips_scsi_pt_adapter = {
509 : ips_scsi_pt_cmd,
510 : scsi_minphys,
511 : NULL,
512 : NULL,
513 : NULL
514 : };
515 :
516 : static const struct pci_matchid ips_ids[] = {
517 : { PCI_VENDOR_IBM, PCI_PRODUCT_IBM_SERVERAID },
518 : { PCI_VENDOR_IBM, PCI_PRODUCT_IBM_SERVERAID2 },
519 : { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_SERVERAID }
520 : };
521 :
522 : static const struct ips_chipset {
523 : enum {
524 : IPS_CHIP_COPPERHEAD = 0,
525 : IPS_CHIP_MORPHEUS
526 : } ic_id;
527 :
528 : int ic_bar;
529 :
530 : void (*ic_exec)(struct ips_softc *, struct ips_ccb *);
531 : void (*ic_intren)(struct ips_softc *);
532 : int (*ic_isintr)(struct ips_softc *);
533 : u_int32_t (*ic_status)(struct ips_softc *);
534 : } ips_chips[] = {
535 : {
536 : IPS_CHIP_COPPERHEAD,
537 : 0x14,
538 : ips_copperhead_exec,
539 : ips_copperhead_intren,
540 : ips_copperhead_isintr,
541 : ips_copperhead_status
542 : },
543 : {
544 : IPS_CHIP_MORPHEUS,
545 : 0x10,
546 : ips_morpheus_exec,
547 : ips_morpheus_intren,
548 : ips_morpheus_isintr,
549 : ips_morpheus_status
550 : }
551 : };
552 :
553 : #define ips_exec(s, c) (s)->sc_chip->ic_exec((s), (c))
554 : #define ips_intren(s) (s)->sc_chip->ic_intren((s))
555 : #define ips_isintr(s) (s)->sc_chip->ic_isintr((s))
556 : #define ips_status(s) (s)->sc_chip->ic_status((s))
557 :
558 : static const char *ips_names[] = {
559 : NULL,
560 : NULL,
561 : "II",
562 : "onboard",
563 : "onboard",
564 : "3H",
565 : "3L",
566 : "4H",
567 : "4M",
568 : "4L",
569 : "4Mx",
570 : "4Lx",
571 : "5i",
572 : "5i",
573 : "6M",
574 : "6i",
575 : "7t",
576 : "7k",
577 : "7M"
578 : };
579 :
580 : int
581 0 : ips_match(struct device *parent, void *match, void *aux)
582 : {
583 0 : return (pci_matchbyid(aux, ips_ids,
584 : sizeof(ips_ids) / sizeof(ips_ids[0])));
585 : }
586 :
587 : void
588 0 : ips_attach(struct device *parent, struct device *self, void *aux)
589 : {
590 0 : struct ips_softc *sc = (struct ips_softc *)self;
591 0 : struct pci_attach_args *pa = aux;
592 0 : struct ips_ccb ccb0;
593 0 : struct scsibus_attach_args saa;
594 : struct ips_adapterinfo *ai;
595 : struct ips_driveinfo *di;
596 : struct ips_pg5 *pg5;
597 : pcireg_t maptype;
598 0 : bus_size_t iosize;
599 0 : pci_intr_handle_t ih;
600 : const char *intrstr;
601 : int type, i;
602 :
603 0 : sc->sc_dmat = pa->pa_dmat;
604 :
605 : /* Identify chipset */
606 0 : if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_IBM_SERVERAID)
607 0 : sc->sc_chip = &ips_chips[IPS_CHIP_COPPERHEAD];
608 : else
609 0 : sc->sc_chip = &ips_chips[IPS_CHIP_MORPHEUS];
610 :
611 : /* Map registers */
612 0 : maptype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, sc->sc_chip->ic_bar);
613 0 : if (pci_mapreg_map(pa, sc->sc_chip->ic_bar, maptype, 0, &sc->sc_iot,
614 0 : &sc->sc_ioh, NULL, &iosize, IPS_IOSIZE)) {
615 0 : printf(": can't map regs\n");
616 0 : return;
617 : }
618 :
619 : /* Allocate command buffer */
620 0 : if (ips_dmamem_alloc(&sc->sc_cmdbm, sc->sc_dmat,
621 : IPS_MAXCMDS * sizeof(struct ips_cmdb))) {
622 0 : printf(": can't alloc cmd buffer\n");
623 0 : goto fail1;
624 : }
625 :
626 : /* Allocate info buffer */
627 0 : if (ips_dmamem_alloc(&sc->sc_infom, sc->sc_dmat,
628 : sizeof(struct ips_info))) {
629 0 : printf(": can't alloc info buffer\n");
630 0 : goto fail2;
631 : }
632 0 : sc->sc_info = sc->sc_infom.dm_vaddr;
633 0 : ai = &sc->sc_info->adapter;
634 0 : di = &sc->sc_info->drive;
635 0 : pg5 = &sc->sc_info->pg5;
636 :
637 : /* Allocate status queue for the Copperhead chipset */
638 0 : if (sc->sc_chip->ic_id == IPS_CHIP_COPPERHEAD) {
639 0 : if (ips_dmamem_alloc(&sc->sc_sqm, sc->sc_dmat, IPS_SQSZ)) {
640 0 : printf(": can't alloc status queue\n");
641 0 : goto fail3;
642 : }
643 0 : sc->sc_sqtail = sc->sc_sqm.dm_paddr;
644 0 : sc->sc_sqbuf = sc->sc_sqm.dm_vaddr;
645 0 : sc->sc_sqidx = 0;
646 0 : bus_space_write_4(sc->sc_iot, sc->sc_ioh, IPS_REG_SQS,
647 : sc->sc_sqm.dm_paddr);
648 0 : bus_space_write_4(sc->sc_iot, sc->sc_ioh, IPS_REG_SQE,
649 : sc->sc_sqm.dm_paddr + IPS_SQSZ);
650 0 : bus_space_write_4(sc->sc_iot, sc->sc_ioh, IPS_REG_SQH,
651 : sc->sc_sqm.dm_paddr + sizeof(u_int32_t));
652 0 : bus_space_write_4(sc->sc_iot, sc->sc_ioh, IPS_REG_SQT,
653 : sc->sc_sqm.dm_paddr);
654 0 : }
655 :
656 : /* Bootstrap CCB queue */
657 0 : sc->sc_nccbs = 1;
658 0 : sc->sc_ccb = &ccb0;
659 0 : bzero(&ccb0, sizeof(ccb0));
660 0 : ccb0.c_cmdbva = sc->sc_cmdbm.dm_vaddr;
661 0 : ccb0.c_cmdbpa = sc->sc_cmdbm.dm_paddr;
662 0 : SLIST_INIT(&sc->sc_ccbq_free);
663 0 : SLIST_INSERT_HEAD(&sc->sc_ccbq_free, &ccb0, c_link);
664 0 : mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
665 0 : scsi_iopool_init(&sc->sc_iopool, sc, ips_ccb_get, ips_ccb_put);
666 :
667 : /* Get adapter info */
668 0 : if (ips_getadapterinfo(sc, SCSI_NOSLEEP)) {
669 0 : printf(": can't get adapter info\n");
670 0 : goto fail4;
671 : }
672 :
673 : /* Get logical drives info */
674 0 : if (ips_getdriveinfo(sc, SCSI_NOSLEEP)) {
675 0 : printf(": can't get ld info\n");
676 0 : goto fail4;
677 : }
678 0 : sc->sc_nunits = di->drivecnt;
679 :
680 : /* Get configuration */
681 0 : if (ips_getconf(sc, SCSI_NOSLEEP)) {
682 0 : printf(": can't get config\n");
683 0 : goto fail4;
684 : }
685 :
686 : /* Read NVRAM page 5 for additional info */
687 0 : (void)ips_getpg5(sc, SCSI_NOSLEEP);
688 :
689 : /* Initialize CCB queue */
690 0 : sc->sc_nccbs = ai->cmdcnt;
691 0 : if ((sc->sc_ccb = ips_ccb_alloc(sc, sc->sc_nccbs)) == NULL) {
692 0 : printf(": can't alloc ccb queue\n");
693 0 : goto fail4;
694 : }
695 0 : SLIST_INIT(&sc->sc_ccbq_free);
696 0 : for (i = 0; i < sc->sc_nccbs; i++)
697 0 : SLIST_INSERT_HEAD(&sc->sc_ccbq_free,
698 : &sc->sc_ccb[i], c_link);
699 :
700 : /* Install interrupt handler */
701 0 : if (pci_intr_map(pa, &ih)) {
702 0 : printf(": can't map interrupt\n");
703 0 : goto fail5;
704 : }
705 0 : intrstr = pci_intr_string(pa->pa_pc, ih);
706 0 : if (pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ips_intr, sc,
707 0 : sc->sc_dev.dv_xname) == NULL) {
708 0 : printf(": can't establish interrupt");
709 0 : if (intrstr != NULL)
710 0 : printf(" at %s", intrstr);
711 0 : printf("\n");
712 0 : goto fail5;
713 : }
714 0 : printf(": %s\n", intrstr);
715 :
716 : /* Display adapter info */
717 0 : printf("%s: ServeRAID", sc->sc_dev.dv_xname);
718 0 : type = letoh16(pg5->type);
719 0 : if (type < sizeof(ips_names) / sizeof(ips_names[0]) && ips_names[type])
720 0 : printf(" %s", ips_names[type]);
721 0 : printf(", FW %c%c%c%c%c%c%c", ai->firmware[0], ai->firmware[1],
722 0 : ai->firmware[2], ai->firmware[3], ai->firmware[4], ai->firmware[5],
723 0 : ai->firmware[6]);
724 0 : printf(", BIOS %c%c%c%c%c%c%c", ai->bios[0], ai->bios[1], ai->bios[2],
725 0 : ai->bios[3], ai->bios[4], ai->bios[5], ai->bios[6]);
726 0 : printf(", %d cmds, %d LD%s", sc->sc_nccbs, sc->sc_nunits,
727 0 : (sc->sc_nunits == 1 ? "" : "s"));
728 0 : printf("\n");
729 :
730 : /* Attach SCSI bus */
731 0 : if (sc->sc_nunits > 0)
732 0 : sc->sc_scsi_link.openings = sc->sc_nccbs / sc->sc_nunits;
733 0 : sc->sc_scsi_link.adapter_target = sc->sc_nunits;
734 0 : sc->sc_scsi_link.adapter_buswidth = sc->sc_nunits;
735 0 : sc->sc_scsi_link.adapter = &ips_scsi_adapter;
736 0 : sc->sc_scsi_link.adapter_softc = sc;
737 0 : sc->sc_scsi_link.pool = &sc->sc_iopool;
738 :
739 0 : bzero(&saa, sizeof(saa));
740 0 : saa.saa_sc_link = &sc->sc_scsi_link;
741 0 : sc->sc_scsibus = (struct scsibus_softc *)config_found(self, &saa,
742 : scsiprint);
743 :
744 : /* For each channel attach SCSI pass-through bus */
745 0 : bzero(&saa, sizeof(saa));
746 0 : for (i = 0; i < IPS_MAXCHANS; i++) {
747 : struct ips_pt *pt;
748 : struct scsi_link *link;
749 : int target, lastarget;
750 :
751 0 : pt = &sc->sc_pt[i];
752 0 : pt->pt_sc = sc;
753 0 : pt->pt_chan = i;
754 0 : pt->pt_proctgt = -1;
755 :
756 : /* Check if channel has any devices besides disks */
757 0 : for (target = 0, lastarget = -1; target < IPS_MAXTARGETS;
758 0 : target++) {
759 : struct ips_dev *idev;
760 : int type;
761 :
762 0 : idev = &sc->sc_info->conf.dev[i][target];
763 0 : type = idev->params & SID_TYPE;
764 0 : if (idev->state && type != T_DIRECT) {
765 : lastarget = target;
766 0 : if (type == T_PROCESSOR ||
767 0 : type == T_ENCLOSURE)
768 : /* remember enclosure address */
769 0 : pt->pt_proctgt = target;
770 : }
771 : }
772 0 : if (lastarget == -1)
773 0 : continue;
774 :
775 0 : link = &pt->pt_link;
776 0 : link->openings = 1;
777 0 : link->adapter_target = IPS_MAXTARGETS;
778 0 : link->adapter_buswidth = lastarget + 1;
779 0 : link->adapter = &ips_scsi_pt_adapter;
780 0 : link->adapter_softc = pt;
781 0 : link->pool = &sc->sc_iopool;
782 :
783 0 : saa.saa_sc_link = link;
784 0 : config_found(self, &saa, scsiprint);
785 0 : }
786 :
787 : /* Enable interrupts */
788 0 : ips_intren(sc);
789 :
790 : #if NBIO > 0
791 : /* Install ioctl handler */
792 0 : if (bio_register(&sc->sc_dev, ips_ioctl))
793 0 : printf("%s: no ioctl support\n", sc->sc_dev.dv_xname);
794 : #endif
795 :
796 : #ifndef SMALL_KERNEL
797 : /* Add sensors */
798 0 : if ((sc->sc_sensors = mallocarray(sc->sc_nunits, sizeof(struct ksensor),
799 0 : M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
800 0 : printf(": can't alloc sensors\n");
801 0 : return;
802 : }
803 0 : strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
804 : sizeof(sc->sc_sensordev.xname));
805 0 : for (i = 0; i < sc->sc_nunits; i++) {
806 : struct device *dev;
807 :
808 0 : sc->sc_sensors[i].type = SENSOR_DRIVE;
809 0 : sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
810 0 : dev = scsi_get_link(sc->sc_scsibus, i, 0)->device_softc;
811 0 : strlcpy(sc->sc_sensors[i].desc, dev->dv_xname,
812 : sizeof(sc->sc_sensors[i].desc));
813 0 : sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
814 : }
815 0 : if (sensor_task_register(sc, ips_sensors, 10) == NULL) {
816 0 : printf(": no sensors support\n");
817 0 : free(sc->sc_sensors, M_DEVBUF,
818 0 : sc->sc_nunits * sizeof(struct ksensor));
819 0 : return;
820 : }
821 0 : sensordev_install(&sc->sc_sensordev);
822 : #endif /* !SMALL_KERNEL */
823 :
824 0 : return;
825 : fail5:
826 0 : ips_ccb_free(sc, sc->sc_ccb, sc->sc_nccbs);
827 : fail4:
828 0 : if (sc->sc_chip->ic_id == IPS_CHIP_COPPERHEAD)
829 0 : ips_dmamem_free(&sc->sc_sqm);
830 : fail3:
831 0 : ips_dmamem_free(&sc->sc_infom);
832 : fail2:
833 0 : ips_dmamem_free(&sc->sc_cmdbm);
834 : fail1:
835 0 : bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
836 0 : }
837 :
838 : void
839 0 : ips_scsi_cmd(struct scsi_xfer *xs)
840 : {
841 0 : struct scsi_link *link = xs->sc_link;
842 0 : struct ips_softc *sc = link->adapter_softc;
843 0 : struct ips_driveinfo *di = &sc->sc_info->drive;
844 : struct ips_drive *drive;
845 0 : struct scsi_inquiry_data inq;
846 0 : struct scsi_read_cap_data rcd;
847 0 : struct scsi_sense_data sd;
848 : struct scsi_rw *rw;
849 : struct scsi_rw_big *rwb;
850 0 : struct ips_ccb *ccb = xs->io;
851 : struct ips_cmd *cmd;
852 0 : int target = link->target;
853 : u_int32_t blkno, blkcnt;
854 : int code;
855 :
856 : DPRINTF(IPS_D_XFER, ("%s: ips_scsi_cmd: xs %p, target %d, "
857 : "opcode 0x%02x, flags 0x%x\n", sc->sc_dev.dv_xname, xs, target,
858 : xs->cmd->opcode, xs->flags));
859 :
860 0 : if (target >= sc->sc_nunits || link->lun != 0) {
861 : DPRINTF(IPS_D_INFO, ("%s: ips_scsi_cmd: invalid params "
862 : "target %d, lun %d\n", sc->sc_dev.dv_xname,
863 : target, link->lun));
864 0 : xs->error = XS_DRIVER_STUFFUP;
865 0 : scsi_done(xs);
866 0 : return;
867 : }
868 :
869 0 : drive = &di->drive[target];
870 0 : xs->error = XS_NOERROR;
871 :
872 : /* Fake SCSI commands */
873 0 : switch (xs->cmd->opcode) {
874 : case READ_BIG:
875 : case READ_COMMAND:
876 : case WRITE_BIG:
877 : case WRITE_COMMAND:
878 0 : if (xs->cmdlen == sizeof(struct scsi_rw)) {
879 0 : rw = (void *)xs->cmd;
880 0 : blkno = _3btol(rw->addr) &
881 : (SRW_TOPADDR << 16 | 0xffff);
882 0 : blkcnt = rw->length ? rw->length : 0x100;
883 0 : } else {
884 0 : rwb = (void *)xs->cmd;
885 0 : blkno = _4btol(rwb->addr);
886 0 : blkcnt = _2btol(rwb->length);
887 : }
888 :
889 0 : if (blkno >= letoh32(drive->seccnt) || blkno + blkcnt >
890 : letoh32(drive->seccnt)) {
891 : DPRINTF(IPS_D_ERR, ("%s: ips_scsi_cmd: invalid params "
892 : "blkno %u, blkcnt %u\n", sc->sc_dev.dv_xname,
893 : blkno, blkcnt));
894 0 : xs->error = XS_DRIVER_STUFFUP;
895 0 : break;
896 : }
897 :
898 0 : if (xs->flags & SCSI_DATA_IN)
899 0 : code = IPS_CMD_READ;
900 : else
901 : code = IPS_CMD_WRITE;
902 :
903 0 : ccb = xs->io;
904 :
905 0 : cmd = ccb->c_cmdbva;
906 0 : cmd->code = code;
907 0 : cmd->drive = target;
908 0 : cmd->lba = htole32(blkno);
909 0 : cmd->seccnt = htole16(blkcnt);
910 :
911 0 : if (ips_load_xs(sc, ccb, xs)) {
912 : DPRINTF(IPS_D_ERR, ("%s: ips_scsi_cmd: ips_load_xs "
913 : "failed\n", sc->sc_dev.dv_xname));
914 0 : xs->error = XS_DRIVER_STUFFUP;
915 0 : scsi_done(xs);
916 0 : return;
917 : }
918 :
919 0 : if (cmd->sgcnt > 0)
920 0 : cmd->code |= IPS_CMD_SG;
921 :
922 0 : ccb->c_done = ips_done_xs;
923 0 : ips_start_xs(sc, ccb, xs);
924 0 : return;
925 : case INQUIRY:
926 0 : bzero(&inq, sizeof(inq));
927 0 : inq.device = T_DIRECT;
928 0 : inq.version = 2;
929 0 : inq.response_format = 2;
930 0 : inq.additional_length = 32;
931 0 : inq.flags |= SID_CmdQue;
932 0 : strlcpy(inq.vendor, "IBM", sizeof(inq.vendor));
933 0 : snprintf(inq.product, sizeof(inq.product),
934 0 : "LD%d RAID%d", target, drive->raid);
935 0 : strlcpy(inq.revision, "1.0", sizeof(inq.revision));
936 0 : memcpy(xs->data, &inq, MIN(xs->datalen, sizeof(inq)));
937 0 : break;
938 : case READ_CAPACITY:
939 0 : bzero(&rcd, sizeof(rcd));
940 0 : _lto4b(letoh32(drive->seccnt) - 1, rcd.addr);
941 0 : _lto4b(IPS_SECSZ, rcd.length);
942 0 : memcpy(xs->data, &rcd, MIN(xs->datalen, sizeof(rcd)));
943 0 : break;
944 : case REQUEST_SENSE:
945 0 : bzero(&sd, sizeof(sd));
946 0 : sd.error_code = SSD_ERRCODE_CURRENT;
947 0 : sd.flags = SKEY_NO_SENSE;
948 0 : memcpy(xs->data, &sd, MIN(xs->datalen, sizeof(sd)));
949 0 : break;
950 : case SYNCHRONIZE_CACHE:
951 0 : cmd = ccb->c_cmdbva;
952 0 : cmd->code = IPS_CMD_FLUSH;
953 :
954 0 : ccb->c_done = ips_done_xs;
955 0 : ips_start_xs(sc, ccb, xs);
956 0 : return;
957 : case PREVENT_ALLOW:
958 : case START_STOP:
959 : case TEST_UNIT_READY:
960 : break;
961 : default:
962 : DPRINTF(IPS_D_INFO, ("%s: unsupported scsi command 0x%02x\n",
963 : sc->sc_dev.dv_xname, xs->cmd->opcode));
964 0 : xs->error = XS_DRIVER_STUFFUP;
965 0 : }
966 :
967 0 : scsi_done(xs);
968 0 : }
969 :
970 : void
971 0 : ips_scsi_pt_cmd(struct scsi_xfer *xs)
972 : {
973 0 : struct scsi_link *link = xs->sc_link;
974 0 : struct ips_pt *pt = link->adapter_softc;
975 0 : struct ips_softc *sc = pt->pt_sc;
976 0 : struct device *dev = link->device_softc;
977 0 : struct ips_ccb *ccb = xs->io;
978 : struct ips_cmdb *cmdb;
979 : struct ips_cmd *cmd;
980 : struct ips_dcdb *dcdb;
981 0 : int chan = pt->pt_chan, target = link->target;
982 :
983 : DPRINTF(IPS_D_XFER, ("%s: ips_scsi_pt_cmd: xs %p, chan %d, target %d, "
984 : "opcode 0x%02x, flags 0x%x\n", sc->sc_dev.dv_xname, xs, chan,
985 : target, xs->cmd->opcode, xs->flags));
986 :
987 0 : if (pt->pt_procdev[0] == '\0' && target == pt->pt_proctgt && dev)
988 0 : strlcpy(pt->pt_procdev, dev->dv_xname, sizeof(pt->pt_procdev));
989 :
990 0 : if (xs->cmdlen > IPS_MAXCDB) {
991 : DPRINTF(IPS_D_ERR, ("%s: cmdlen %d too big\n",
992 : sc->sc_dev.dv_xname, xs->cmdlen));
993 :
994 0 : bzero(&xs->sense, sizeof(xs->sense));
995 0 : xs->sense.error_code = SSD_ERRCODE_VALID | SSD_ERRCODE_CURRENT;
996 0 : xs->sense.flags = SKEY_ILLEGAL_REQUEST;
997 0 : xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */
998 0 : xs->error = XS_SENSE;
999 0 : scsi_done(xs);
1000 0 : return;
1001 : }
1002 :
1003 0 : xs->error = XS_NOERROR;
1004 :
1005 0 : cmdb = ccb->c_cmdbva;
1006 0 : cmd = &cmdb->cmd;
1007 0 : dcdb = &cmdb->dcdb;
1008 :
1009 0 : cmd->code = IPS_CMD_DCDB;
1010 :
1011 0 : dcdb->device = (chan << 4) | target;
1012 0 : if (xs->flags & SCSI_DATA_IN)
1013 0 : dcdb->attr |= IPS_DCDB_DATAIN;
1014 0 : if (xs->flags & SCSI_DATA_OUT)
1015 0 : dcdb->attr |= IPS_DCDB_DATAOUT;
1016 :
1017 : /*
1018 : * Adjust timeout value to what controller supports. Make sure our
1019 : * timeout will be fired after controller gives up.
1020 : */
1021 0 : if (xs->timeout <= 10000) {
1022 0 : dcdb->attr |= IPS_DCDB_TIMO10;
1023 0 : xs->timeout = 11000;
1024 0 : } else if (xs->timeout <= 60000) {
1025 0 : dcdb->attr |= IPS_DCDB_TIMO60;
1026 0 : xs->timeout = 61000;
1027 0 : } else {
1028 0 : dcdb->attr |= IPS_DCDB_TIMO20M;
1029 0 : xs->timeout = 20 * 60000 + 1000;
1030 : }
1031 :
1032 0 : dcdb->attr |= IPS_DCDB_DISCON;
1033 0 : dcdb->datalen = htole16(xs->datalen);
1034 0 : dcdb->cdblen = xs->cmdlen;
1035 0 : dcdb->senselen = MIN(sizeof(xs->sense), sizeof(dcdb->sense));
1036 0 : memcpy(dcdb->cdb, xs->cmd, xs->cmdlen);
1037 :
1038 0 : if (ips_load_xs(sc, ccb, xs)) {
1039 : DPRINTF(IPS_D_ERR, ("%s: ips_scsi_pt_cmd: ips_load_xs "
1040 : "failed\n", sc->sc_dev.dv_xname));
1041 0 : xs->error = XS_DRIVER_STUFFUP;
1042 0 : scsi_done(xs);
1043 0 : return;
1044 : }
1045 0 : if (cmd->sgcnt > 0)
1046 0 : cmd->code |= IPS_CMD_SG;
1047 0 : dcdb->sgaddr = cmd->sgaddr;
1048 0 : dcdb->sgcnt = cmd->sgcnt;
1049 0 : cmd->sgaddr = htole32(ccb->c_cmdbpa + offsetof(struct ips_cmdb, dcdb));
1050 0 : cmd->sgcnt = 0;
1051 :
1052 0 : ccb->c_done = ips_done_pt;
1053 0 : ips_start_xs(sc, ccb, xs);
1054 0 : }
1055 :
1056 : int
1057 0 : ips_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag)
1058 : {
1059 : #if NBIO > 0
1060 0 : return (ips_ioctl(link->adapter_softc, cmd, addr));
1061 : #else
1062 : return (ENOTTY);
1063 : #endif
1064 : }
1065 :
1066 : #if NBIO > 0
1067 : int
1068 0 : ips_ioctl(struct device *dev, u_long cmd, caddr_t addr)
1069 : {
1070 0 : struct ips_softc *sc = (struct ips_softc *)dev;
1071 :
1072 : DPRINTF(IPS_D_INFO, ("%s: ips_ioctl: cmd %lu\n",
1073 : sc->sc_dev.dv_xname, cmd));
1074 :
1075 0 : switch (cmd) {
1076 : case BIOCINQ:
1077 0 : return (ips_ioctl_inq(sc, (struct bioc_inq *)addr));
1078 : case BIOCVOL:
1079 0 : return (ips_ioctl_vol(sc, (struct bioc_vol *)addr));
1080 : case BIOCDISK:
1081 0 : return (ips_ioctl_disk(sc, (struct bioc_disk *)addr));
1082 : case BIOCSETSTATE:
1083 0 : return (ips_ioctl_setstate(sc, (struct bioc_setstate *)addr));
1084 : default:
1085 0 : return (ENOTTY);
1086 : }
1087 0 : }
1088 :
1089 : int
1090 0 : ips_ioctl_inq(struct ips_softc *sc, struct bioc_inq *bi)
1091 : {
1092 0 : struct ips_conf *conf = &sc->sc_info->conf;
1093 : int i;
1094 :
1095 0 : strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev));
1096 0 : bi->bi_novol = sc->sc_nunits;
1097 0 : for (i = 0, bi->bi_nodisk = 0; i < sc->sc_nunits; i++)
1098 0 : bi->bi_nodisk += conf->ld[i].chunkcnt;
1099 :
1100 : DPRINTF(IPS_D_INFO, ("%s: ips_ioctl_inq: novol %d, nodisk %d\n",
1101 : bi->bi_dev, bi->bi_novol, bi->bi_nodisk));
1102 :
1103 0 : return (0);
1104 : }
1105 :
1106 : int
1107 0 : ips_ioctl_vol(struct ips_softc *sc, struct bioc_vol *bv)
1108 : {
1109 0 : struct ips_driveinfo *di = &sc->sc_info->drive;
1110 0 : struct ips_conf *conf = &sc->sc_info->conf;
1111 0 : struct ips_rblstat *rblstat = &sc->sc_info->rblstat;
1112 : struct ips_ld *ld;
1113 0 : int vid = bv->bv_volid;
1114 : struct device *dv;
1115 : int error, rebuild = 0;
1116 : u_int32_t total = 0, done = 0;
1117 :
1118 0 : if (vid >= sc->sc_nunits)
1119 0 : return (EINVAL);
1120 0 : if ((error = ips_getconf(sc, 0)))
1121 0 : return (error);
1122 0 : ld = &conf->ld[vid];
1123 :
1124 0 : switch (ld->state) {
1125 : case IPS_DS_ONLINE:
1126 0 : bv->bv_status = BIOC_SVONLINE;
1127 0 : break;
1128 : case IPS_DS_DEGRADED:
1129 0 : bv->bv_status = BIOC_SVDEGRADED;
1130 : rebuild++;
1131 0 : break;
1132 : case IPS_DS_OFFLINE:
1133 0 : bv->bv_status = BIOC_SVOFFLINE;
1134 0 : break;
1135 : default:
1136 0 : bv->bv_status = BIOC_SVINVALID;
1137 0 : }
1138 :
1139 0 : if (rebuild && ips_getrblstat(sc, 0) == 0) {
1140 0 : total = letoh32(rblstat->ld[vid].total);
1141 0 : done = total - letoh32(rblstat->ld[vid].remain);
1142 0 : if (total && total > done) {
1143 0 : bv->bv_status = BIOC_SVREBUILD;
1144 0 : bv->bv_percent = 100 * done / total;
1145 0 : }
1146 : }
1147 :
1148 0 : bv->bv_size = (uint64_t)letoh32(ld->size) * IPS_SECSZ;
1149 0 : bv->bv_level = di->drive[vid].raid;
1150 0 : bv->bv_nodisk = ld->chunkcnt;
1151 :
1152 : /* Associate all unused and spare drives with first volume */
1153 0 : if (vid == 0) {
1154 : struct ips_dev *dev;
1155 : int chan, target;
1156 :
1157 0 : for (chan = 0; chan < IPS_MAXCHANS; chan++)
1158 0 : for (target = 0; target < IPS_MAXTARGETS; target++) {
1159 0 : dev = &conf->dev[chan][target];
1160 0 : if (dev->state && !(dev->state &
1161 0 : IPS_DVS_MEMBER) &&
1162 0 : (dev->params & SID_TYPE) == T_DIRECT)
1163 0 : bv->bv_nodisk++;
1164 : }
1165 0 : }
1166 :
1167 0 : dv = scsi_get_link(sc->sc_scsibus, vid, 0)->device_softc;
1168 0 : strlcpy(bv->bv_dev, dv->dv_xname, sizeof(bv->bv_dev));
1169 0 : strlcpy(bv->bv_vendor, "IBM", sizeof(bv->bv_vendor));
1170 :
1171 : DPRINTF(IPS_D_INFO, ("%s: ips_ioctl_vol: vid %d, state 0x%02x, "
1172 : "total %u, done %u, size %llu, level %d, nodisk %d, dev %s\n",
1173 : sc->sc_dev.dv_xname, vid, ld->state, total, done, bv->bv_size,
1174 : bv->bv_level, bv->bv_nodisk, bv->bv_dev));
1175 :
1176 0 : return (0);
1177 0 : }
1178 :
1179 : int
1180 0 : ips_ioctl_disk(struct ips_softc *sc, struct bioc_disk *bd)
1181 : {
1182 0 : struct ips_conf *conf = &sc->sc_info->conf;
1183 : struct ips_ld *ld;
1184 : struct ips_chunk *chunk;
1185 : struct ips_dev *dev;
1186 0 : int vid = bd->bd_volid, did = bd->bd_diskid;
1187 : int chan, target, error, i;
1188 :
1189 0 : if (vid >= sc->sc_nunits)
1190 0 : return (EINVAL);
1191 0 : if ((error = ips_getconf(sc, 0)))
1192 0 : return (error);
1193 0 : ld = &conf->ld[vid];
1194 :
1195 0 : if (did >= ld->chunkcnt) {
1196 : /* Probably unused or spare drives */
1197 0 : if (vid != 0)
1198 0 : return (EINVAL);
1199 :
1200 : i = ld->chunkcnt;
1201 0 : for (chan = 0; chan < IPS_MAXCHANS; chan++)
1202 0 : for (target = 0; target < IPS_MAXTARGETS; target++) {
1203 0 : dev = &conf->dev[chan][target];
1204 0 : if (dev->state && !(dev->state &
1205 0 : IPS_DVS_MEMBER) &&
1206 0 : (dev->params & SID_TYPE) == T_DIRECT)
1207 0 : if (i++ == did)
1208 : goto out;
1209 : }
1210 : } else {
1211 0 : chunk = &ld->chunk[did];
1212 0 : chan = chunk->channel;
1213 0 : target = chunk->target;
1214 : }
1215 :
1216 : out:
1217 0 : if (chan >= IPS_MAXCHANS || target >= IPS_MAXTARGETS)
1218 0 : return (EINVAL);
1219 0 : dev = &conf->dev[chan][target];
1220 :
1221 0 : bd->bd_channel = chan;
1222 0 : bd->bd_target = target;
1223 0 : bd->bd_lun = 0;
1224 0 : bd->bd_size = (uint64_t)letoh32(dev->seccnt) * IPS_SECSZ;
1225 :
1226 0 : bzero(bd->bd_vendor, sizeof(bd->bd_vendor));
1227 0 : memcpy(bd->bd_vendor, dev->devid, MIN(sizeof(bd->bd_vendor),
1228 : sizeof(dev->devid)));
1229 0 : strlcpy(bd->bd_procdev, sc->sc_pt[chan].pt_procdev,
1230 : sizeof(bd->bd_procdev));
1231 :
1232 0 : if (dev->state & IPS_DVS_READY) {
1233 0 : bd->bd_status = BIOC_SDUNUSED;
1234 0 : if (dev->state & IPS_DVS_MEMBER)
1235 0 : bd->bd_status = BIOC_SDONLINE;
1236 0 : if (dev->state & IPS_DVS_SPARE)
1237 0 : bd->bd_status = BIOC_SDHOTSPARE;
1238 0 : if (dev->state & IPS_DVS_REBUILD)
1239 0 : bd->bd_status = BIOC_SDREBUILD;
1240 : } else {
1241 0 : bd->bd_status = BIOC_SDOFFLINE;
1242 : }
1243 :
1244 : DPRINTF(IPS_D_INFO, ("%s: ips_ioctl_disk: vid %d, did %d, channel %d, "
1245 : "target %d, size %llu, state 0x%02x\n", sc->sc_dev.dv_xname,
1246 : vid, did, bd->bd_channel, bd->bd_target, bd->bd_size, dev->state));
1247 :
1248 0 : return (0);
1249 0 : }
1250 :
1251 : int
1252 0 : ips_ioctl_setstate(struct ips_softc *sc, struct bioc_setstate *bs)
1253 : {
1254 0 : struct ips_conf *conf = &sc->sc_info->conf;
1255 : struct ips_dev *dev;
1256 : int state, error;
1257 :
1258 0 : if (bs->bs_channel >= IPS_MAXCHANS || bs->bs_target >= IPS_MAXTARGETS)
1259 0 : return (EINVAL);
1260 0 : if ((error = ips_getconf(sc, 0)))
1261 0 : return (error);
1262 0 : dev = &conf->dev[bs->bs_channel][bs->bs_target];
1263 0 : state = dev->state;
1264 :
1265 0 : switch (bs->bs_status) {
1266 : case BIOC_SSONLINE:
1267 0 : state |= IPS_DVS_READY;
1268 0 : break;
1269 : case BIOC_SSOFFLINE:
1270 0 : state &= ~IPS_DVS_READY;
1271 0 : break;
1272 : case BIOC_SSHOTSPARE:
1273 0 : state |= IPS_DVS_SPARE;
1274 0 : break;
1275 : case BIOC_SSREBUILD:
1276 0 : return (ips_rebuild(sc, bs->bs_channel, bs->bs_target,
1277 : bs->bs_channel, bs->bs_target, 0));
1278 : default:
1279 0 : return (EINVAL);
1280 : }
1281 :
1282 0 : return (ips_setstate(sc, bs->bs_channel, bs->bs_target, state, 0));
1283 0 : }
1284 : #endif /* NBIO > 0 */
1285 :
1286 : #ifndef SMALL_KERNEL
1287 : void
1288 0 : ips_sensors(void *arg)
1289 : {
1290 0 : struct ips_softc *sc = arg;
1291 0 : struct ips_conf *conf = &sc->sc_info->conf;
1292 : struct ips_ld *ld;
1293 : int i;
1294 :
1295 : /* ips_sensors() runs from work queue thus allowed to sleep */
1296 0 : if (ips_getconf(sc, 0)) {
1297 : DPRINTF(IPS_D_ERR, ("%s: ips_sensors: ips_getconf failed\n",
1298 : sc->sc_dev.dv_xname));
1299 :
1300 0 : for (i = 0; i < sc->sc_nunits; i++) {
1301 0 : sc->sc_sensors[i].value = 0;
1302 0 : sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
1303 : }
1304 0 : return;
1305 : }
1306 :
1307 : DPRINTF(IPS_D_INFO, ("%s: ips_sensors:", sc->sc_dev.dv_xname));
1308 0 : for (i = 0; i < sc->sc_nunits; i++) {
1309 0 : ld = &conf->ld[i];
1310 : DPRINTF(IPS_D_INFO, (" ld%d.state 0x%02x", i, ld->state));
1311 0 : switch (ld->state) {
1312 : case IPS_DS_ONLINE:
1313 0 : sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE;
1314 0 : sc->sc_sensors[i].status = SENSOR_S_OK;
1315 0 : break;
1316 : case IPS_DS_DEGRADED:
1317 0 : sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL;
1318 0 : sc->sc_sensors[i].status = SENSOR_S_WARN;
1319 0 : break;
1320 : case IPS_DS_OFFLINE:
1321 0 : sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL;
1322 0 : sc->sc_sensors[i].status = SENSOR_S_CRIT;
1323 0 : break;
1324 : default:
1325 0 : sc->sc_sensors[i].value = 0;
1326 0 : sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
1327 0 : }
1328 : }
1329 : DPRINTF(IPS_D_INFO, ("\n"));
1330 0 : }
1331 : #endif /* !SMALL_KERNEL */
1332 :
1333 : int
1334 0 : ips_load_xs(struct ips_softc *sc, struct ips_ccb *ccb, struct scsi_xfer *xs)
1335 : {
1336 0 : struct ips_cmdb *cmdb = ccb->c_cmdbva;
1337 0 : struct ips_cmd *cmd = &cmdb->cmd;
1338 0 : struct ips_sg *sg = cmdb->sg;
1339 : int nsegs, i;
1340 :
1341 0 : if (xs->datalen == 0)
1342 0 : return (0);
1343 :
1344 : /* Map data buffer into DMA segments */
1345 0 : if (bus_dmamap_load(sc->sc_dmat, ccb->c_dmam, xs->data, xs->datalen,
1346 : NULL, (xs->flags & SCSI_NOSLEEP ? BUS_DMA_NOWAIT : 0)))
1347 0 : return (1);
1348 0 : bus_dmamap_sync(sc->sc_dmat, ccb->c_dmam, 0,ccb->c_dmam->dm_mapsize,
1349 : xs->flags & SCSI_DATA_IN ? BUS_DMASYNC_PREREAD :
1350 : BUS_DMASYNC_PREWRITE);
1351 :
1352 0 : if ((nsegs = ccb->c_dmam->dm_nsegs) > IPS_MAXSGS)
1353 0 : return (1);
1354 :
1355 0 : if (nsegs > 1) {
1356 0 : cmd->sgcnt = nsegs;
1357 0 : cmd->sgaddr = htole32(ccb->c_cmdbpa + offsetof(struct ips_cmdb,
1358 : sg));
1359 :
1360 : /* Fill in scatter-gather array */
1361 0 : for (i = 0; i < nsegs; i++) {
1362 0 : sg[i].addr = htole32(ccb->c_dmam->dm_segs[i].ds_addr);
1363 0 : sg[i].size = htole32(ccb->c_dmam->dm_segs[i].ds_len);
1364 : }
1365 : } else {
1366 0 : cmd->sgcnt = 0;
1367 0 : cmd->sgaddr = htole32(ccb->c_dmam->dm_segs[0].ds_addr);
1368 : }
1369 :
1370 0 : return (0);
1371 0 : }
1372 :
1373 : void
1374 0 : ips_start_xs(struct ips_softc *sc, struct ips_ccb *ccb, struct scsi_xfer *xs)
1375 : {
1376 0 : ccb->c_flags = xs->flags;
1377 0 : ccb->c_xfer = xs;
1378 0 : int ispoll = xs->flags & SCSI_POLL;
1379 :
1380 0 : if (!ispoll) {
1381 0 : timeout_set(&xs->stimeout, ips_timeout, ccb);
1382 0 : timeout_add_msec(&xs->stimeout, xs->timeout);
1383 0 : }
1384 :
1385 : /*
1386 : * Return value not used here because ips_cmd() must complete
1387 : * scsi_xfer on any failure and SCSI layer will handle possible
1388 : * errors.
1389 : */
1390 0 : ips_cmd(sc, ccb);
1391 0 : }
1392 :
1393 : int
1394 0 : ips_cmd(struct ips_softc *sc, struct ips_ccb *ccb)
1395 : {
1396 0 : struct ips_cmd *cmd = ccb->c_cmdbva;
1397 : int s, error = 0;
1398 :
1399 : DPRINTF(IPS_D_XFER, ("%s: ips_cmd: id 0x%02x, flags 0x%x, xs %p, "
1400 : "code 0x%02x, drive %d, sgcnt %d, lba %d, sgaddr 0x%08x, "
1401 : "seccnt %d\n", sc->sc_dev.dv_xname, ccb->c_id, ccb->c_flags,
1402 : ccb->c_xfer, cmd->code, cmd->drive, cmd->sgcnt, letoh32(cmd->lba),
1403 : letoh32(cmd->sgaddr), letoh16(cmd->seccnt)));
1404 :
1405 0 : cmd->id = ccb->c_id;
1406 :
1407 : /* Post command to controller and optionally wait for completion */
1408 0 : s = splbio();
1409 0 : ips_exec(sc, ccb);
1410 0 : ccb->c_state = IPS_CCB_QUEUED;
1411 0 : if (ccb->c_flags & SCSI_POLL)
1412 0 : error = ips_poll(sc, ccb);
1413 0 : splx(s);
1414 :
1415 0 : return (error);
1416 : }
1417 :
1418 : int
1419 0 : ips_poll(struct ips_softc *sc, struct ips_ccb *ccb)
1420 : {
1421 0 : struct timeval tv;
1422 : int error, timo;
1423 :
1424 0 : splassert(IPL_BIO);
1425 :
1426 0 : if (ccb->c_flags & SCSI_NOSLEEP) {
1427 : /* busy-wait */
1428 : DPRINTF(IPS_D_XFER, ("%s: ips_poll: busy-wait\n",
1429 : sc->sc_dev.dv_xname));
1430 :
1431 0 : for (timo = 10000; timo > 0; timo--) {
1432 0 : delay(100);
1433 0 : ips_intr(sc);
1434 0 : if (ccb->c_state == IPS_CCB_DONE)
1435 : break;
1436 : }
1437 : } else {
1438 : /* sleep */
1439 0 : timo = ccb->c_xfer ? ccb->c_xfer->timeout : IPS_TIMEOUT;
1440 0 : tv.tv_sec = timo / 1000;
1441 0 : tv.tv_usec = (timo % 1000) * 1000;
1442 0 : timo = tvtohz(&tv);
1443 :
1444 : DPRINTF(IPS_D_XFER, ("%s: ips_poll: sleep %d hz\n",
1445 : sc->sc_dev.dv_xname, timo));
1446 0 : tsleep(ccb, PRIBIO + 1, "ipscmd", timo);
1447 : }
1448 : DPRINTF(IPS_D_XFER, ("%s: ips_poll: state %d\n", sc->sc_dev.dv_xname,
1449 : ccb->c_state));
1450 :
1451 0 : if (ccb->c_state != IPS_CCB_DONE)
1452 : /*
1453 : * Command never completed. Fake hardware status byte
1454 : * to indicate timeout.
1455 : */
1456 0 : ccb->c_stat = IPS_STAT_TIMO;
1457 :
1458 0 : ips_done(sc, ccb);
1459 0 : error = ccb->c_error;
1460 :
1461 0 : return (error);
1462 0 : }
1463 :
1464 : void
1465 0 : ips_done(struct ips_softc *sc, struct ips_ccb *ccb)
1466 : {
1467 0 : splassert(IPL_BIO);
1468 :
1469 : DPRINTF(IPS_D_XFER, ("%s: ips_done: id 0x%02x, flags 0x%x, xs %p\n",
1470 : sc->sc_dev.dv_xname, ccb->c_id, ccb->c_flags, ccb->c_xfer));
1471 :
1472 0 : ccb->c_error = ips_error(sc, ccb);
1473 0 : ccb->c_done(sc, ccb);
1474 0 : }
1475 :
1476 : void
1477 0 : ips_done_xs(struct ips_softc *sc, struct ips_ccb *ccb)
1478 : {
1479 0 : struct scsi_xfer *xs = ccb->c_xfer;
1480 :
1481 0 : if (!(xs->flags & SCSI_POLL))
1482 0 : timeout_del(&xs->stimeout);
1483 :
1484 0 : if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1485 0 : bus_dmamap_sync(sc->sc_dmat, ccb->c_dmam, 0,
1486 : ccb->c_dmam->dm_mapsize, xs->flags & SCSI_DATA_IN ?
1487 : BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1488 0 : bus_dmamap_unload(sc->sc_dmat, ccb->c_dmam);
1489 0 : }
1490 :
1491 0 : xs->resid = 0;
1492 0 : xs->error = ips_error_xs(sc, ccb);
1493 0 : scsi_done(xs);
1494 0 : }
1495 :
1496 : void
1497 0 : ips_done_pt(struct ips_softc *sc, struct ips_ccb *ccb)
1498 : {
1499 0 : struct scsi_xfer *xs = ccb->c_xfer;
1500 0 : struct ips_cmdb *cmdb = ccb->c_cmdbva;
1501 0 : struct ips_dcdb *dcdb = &cmdb->dcdb;
1502 0 : int done = letoh16(dcdb->datalen);
1503 :
1504 0 : if (!(xs->flags & SCSI_POLL))
1505 0 : timeout_del(&xs->stimeout);
1506 :
1507 0 : if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1508 0 : bus_dmamap_sync(sc->sc_dmat, ccb->c_dmam, 0,
1509 : ccb->c_dmam->dm_mapsize, xs->flags & SCSI_DATA_IN ?
1510 : BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1511 0 : bus_dmamap_unload(sc->sc_dmat, ccb->c_dmam);
1512 0 : }
1513 :
1514 0 : if (done && done < xs->datalen)
1515 0 : xs->resid = xs->datalen - done;
1516 : else
1517 0 : xs->resid = 0;
1518 0 : xs->error = ips_error_xs(sc, ccb);
1519 0 : xs->status = dcdb->status;
1520 :
1521 0 : if (xs->error == XS_SENSE)
1522 0 : memcpy(&xs->sense, dcdb->sense, MIN(sizeof(xs->sense),
1523 : sizeof(dcdb->sense)));
1524 :
1525 0 : if (xs->cmd->opcode == INQUIRY && xs->error == XS_NOERROR) {
1526 0 : int type = ((struct scsi_inquiry_data *)xs->data)->device &
1527 : SID_TYPE;
1528 :
1529 0 : if (type == T_DIRECT)
1530 : /* mask physical drives */
1531 0 : xs->error = XS_DRIVER_STUFFUP;
1532 0 : }
1533 :
1534 0 : scsi_done(xs);
1535 0 : }
1536 :
1537 : void
1538 0 : ips_done_mgmt(struct ips_softc *sc, struct ips_ccb *ccb)
1539 : {
1540 0 : if (ccb->c_flags & (SCSI_DATA_IN | SCSI_DATA_OUT))
1541 0 : bus_dmamap_sync(sc->sc_dmat, sc->sc_infom.dm_map, 0,
1542 : sc->sc_infom.dm_map->dm_mapsize,
1543 : ccb->c_flags & SCSI_DATA_IN ? BUS_DMASYNC_POSTREAD :
1544 : BUS_DMASYNC_POSTWRITE);
1545 0 : scsi_io_put(&sc->sc_iopool, ccb);
1546 0 : }
1547 :
1548 : int
1549 0 : ips_error(struct ips_softc *sc, struct ips_ccb *ccb)
1550 : {
1551 0 : struct ips_cmdb *cmdb = ccb->c_cmdbva;
1552 0 : struct ips_cmd *cmd = &cmdb->cmd;
1553 0 : struct ips_dcdb *dcdb = &cmdb->dcdb;
1554 0 : struct scsi_xfer *xs = ccb->c_xfer;
1555 0 : u_int8_t gsc = IPS_STAT_GSC(ccb->c_stat);
1556 :
1557 0 : if (gsc == IPS_STAT_OK)
1558 0 : return (0);
1559 :
1560 : DPRINTF(IPS_D_ERR, ("%s: ips_error: stat 0x%02x, estat 0x%02x, "
1561 : "cmd code 0x%02x, drive %d, sgcnt %d, lba %u, seccnt %d",
1562 : sc->sc_dev.dv_xname, ccb->c_stat, ccb->c_estat, cmd->code,
1563 : cmd->drive, cmd->sgcnt, letoh32(cmd->lba), letoh16(cmd->seccnt)));
1564 0 : if (cmd->code == IPS_CMD_DCDB || cmd->code == IPS_CMD_DCDB_SG) {
1565 : int i;
1566 :
1567 : DPRINTF(IPS_D_ERR, (", dcdb device 0x%02x, attr 0x%02x, "
1568 : "datalen %d, sgcnt %d, status 0x%02x",
1569 : dcdb->device, dcdb->attr, letoh16(dcdb->datalen),
1570 : dcdb->sgcnt, dcdb->status));
1571 :
1572 : DPRINTF(IPS_D_ERR, (", cdb"));
1573 0 : for (i = 0; i < dcdb->cdblen; i++)
1574 : DPRINTF(IPS_D_ERR, (" %x", dcdb->cdb[i]));
1575 0 : if (ccb->c_estat == IPS_ESTAT_CKCOND) {
1576 : DPRINTF(IPS_D_ERR, (", sense"));
1577 0 : for (i = 0; i < dcdb->senselen; i++)
1578 : DPRINTF(IPS_D_ERR, (" %x", dcdb->sense[i]));
1579 : }
1580 0 : }
1581 : DPRINTF(IPS_D_ERR, ("\n"));
1582 :
1583 0 : switch (gsc) {
1584 : case IPS_STAT_RECOV:
1585 0 : return (0);
1586 : case IPS_STAT_INVOP:
1587 : case IPS_STAT_INVCMD:
1588 : case IPS_STAT_INVPARM:
1589 0 : return (EINVAL);
1590 : case IPS_STAT_BUSY:
1591 0 : return (EBUSY);
1592 : case IPS_STAT_TIMO:
1593 0 : return (ETIMEDOUT);
1594 : case IPS_STAT_PDRVERR:
1595 0 : switch (ccb->c_estat) {
1596 : case IPS_ESTAT_SELTIMO:
1597 0 : return (ENODEV);
1598 : case IPS_ESTAT_OURUN:
1599 0 : if (xs && letoh16(dcdb->datalen) < xs->datalen)
1600 : /* underrun */
1601 0 : return (0);
1602 : break;
1603 : case IPS_ESTAT_RECOV:
1604 0 : return (0);
1605 : }
1606 : break;
1607 : }
1608 :
1609 0 : return (EIO);
1610 0 : }
1611 :
1612 : int
1613 0 : ips_error_xs(struct ips_softc *sc, struct ips_ccb *ccb)
1614 : {
1615 0 : struct ips_cmdb *cmdb = ccb->c_cmdbva;
1616 0 : struct ips_dcdb *dcdb = &cmdb->dcdb;
1617 0 : struct scsi_xfer *xs = ccb->c_xfer;
1618 0 : u_int8_t gsc = IPS_STAT_GSC(ccb->c_stat);
1619 :
1620 : /* Map hardware error codes to SCSI ones */
1621 0 : switch (gsc) {
1622 : case IPS_STAT_OK:
1623 : case IPS_STAT_RECOV:
1624 0 : return (XS_NOERROR);
1625 : case IPS_STAT_BUSY:
1626 0 : return (XS_BUSY);
1627 : case IPS_STAT_TIMO:
1628 0 : return (XS_TIMEOUT);
1629 : case IPS_STAT_PDRVERR:
1630 0 : switch (ccb->c_estat) {
1631 : case IPS_ESTAT_SELTIMO:
1632 0 : return (XS_SELTIMEOUT);
1633 : case IPS_ESTAT_OURUN:
1634 0 : if (xs && letoh16(dcdb->datalen) < xs->datalen)
1635 : /* underrun */
1636 0 : return (XS_NOERROR);
1637 : break;
1638 : case IPS_ESTAT_HOSTRST:
1639 : case IPS_ESTAT_DEVRST:
1640 0 : return (XS_RESET);
1641 : case IPS_ESTAT_RECOV:
1642 0 : return (XS_NOERROR);
1643 : case IPS_ESTAT_CKCOND:
1644 0 : return (XS_SENSE);
1645 : }
1646 : break;
1647 : }
1648 :
1649 0 : return (XS_DRIVER_STUFFUP);
1650 0 : }
1651 :
1652 : int
1653 0 : ips_intr(void *arg)
1654 : {
1655 0 : struct ips_softc *sc = arg;
1656 : struct ips_ccb *ccb;
1657 : u_int32_t status;
1658 : int id;
1659 :
1660 : DPRINTF(IPS_D_XFER, ("%s: ips_intr", sc->sc_dev.dv_xname));
1661 0 : if (!ips_isintr(sc)) {
1662 : DPRINTF(IPS_D_XFER, (": not ours\n"));
1663 0 : return (0);
1664 : }
1665 : DPRINTF(IPS_D_XFER, ("\n"));
1666 :
1667 : /* Process completed commands */
1668 0 : while ((status = ips_status(sc)) != 0xffffffff) {
1669 : DPRINTF(IPS_D_XFER, ("%s: ips_intr: status 0x%08x\n",
1670 : sc->sc_dev.dv_xname, status));
1671 :
1672 0 : id = IPS_STAT_ID(status);
1673 0 : if (id >= sc->sc_nccbs) {
1674 : DPRINTF(IPS_D_ERR, ("%s: ips_intr: invalid id %d\n",
1675 : sc->sc_dev.dv_xname, id));
1676 0 : continue;
1677 : }
1678 :
1679 0 : ccb = &sc->sc_ccb[id];
1680 0 : if (ccb->c_state != IPS_CCB_QUEUED) {
1681 : DPRINTF(IPS_D_ERR, ("%s: ips_intr: cmd 0x%02x not "
1682 : "queued, state %d, status 0x%08x\n",
1683 : sc->sc_dev.dv_xname, ccb->c_id, ccb->c_state,
1684 : status));
1685 0 : continue;
1686 : }
1687 :
1688 0 : ccb->c_state = IPS_CCB_DONE;
1689 0 : ccb->c_stat = IPS_STAT_BASIC(status);
1690 0 : ccb->c_estat = IPS_STAT_EXT(status);
1691 :
1692 0 : if (ccb->c_flags & SCSI_POLL) {
1693 0 : wakeup(ccb);
1694 0 : } else {
1695 0 : ips_done(sc, ccb);
1696 : }
1697 : }
1698 :
1699 0 : return (1);
1700 0 : }
1701 :
1702 : void
1703 0 : ips_timeout(void *arg)
1704 : {
1705 0 : struct ips_ccb *ccb = arg;
1706 0 : struct ips_softc *sc = ccb->c_sc;
1707 0 : struct scsi_xfer *xs = ccb->c_xfer;
1708 : int s;
1709 :
1710 0 : s = splbio();
1711 0 : if (xs)
1712 0 : sc_print_addr(xs->sc_link);
1713 : else
1714 0 : printf("%s: ", sc->sc_dev.dv_xname);
1715 0 : printf("timeout\n");
1716 :
1717 : /*
1718 : * Command never completed. Fake hardware status byte
1719 : * to indicate timeout.
1720 : * XXX: need to remove command from controller.
1721 : */
1722 0 : ccb->c_stat = IPS_STAT_TIMO;
1723 0 : ips_done(sc, ccb);
1724 0 : splx(s);
1725 0 : }
1726 :
1727 : int
1728 0 : ips_getadapterinfo(struct ips_softc *sc, int flags)
1729 : {
1730 : struct ips_ccb *ccb;
1731 : struct ips_cmd *cmd;
1732 :
1733 0 : ccb = scsi_io_get(&sc->sc_iopool, 0);
1734 0 : if (ccb == NULL)
1735 0 : return (1);
1736 :
1737 0 : ccb->c_flags = SCSI_DATA_IN | SCSI_POLL | flags;
1738 0 : ccb->c_done = ips_done_mgmt;
1739 :
1740 0 : cmd = ccb->c_cmdbva;
1741 0 : cmd->code = IPS_CMD_GETADAPTERINFO;
1742 0 : cmd->sgaddr = htole32(sc->sc_infom.dm_paddr + offsetof(struct ips_info,
1743 : adapter));
1744 :
1745 0 : return (ips_cmd(sc, ccb));
1746 0 : }
1747 :
1748 : int
1749 0 : ips_getdriveinfo(struct ips_softc *sc, int flags)
1750 : {
1751 : struct ips_ccb *ccb;
1752 : struct ips_cmd *cmd;
1753 :
1754 0 : ccb = scsi_io_get(&sc->sc_iopool, 0);
1755 0 : if (ccb == NULL)
1756 0 : return (1);
1757 :
1758 0 : ccb->c_flags = SCSI_DATA_IN | SCSI_POLL | flags;
1759 0 : ccb->c_done = ips_done_mgmt;
1760 :
1761 0 : cmd = ccb->c_cmdbva;
1762 0 : cmd->code = IPS_CMD_GETDRIVEINFO;
1763 0 : cmd->sgaddr = htole32(sc->sc_infom.dm_paddr + offsetof(struct ips_info,
1764 : drive));
1765 :
1766 0 : return (ips_cmd(sc, ccb));
1767 0 : }
1768 :
1769 : int
1770 0 : ips_getconf(struct ips_softc *sc, int flags)
1771 : {
1772 : struct ips_ccb *ccb;
1773 : struct ips_cmd *cmd;
1774 :
1775 0 : ccb = scsi_io_get(&sc->sc_iopool, 0);
1776 0 : if (ccb == NULL)
1777 0 : return (1);
1778 :
1779 0 : ccb->c_flags = SCSI_DATA_IN | SCSI_POLL | flags;
1780 0 : ccb->c_done = ips_done_mgmt;
1781 :
1782 0 : cmd = ccb->c_cmdbva;
1783 0 : cmd->code = IPS_CMD_READCONF;
1784 0 : cmd->sgaddr = htole32(sc->sc_infom.dm_paddr + offsetof(struct ips_info,
1785 : conf));
1786 :
1787 0 : return (ips_cmd(sc, ccb));
1788 0 : }
1789 :
1790 : int
1791 0 : ips_getpg5(struct ips_softc *sc, int flags)
1792 : {
1793 : struct ips_ccb *ccb;
1794 : struct ips_cmd *cmd;
1795 :
1796 0 : ccb = scsi_io_get(&sc->sc_iopool, 0);
1797 0 : if (ccb == NULL)
1798 0 : return (1);
1799 :
1800 0 : ccb->c_flags = SCSI_DATA_IN | SCSI_POLL | flags;
1801 0 : ccb->c_done = ips_done_mgmt;
1802 :
1803 0 : cmd = ccb->c_cmdbva;
1804 0 : cmd->code = IPS_CMD_RWNVRAM;
1805 0 : cmd->drive = 5;
1806 0 : cmd->sgaddr = htole32(sc->sc_infom.dm_paddr + offsetof(struct ips_info,
1807 : pg5));
1808 :
1809 0 : return (ips_cmd(sc, ccb));
1810 0 : }
1811 :
1812 : #if NBIO > 0
1813 : int
1814 0 : ips_getrblstat(struct ips_softc *sc, int flags)
1815 : {
1816 : struct ips_ccb *ccb;
1817 : struct ips_cmd *cmd;
1818 :
1819 0 : ccb = scsi_io_get(&sc->sc_iopool, 0);
1820 0 : if (ccb == NULL)
1821 0 : return (1);
1822 :
1823 0 : ccb->c_flags = SCSI_DATA_IN | SCSI_POLL | flags;
1824 0 : ccb->c_done = ips_done_mgmt;
1825 :
1826 0 : cmd = ccb->c_cmdbva;
1827 0 : cmd->code = IPS_CMD_REBUILDSTATUS;
1828 0 : cmd->sgaddr = htole32(sc->sc_infom.dm_paddr + offsetof(struct ips_info,
1829 : rblstat));
1830 :
1831 0 : return (ips_cmd(sc, ccb));
1832 0 : }
1833 :
1834 : int
1835 0 : ips_setstate(struct ips_softc *sc, int chan, int target, int state, int flags)
1836 : {
1837 : struct ips_ccb *ccb;
1838 : struct ips_cmd *cmd;
1839 :
1840 0 : ccb = scsi_io_get(&sc->sc_iopool, 0);
1841 0 : if (ccb == NULL)
1842 0 : return (1);
1843 :
1844 0 : ccb->c_flags = SCSI_POLL | flags;
1845 0 : ccb->c_done = ips_done_mgmt;
1846 :
1847 0 : cmd = ccb->c_cmdbva;
1848 0 : cmd->code = IPS_CMD_SETSTATE;
1849 0 : cmd->drive = chan;
1850 0 : cmd->sgcnt = target;
1851 0 : cmd->seg4g = state;
1852 :
1853 0 : return (ips_cmd(sc, ccb));
1854 0 : }
1855 :
1856 : int
1857 0 : ips_rebuild(struct ips_softc *sc, int chan, int target, int nchan,
1858 : int ntarget, int flags)
1859 : {
1860 : struct ips_ccb *ccb;
1861 : struct ips_cmd *cmd;
1862 :
1863 0 : ccb = scsi_io_get(&sc->sc_iopool, 0);
1864 0 : if (ccb == NULL)
1865 0 : return (1);
1866 :
1867 0 : ccb->c_flags = SCSI_POLL | flags;
1868 0 : ccb->c_done = ips_done_mgmt;
1869 :
1870 0 : cmd = ccb->c_cmdbva;
1871 0 : cmd->code = IPS_CMD_REBUILD;
1872 0 : cmd->drive = chan;
1873 0 : cmd->sgcnt = target;
1874 0 : cmd->seccnt = htole16(ntarget << 8 | nchan);
1875 :
1876 0 : return (ips_cmd(sc, ccb));
1877 0 : }
1878 : #endif /* NBIO > 0 */
1879 :
1880 : void
1881 0 : ips_copperhead_exec(struct ips_softc *sc, struct ips_ccb *ccb)
1882 : {
1883 : u_int32_t reg;
1884 : int timeout;
1885 :
1886 0 : for (timeout = 100; timeout-- > 0; delay(100)) {
1887 0 : reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IPS_REG_CCC);
1888 0 : if ((reg & IPS_REG_CCC_SEM) == 0)
1889 : break;
1890 : }
1891 0 : if (timeout < 0) {
1892 0 : printf("%s: semaphore timeout\n", sc->sc_dev.dv_xname);
1893 0 : return;
1894 : }
1895 :
1896 0 : bus_space_write_4(sc->sc_iot, sc->sc_ioh, IPS_REG_CCSA, ccb->c_cmdbpa);
1897 0 : bus_space_write_2(sc->sc_iot, sc->sc_ioh, IPS_REG_CCC,
1898 : IPS_REG_CCC_START);
1899 0 : }
1900 :
1901 : void
1902 0 : ips_copperhead_intren(struct ips_softc *sc)
1903 : {
1904 0 : bus_space_write_1(sc->sc_iot, sc->sc_ioh, IPS_REG_HIS, IPS_REG_HIS_EN);
1905 0 : }
1906 :
1907 : int
1908 0 : ips_copperhead_isintr(struct ips_softc *sc)
1909 : {
1910 : u_int8_t reg;
1911 :
1912 0 : reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, IPS_REG_HIS);
1913 0 : bus_space_write_1(sc->sc_iot, sc->sc_ioh, IPS_REG_HIS, reg);
1914 0 : if (reg != 0xff && (reg & IPS_REG_HIS_SCE))
1915 0 : return (1);
1916 :
1917 0 : return (0);
1918 0 : }
1919 :
1920 : u_int32_t
1921 0 : ips_copperhead_status(struct ips_softc *sc)
1922 : {
1923 : u_int32_t sqhead, sqtail, status;
1924 :
1925 0 : sqhead = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IPS_REG_SQH);
1926 : DPRINTF(IPS_D_XFER, ("%s: sqhead 0x%08x, sqtail 0x%08x\n",
1927 : sc->sc_dev.dv_xname, sqhead, sc->sc_sqtail));
1928 :
1929 0 : sqtail = sc->sc_sqtail + sizeof(u_int32_t);
1930 0 : if (sqtail == sc->sc_sqm.dm_paddr + IPS_SQSZ)
1931 0 : sqtail = sc->sc_sqm.dm_paddr;
1932 0 : if (sqtail == sqhead)
1933 0 : return (0xffffffff);
1934 :
1935 0 : sc->sc_sqtail = sqtail;
1936 0 : if (++sc->sc_sqidx == IPS_MAXCMDS)
1937 0 : sc->sc_sqidx = 0;
1938 0 : status = letoh32(sc->sc_sqbuf[sc->sc_sqidx]);
1939 0 : bus_space_write_4(sc->sc_iot, sc->sc_ioh, IPS_REG_SQT, sqtail);
1940 :
1941 0 : return (status);
1942 0 : }
1943 :
1944 : void
1945 0 : ips_morpheus_exec(struct ips_softc *sc, struct ips_ccb *ccb)
1946 : {
1947 0 : bus_space_write_4(sc->sc_iot, sc->sc_ioh, IPS_REG_IQP, ccb->c_cmdbpa);
1948 0 : }
1949 :
1950 : void
1951 0 : ips_morpheus_intren(struct ips_softc *sc)
1952 : {
1953 : u_int32_t reg;
1954 :
1955 0 : reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IPS_REG_OIM);
1956 0 : reg &= ~IPS_REG_OIM_DS;
1957 0 : bus_space_write_4(sc->sc_iot, sc->sc_ioh, IPS_REG_OIM, reg);
1958 0 : }
1959 :
1960 : int
1961 0 : ips_morpheus_isintr(struct ips_softc *sc)
1962 : {
1963 0 : return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, IPS_REG_OIS) &
1964 : IPS_REG_OIS_PEND);
1965 : }
1966 :
1967 : u_int32_t
1968 0 : ips_morpheus_status(struct ips_softc *sc)
1969 : {
1970 : u_int32_t reg;
1971 :
1972 0 : reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IPS_REG_OQP);
1973 : DPRINTF(IPS_D_XFER, ("%s: status 0x%08x\n", sc->sc_dev.dv_xname, reg));
1974 :
1975 0 : return (reg);
1976 : }
1977 :
1978 : struct ips_ccb *
1979 0 : ips_ccb_alloc(struct ips_softc *sc, int n)
1980 : {
1981 : struct ips_ccb *ccb;
1982 : int i;
1983 :
1984 0 : if ((ccb = mallocarray(n, sizeof(*ccb), M_DEVBUF,
1985 0 : M_NOWAIT | M_ZERO)) == NULL)
1986 0 : return (NULL);
1987 :
1988 0 : for (i = 0; i < n; i++) {
1989 0 : ccb[i].c_sc = sc;
1990 0 : ccb[i].c_id = i;
1991 0 : ccb[i].c_cmdbva = (char *)sc->sc_cmdbm.dm_vaddr +
1992 0 : i * sizeof(struct ips_cmdb);
1993 0 : ccb[i].c_cmdbpa = sc->sc_cmdbm.dm_paddr +
1994 : i * sizeof(struct ips_cmdb);
1995 0 : if (bus_dmamap_create(sc->sc_dmat, IPS_MAXFER, IPS_MAXSGS,
1996 : IPS_MAXFER, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1997 : &ccb[i].c_dmam))
1998 : goto fail;
1999 : }
2000 :
2001 0 : return (ccb);
2002 : fail:
2003 0 : for (; i > 0; i--)
2004 0 : bus_dmamap_destroy(sc->sc_dmat, ccb[i - 1].c_dmam);
2005 0 : free(ccb, M_DEVBUF, n * sizeof(*ccb));
2006 0 : return (NULL);
2007 0 : }
2008 :
2009 : void
2010 0 : ips_ccb_free(struct ips_softc *sc, struct ips_ccb *ccb, int n)
2011 : {
2012 : int i;
2013 :
2014 0 : for (i = 0; i < n; i++)
2015 0 : bus_dmamap_destroy(sc->sc_dmat, ccb[i - 1].c_dmam);
2016 0 : free(ccb, M_DEVBUF, n * sizeof(*ccb));
2017 0 : }
2018 :
2019 : void *
2020 0 : ips_ccb_get(void *xsc)
2021 : {
2022 0 : struct ips_softc *sc = xsc;
2023 : struct ips_ccb *ccb;
2024 :
2025 0 : mtx_enter(&sc->sc_ccb_mtx);
2026 0 : if ((ccb = SLIST_FIRST(&sc->sc_ccbq_free)) != NULL) {
2027 0 : SLIST_REMOVE_HEAD(&sc->sc_ccbq_free, c_link);
2028 0 : ccb->c_flags = 0;
2029 0 : ccb->c_xfer = NULL;
2030 0 : bzero(ccb->c_cmdbva, sizeof(struct ips_cmdb));
2031 0 : }
2032 0 : mtx_leave(&sc->sc_ccb_mtx);
2033 :
2034 0 : return (ccb);
2035 : }
2036 :
2037 : void
2038 0 : ips_ccb_put(void *xsc, void *xccb)
2039 : {
2040 0 : struct ips_softc *sc = xsc;
2041 0 : struct ips_ccb *ccb = xccb;
2042 :
2043 0 : ccb->c_state = IPS_CCB_FREE;
2044 0 : mtx_enter(&sc->sc_ccb_mtx);
2045 0 : SLIST_INSERT_HEAD(&sc->sc_ccbq_free, ccb, c_link);
2046 0 : mtx_leave(&sc->sc_ccb_mtx);
2047 0 : }
2048 :
2049 : int
2050 0 : ips_dmamem_alloc(struct dmamem *dm, bus_dma_tag_t tag, bus_size_t size)
2051 : {
2052 0 : int nsegs;
2053 :
2054 0 : dm->dm_tag = tag;
2055 0 : dm->dm_size = size;
2056 :
2057 0 : if (bus_dmamap_create(tag, size, 1, size, 0,
2058 : BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &dm->dm_map))
2059 0 : return (1);
2060 0 : if (bus_dmamem_alloc(tag, size, 0, 0, &dm->dm_seg, 1, &nsegs,
2061 : BUS_DMA_NOWAIT))
2062 : goto fail1;
2063 0 : if (bus_dmamem_map(tag, &dm->dm_seg, 1, size, (caddr_t *)&dm->dm_vaddr,
2064 : BUS_DMA_NOWAIT))
2065 : goto fail2;
2066 0 : if (bus_dmamap_load(tag, dm->dm_map, dm->dm_vaddr, size, NULL,
2067 : BUS_DMA_NOWAIT))
2068 : goto fail3;
2069 :
2070 0 : return (0);
2071 :
2072 : fail3:
2073 0 : bus_dmamem_unmap(tag, dm->dm_vaddr, size);
2074 : fail2:
2075 0 : bus_dmamem_free(tag, &dm->dm_seg, 1);
2076 : fail1:
2077 0 : bus_dmamap_destroy(tag, dm->dm_map);
2078 0 : return (1);
2079 0 : }
2080 :
2081 : void
2082 0 : ips_dmamem_free(struct dmamem *dm)
2083 : {
2084 0 : bus_dmamap_unload(dm->dm_tag, dm->dm_map);
2085 0 : bus_dmamem_unmap(dm->dm_tag, dm->dm_vaddr, dm->dm_size);
2086 0 : bus_dmamem_free(dm->dm_tag, &dm->dm_seg, 1);
2087 0 : bus_dmamap_destroy(dm->dm_tag, dm->dm_map);
2088 0 : }
|