This source file includes following definitions.
- mpi_attach
- mpi_squash_ppr
- mpi_run_ppr
- mpi_ppr
- mpi_inq
- mpi_detach
- mpi_intr
- mpi_reply
- mpi_dmamem_alloc
- mpi_dmamem_free
- mpi_alloc_ccbs
- mpi_get_ccb
- mpi_put_ccb
- mpi_alloc_replies
- mpi_push_replies
- mpi_start
- mpi_complete
- mpi_poll
- mpi_scsi_cmd
- mpi_scsi_cmd_done
- mpi_timeout_xs
- mpi_load_xs
- mpi_minphys
- mpi_scsi_ioctl
- mpi_read
- mpi_write
- mpi_wait_eq
- mpi_wait_ne
- mpi_init
- mpi_reset_soft
- mpi_reset_hard
- mpi_handshake_send
- mpi_handshake_recv_dword
- mpi_handshake_recv
- mpi_empty_done
- mpi_iocfacts
- mpi_iocinit
- mpi_portfacts
- mpi_eventnotify
- mpi_eventnotify_done
- mpi_evt_sas
- mpi_eventack
- mpi_eventack_done
- mpi_portenable
- mpi_fwupload
- mpi_get_raid
- mpi_cfg_header
- mpi_cfg_page
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/buf.h>
23 #include <sys/device.h>
24 #include <sys/proc.h>
25 #include <sys/malloc.h>
26 #include <sys/kernel.h>
27
28 #include <machine/bus.h>
29
30 #include <scsi/scsi_all.h>
31 #include <scsi/scsiconf.h>
32
33 #include <dev/ic/mpireg.h>
34 #include <dev/ic/mpivar.h>
35
36 #ifdef MPI_DEBUG
37 uint32_t mpi_debug = 0
38
39
40
41
42
43
44
45
46
47
48
49 ;
50 #endif
51
52 struct cfdriver mpi_cd = {
53 NULL, "mpi", DV_DULL
54 };
55
56 int mpi_scsi_cmd(struct scsi_xfer *);
57 void mpi_scsi_cmd_done(struct mpi_ccb *);
58 void mpi_minphys(struct buf *bp);
59 int mpi_scsi_ioctl(struct scsi_link *, u_long, caddr_t,
60 int, struct proc *);
61
62 struct scsi_adapter mpi_switch = {
63 mpi_scsi_cmd, mpi_minphys, NULL, NULL, mpi_scsi_ioctl
64 };
65
66 struct scsi_device mpi_dev = {
67 NULL, NULL, NULL, NULL
68 };
69
70 struct mpi_dmamem *mpi_dmamem_alloc(struct mpi_softc *, size_t);
71 void mpi_dmamem_free(struct mpi_softc *,
72 struct mpi_dmamem *);
73 int mpi_alloc_ccbs(struct mpi_softc *);
74 struct mpi_ccb *mpi_get_ccb(struct mpi_softc *);
75 void mpi_put_ccb(struct mpi_softc *, struct mpi_ccb *);
76 int mpi_alloc_replies(struct mpi_softc *);
77 void mpi_push_replies(struct mpi_softc *);
78
79 void mpi_start(struct mpi_softc *, struct mpi_ccb *);
80 int mpi_complete(struct mpi_softc *, struct mpi_ccb *, int);
81 int mpi_poll(struct mpi_softc *, struct mpi_ccb *, int);
82 int mpi_reply(struct mpi_softc *, u_int32_t);
83
84 void mpi_squash_ppr(struct mpi_softc *);
85 void mpi_run_ppr(struct mpi_softc *);
86 int mpi_ppr(struct mpi_softc *, struct scsi_link *,
87 struct mpi_cfg_raid_physdisk *, int, int, int);
88 int mpi_inq(struct mpi_softc *, u_int16_t, int);
89
90 void mpi_timeout_xs(void *);
91 int mpi_load_xs(struct mpi_ccb *);
92
93 u_int32_t mpi_read(struct mpi_softc *, bus_size_t);
94 void mpi_write(struct mpi_softc *, bus_size_t, u_int32_t);
95 int mpi_wait_eq(struct mpi_softc *, bus_size_t, u_int32_t,
96 u_int32_t);
97 int mpi_wait_ne(struct mpi_softc *, bus_size_t, u_int32_t,
98 u_int32_t);
99
100 int mpi_init(struct mpi_softc *);
101 int mpi_reset_soft(struct mpi_softc *);
102 int mpi_reset_hard(struct mpi_softc *);
103
104 int mpi_handshake_send(struct mpi_softc *, void *, size_t);
105 int mpi_handshake_recv_dword(struct mpi_softc *,
106 u_int32_t *);
107 int mpi_handshake_recv(struct mpi_softc *, void *, size_t);
108
109 void mpi_empty_done(struct mpi_ccb *);
110
111 int mpi_iocinit(struct mpi_softc *);
112 int mpi_iocfacts(struct mpi_softc *);
113 int mpi_portfacts(struct mpi_softc *);
114 int mpi_portenable(struct mpi_softc *);
115 void mpi_get_raid(struct mpi_softc *);
116 int mpi_fwupload(struct mpi_softc *);
117
118 int mpi_eventnotify(struct mpi_softc *);
119 void mpi_eventnotify_done(struct mpi_ccb *);
120 void mpi_eventack(struct mpi_softc *,
121 struct mpi_msg_event_reply *);
122 void mpi_eventack_done(struct mpi_ccb *);
123 void mpi_evt_sas(void *, void *);
124
125 int mpi_cfg_header(struct mpi_softc *, u_int8_t, u_int8_t,
126 u_int32_t, struct mpi_cfg_hdr *);
127 int mpi_cfg_page(struct mpi_softc *, u_int32_t,
128 struct mpi_cfg_hdr *, int, void *, size_t);
129
130 #define DEVNAME(s) ((s)->sc_dev.dv_xname)
131
132 #define dwordsof(s) (sizeof(s) / sizeof(u_int32_t))
133 #define sizeofa(s) (sizeof(s) / sizeof((s)[0]))
134
135 #define mpi_read_db(s) mpi_read((s), MPI_DOORBELL)
136 #define mpi_write_db(s, v) mpi_write((s), MPI_DOORBELL, (v))
137 #define mpi_read_intr(s) mpi_read((s), MPI_INTR_STATUS)
138 #define mpi_write_intr(s, v) mpi_write((s), MPI_INTR_STATUS, (v))
139 #define mpi_pop_reply(s) mpi_read((s), MPI_REPLY_QUEUE)
140 #define mpi_push_reply(s, v) mpi_write((s), MPI_REPLY_QUEUE, (v))
141
142 #define mpi_wait_db_int(s) mpi_wait_ne((s), MPI_INTR_STATUS, \
143 MPI_INTR_STATUS_DOORBELL, 0)
144 #define mpi_wait_db_ack(s) mpi_wait_eq((s), MPI_INTR_STATUS, \
145 MPI_INTR_STATUS_IOCDOORBELL, 0)
146
147 int
148 mpi_attach(struct mpi_softc *sc)
149 {
150 struct scsibus_attach_args saa;
151 struct mpi_ccb *ccb;
152
153 printf("\n");
154
155
156 mpi_write(sc, MPI_INTR_MASK,
157 MPI_INTR_MASK_REPLY | MPI_INTR_MASK_DOORBELL);
158
159 if (mpi_init(sc) != 0) {
160 printf("%s: unable to initialise\n", DEVNAME(sc));
161 return (1);
162 }
163
164 if (mpi_iocfacts(sc) != 0) {
165 printf("%s: unable to get iocfacts\n", DEVNAME(sc));
166 return (1);
167 }
168
169 if (mpi_alloc_ccbs(sc) != 0) {
170
171 return (1);
172 }
173
174 if (mpi_alloc_replies(sc) != 0) {
175 printf("%s: unable to allocate reply space\n", DEVNAME(sc));
176 goto free_ccbs;
177 }
178
179 if (mpi_iocinit(sc) != 0) {
180 printf("%s: unable to send iocinit\n", DEVNAME(sc));
181 goto free_ccbs;
182 }
183
184
185 if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
186 MPI_DOORBELL_STATE_OPER) != 0) {
187 printf("%s: state: 0x%08x\n", DEVNAME(sc),
188 mpi_read_db(sc) & MPI_DOORBELL_STATE);
189 printf("%s: operational state timeout\n", DEVNAME(sc));
190 goto free_ccbs;
191 }
192
193 mpi_push_replies(sc);
194
195 if (mpi_portfacts(sc) != 0) {
196 printf("%s: unable to get portfacts\n", DEVNAME(sc));
197 goto free_replies;
198 }
199
200 #ifdef notyet
201 if (mpi_eventnotify(sc) != 0) {
202 printf("%s: unable to get portfacts\n", DEVNAME(sc));
203 goto free_replies;
204 }
205 #endif
206
207 if (mpi_portenable(sc) != 0) {
208 printf("%s: unable to enable port\n", DEVNAME(sc));
209 goto free_replies;
210 }
211
212 if (mpi_fwupload(sc) != 0) {
213 printf("%s: unable to upload firmware\n", DEVNAME(sc));
214 goto free_replies;
215 }
216
217 if (sc->sc_porttype == MPI_PORTFACTS_PORTTYPE_SCSI)
218 mpi_squash_ppr(sc);
219
220
221 sc->sc_link.device = &mpi_dev;
222 sc->sc_link.adapter = &mpi_switch;
223 sc->sc_link.adapter_softc = sc;
224 sc->sc_link.adapter_target = sc->sc_target;
225 sc->sc_link.adapter_buswidth = sc->sc_buswidth;
226 sc->sc_link.openings = sc->sc_maxcmds / sc->sc_buswidth;
227
228 bzero(&saa, sizeof(saa));
229 saa.saa_sc_link = &sc->sc_link;
230
231
232 sc->sc_scsibus = (struct scsibus_softc *) config_found(&sc->sc_dev,
233 &saa, scsiprint);
234
235
236 mpi_get_raid(sc);
237
238
239 if (sc->sc_porttype == MPI_PORTFACTS_PORTTYPE_SCSI)
240 mpi_run_ppr(sc);
241
242
243 mpi_write(sc, MPI_INTR_MASK, MPI_INTR_MASK_DOORBELL);
244
245 return (0);
246
247 free_replies:
248 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies),
249 0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
250 mpi_dmamem_free(sc, sc->sc_replies);
251 free_ccbs:
252 while ((ccb = mpi_get_ccb(sc)) != NULL)
253 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
254 mpi_dmamem_free(sc, sc->sc_requests);
255 free(sc->sc_ccbs, M_DEVBUF);
256
257 return(1);
258 }
259
260 void
261 mpi_squash_ppr(struct mpi_softc *sc)
262 {
263 struct mpi_cfg_hdr hdr;
264 struct mpi_cfg_spi_dev_pg1 page;
265 int i;
266
267 DNPRINTF(MPI_D_PPR, "%s: mpi_squash_ppr\n", DEVNAME(sc));
268
269 for (i = 0; i < sc->sc_buswidth; i++) {
270 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV,
271 1, i, &hdr) != 0)
272 return;
273
274 if (mpi_cfg_page(sc, i, &hdr, 1, &page, sizeof(page)) != 0)
275 return;
276
277 DNPRINTF(MPI_D_PPR, "%s: target: %d req_params1: 0x%02x "
278 "req_offset: 0x%02x req_period: 0x%02x "
279 "req_params2: 0x%02x conf: 0x%08x\n", DEVNAME(sc), i,
280 page.req_params1, page.req_offset, page.req_period,
281 page.req_params2, letoh32(page.configuration));
282
283 page.req_params1 = 0x0;
284 page.req_offset = 0x0;
285 page.req_period = 0x0;
286 page.req_params2 = 0x0;
287 page.configuration = htole32(0x0);
288
289 if (mpi_cfg_page(sc, i, &hdr, 0, &page, sizeof(page)) != 0)
290 return;
291 }
292 }
293
294 void
295 mpi_run_ppr(struct mpi_softc *sc)
296 {
297 struct mpi_cfg_hdr hdr;
298 struct mpi_cfg_spi_port_pg0 port_pg;
299 struct mpi_cfg_ioc_pg3 *physdisk_pg;
300 struct mpi_cfg_raid_physdisk *physdisk_list, *physdisk;
301 size_t pagelen;
302 struct scsi_link *link;
303 int i, tries;
304
305 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_PORT, 0, 0x0,
306 &hdr) != 0) {
307 DNPRINTF(MPI_D_PPR, "%s: mpi_run_ppr unable to fetch header\n",
308 DEVNAME(sc));
309 return;
310 }
311
312 if (mpi_cfg_page(sc, 0x0, &hdr, 1, &port_pg, sizeof(port_pg)) != 0) {
313 DNPRINTF(MPI_D_PPR, "%s: mpi_run_ppr unable to fetch page\n",
314 DEVNAME(sc));
315 return;
316 }
317
318 for (i = 0; i < sc->sc_buswidth; i++) {
319 link = sc->sc_scsibus->sc_link[i][0];
320 if (link == NULL)
321 continue;
322
323
324 if (link->flags & SDEV_VIRTUAL)
325 continue;
326
327 tries = 0;
328 while (mpi_ppr(sc, link, NULL, port_pg.min_period,
329 port_pg.max_offset, tries) == EAGAIN)
330 tries++;
331 }
332
333 if ((sc->sc_flags & MPI_F_RAID) == 0)
334 return;
335
336 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_IOC, 3, 0x0,
337 &hdr) != 0) {
338 DNPRINTF(MPI_D_RAID|MPI_D_PPR, "%s: mpi_run_ppr unable to "
339 "fetch ioc pg 3 header\n", DEVNAME(sc));
340 return;
341 }
342
343 pagelen = hdr.page_length * 4;
344 physdisk_pg = malloc(pagelen, M_TEMP, M_WAITOK|M_CANFAIL);
345 if (physdisk_pg == NULL) {
346 DNPRINTF(MPI_D_RAID|MPI_D_PPR, "%s: mpi_run_ppr unable to "
347 "allocate ioc pg 3\n", DEVNAME(sc));
348 return;
349 }
350 physdisk_list = (struct mpi_cfg_raid_physdisk *)(physdisk_pg + 1);
351
352 if (mpi_cfg_page(sc, 0, &hdr, 1, physdisk_pg, pagelen) != 0) {
353 DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s: mpi_run_ppr unable to "
354 "fetch ioc page 3\n", DEVNAME(sc));
355 goto out;
356 }
357
358 DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s: no_phys_disks: %d\n", DEVNAME(sc),
359 physdisk_pg->no_phys_disks);
360
361 for (i = 0; i < physdisk_pg->no_phys_disks; i++) {
362 physdisk = &physdisk_list[i];
363
364 DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s: id: %d bus: %d ioc: %d "
365 "num: %d\n", DEVNAME(sc), physdisk->phys_disk_id,
366 physdisk->phys_disk_bus, physdisk->phys_disk_ioc,
367 physdisk->phys_disk_num);
368
369 if (physdisk->phys_disk_ioc != sc->sc_ioc_number)
370 continue;
371
372 tries = 0;
373 while (mpi_ppr(sc, NULL, physdisk, port_pg.min_period,
374 port_pg.max_offset, tries) == EAGAIN)
375 tries++;
376 }
377
378 out:
379 free(physdisk_pg, M_TEMP);
380 }
381
382 int
383 mpi_ppr(struct mpi_softc *sc, struct scsi_link *link,
384 struct mpi_cfg_raid_physdisk *physdisk, int period, int offset, int try)
385 {
386 struct mpi_cfg_hdr hdr0, hdr1;
387 struct mpi_cfg_spi_dev_pg0 pg0;
388 struct mpi_cfg_spi_dev_pg1 pg1;
389 u_int32_t address;
390 int id;
391 int raid = 0;
392
393 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr period: %d offset: %d try: %d "
394 "link quirks: 0x%x\n", DEVNAME(sc), period, offset, try,
395 link->quirks);
396
397 if (try >= 3)
398 return (EIO);
399
400 if (physdisk == NULL) {
401 if ((link->inqdata.device & SID_TYPE) == T_PROCESSOR)
402 return (EIO);
403
404 address = link->target;
405 id = link->target;
406 } else {
407 raid = 1;
408 address = (physdisk->phys_disk_bus << 8) |
409 (physdisk->phys_disk_id);
410 id = physdisk->phys_disk_num;
411 }
412
413 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV, 0,
414 address, &hdr0) != 0) {
415 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch header 0\n",
416 DEVNAME(sc));
417 return (EIO);
418 }
419
420 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV, 1,
421 address, &hdr1) != 0) {
422 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch header 1\n",
423 DEVNAME(sc));
424 return (EIO);
425 }
426
427 #ifdef MPI_DEBUG
428 if (mpi_cfg_page(sc, address, &hdr0, 1, &pg0, sizeof(pg0)) != 0) {
429 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch page 0\n",
430 DEVNAME(sc));
431 return (EIO);
432 }
433
434 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 0 neg_params1: 0x%02x "
435 "neg_offset: %d neg_period: 0x%02x neg_params2: 0x%02x "
436 "info: 0x%08x\n", DEVNAME(sc), pg0.neg_params1, pg0.neg_offset,
437 pg0.neg_period, pg0.neg_params2, letoh32(pg0.information));
438 #endif
439
440 if (mpi_cfg_page(sc, address, &hdr1, 1, &pg1, sizeof(pg1)) != 0) {
441 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch page 1\n",
442 DEVNAME(sc));
443 return (EIO);
444 }
445
446 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x "
447 "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x "
448 "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset,
449 pg1.req_period, pg1.req_params2, letoh32(pg1.configuration));
450
451 pg1.req_params1 = 0;
452 pg1.req_offset = offset;
453 pg1.req_period = period;
454 pg1.req_params2 &= ~MPI_CFG_SPI_DEV_1_REQPARAMS_WIDTH;
455
456 if (raid || !(link->quirks & SDEV_NOSYNC)) {
457 pg1.req_params2 |= MPI_CFG_SPI_DEV_1_REQPARAMS_WIDTH_WIDE;
458
459 switch (try) {
460 case 0:
461 break;
462 case 1:
463 pg1.req_period = 0x09;
464 break;
465 case 2:
466 pg1.req_period = 0x0a;
467 break;
468 }
469
470 if (pg1.req_period < 0x09) {
471
472 pg1.req_params1 |= MPI_CFG_SPI_DEV_1_REQPARAMS_QAS |
473 MPI_CFG_SPI_DEV_1_REQPARAMS_PACKETIZED;
474 }
475 if (pg1.req_period < 0xa) {
476
477 pg1.req_params1 |=
478 MPI_CFG_SPI_DEV_1_REQPARAMS_DUALXFERS;
479 }
480 }
481
482 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x "
483 "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x "
484 "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset,
485 pg1.req_period, pg1.req_params2, letoh32(pg1.configuration));
486
487 if (mpi_cfg_page(sc, address, &hdr1, 0, &pg1, sizeof(pg1)) != 0) {
488 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to write page 1\n",
489 DEVNAME(sc));
490 return (EIO);
491 }
492
493 if (mpi_cfg_page(sc, address, &hdr1, 1, &pg1, sizeof(pg1)) != 0) {
494 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to read page 1\n",
495 DEVNAME(sc));
496 return (EIO);
497 }
498
499 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x "
500 "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x "
501 "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset,
502 pg1.req_period, pg1.req_params2, letoh32(pg1.configuration));
503
504 if (mpi_inq(sc, id, raid) != 0) {
505 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to do inquiry against "
506 "target %d\n", DEVNAME(sc), link->target);
507 return (EIO);
508 }
509
510 if (mpi_cfg_page(sc, address, &hdr0, 1, &pg0, sizeof(pg0)) != 0) {
511 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to read page 0 after "
512 "inquiry\n", DEVNAME(sc));
513 return (EIO);
514 }
515
516 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 0 neg_params1: 0x%02x "
517 "neg_offset: %d neg_period: 0x%02x neg_params2: 0x%02x "
518 "info: 0x%08x\n", DEVNAME(sc), pg0.neg_params1, pg0.neg_offset,
519 pg0.neg_period, pg0.neg_params2, letoh32(pg0.information));
520
521 if (!(letoh32(pg0.information) & 0x07) && (try == 0)) {
522 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr U320 ppr rejected\n",
523 DEVNAME(sc));
524 return (EAGAIN);
525 }
526
527 if ((((letoh32(pg0.information) >> 8) & 0xff) > 0x09) && (try == 1)) {
528 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr U160 ppr rejected\n",
529 DEVNAME(sc));
530 return (EAGAIN);
531 }
532
533 if (letoh32(pg0.information) & 0x0e) {
534 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr ppr rejected: %0x\n",
535 DEVNAME(sc), letoh32(pg0.information));
536 return (EAGAIN);
537 }
538
539 switch(pg0.neg_period) {
540 case 0x08:
541 period = 160;
542 break;
543 case 0x09:
544 period = 80;
545 break;
546 case 0x0a:
547 period = 40;
548 break;
549 case 0x0b:
550 period = 20;
551 break;
552 case 0x0c:
553 period = 10;
554 break;
555 default:
556 period = 0;
557 break;
558 }
559
560 printf("%s: %s %d %s at %dMHz width %dbit offset %d "
561 "QAS %d DT %d IU %d\n", DEVNAME(sc), raid ? "phys disk" : "target",
562 id, period ? "Sync" : "Async", period,
563 (pg0.neg_params2 & MPI_CFG_SPI_DEV_0_NEGPARAMS_WIDTH_WIDE) ? 16 : 8,
564 pg0.neg_offset,
565 (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_QAS) ? 1 : 0,
566 (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_DUALXFERS) ? 1 : 0,
567 (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_PACKETIZED) ? 1 : 0);
568
569 return (0);
570 }
571
572 int
573 mpi_inq(struct mpi_softc *sc, u_int16_t target, int physdisk)
574 {
575 struct mpi_ccb *ccb;
576 struct scsi_inquiry inq;
577 struct {
578 struct mpi_msg_scsi_io io;
579 struct mpi_sge sge;
580 struct scsi_inquiry_data inqbuf;
581 struct scsi_sense_data sense;
582 } __packed *bundle;
583 struct mpi_msg_scsi_io *io;
584 struct mpi_sge *sge;
585 u_int64_t addr;
586
587 DNPRINTF(MPI_D_PPR, "%s: mpi_inq\n", DEVNAME(sc));
588
589 bzero(&inq, sizeof(inq));
590 inq.opcode = INQUIRY;
591 _lto2b(sizeof(struct scsi_inquiry_data), inq.length);
592
593 ccb = mpi_get_ccb(sc);
594 if (ccb == NULL)
595 return (1);
596
597 ccb->ccb_done = mpi_empty_done;
598
599 bundle = ccb->ccb_cmd;
600 io = &bundle->io;
601 sge = &bundle->sge;
602
603 io->function = physdisk ? MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH :
604 MPI_FUNCTION_SCSI_IO_REQUEST;
605
606
607
608
609 io->target_id = target;
610
611 io->cdb_length = sizeof(inq);
612 io->sense_buf_len = sizeof(struct scsi_sense_data);
613 io->msg_flags = MPI_SCSIIO_SENSE_BUF_ADDR_WIDTH_64;
614
615 io->msg_context = htole32(ccb->ccb_id);
616
617
618
619
620
621
622 io->direction = MPI_SCSIIO_DIR_READ;
623 io->tagging = MPI_SCSIIO_ATTR_NO_DISCONNECT;
624
625 bcopy(&inq, io->cdb, sizeof(inq));
626
627 io->data_length = htole32(sizeof(struct scsi_inquiry_data));
628
629 io->sense_buf_low_addr = htole32(ccb->ccb_cmd_dva +
630 ((u_int8_t *)&bundle->sense - (u_int8_t *)bundle));
631
632 sge->sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_SIZE_64 |
633 MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL |
634 (u_int32_t)sizeof(inq));
635
636 addr = ccb->ccb_cmd_dva +
637 ((u_int8_t *)&bundle->inqbuf - (u_int8_t *)bundle);
638 sge->sg_hi_addr = htole32((u_int32_t)(addr >> 32));
639 sge->sg_lo_addr = htole32((u_int32_t)addr);
640
641 if (mpi_poll(sc, ccb, 5000) != 0)
642 return (1);
643
644 if (ccb->ccb_rcb != NULL)
645 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
646
647 mpi_put_ccb(sc, ccb);
648
649 return (0);
650 }
651
652 void
653 mpi_detach(struct mpi_softc *sc)
654 {
655
656 }
657
658 int
659 mpi_intr(void *arg)
660 {
661 struct mpi_softc *sc = arg;
662 u_int32_t reg;
663 int rv = 0;
664
665 while ((reg = mpi_pop_reply(sc)) != 0xffffffff) {
666 mpi_reply(sc, reg);
667 rv = 1;
668 }
669
670 return (rv);
671 }
672
673 int
674 mpi_reply(struct mpi_softc *sc, u_int32_t reg)
675 {
676 struct mpi_ccb *ccb;
677 struct mpi_rcb *rcb = NULL;
678 struct mpi_msg_reply *reply = NULL;
679 u_int32_t reply_dva;
680 int id;
681 int i;
682
683 DNPRINTF(MPI_D_INTR, "%s: mpi_reply reg: 0x%08x\n", DEVNAME(sc), reg);
684
685 if (reg & MPI_REPLY_QUEUE_ADDRESS) {
686 bus_dmamap_sync(sc->sc_dmat,
687 MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE,
688 BUS_DMASYNC_POSTREAD);
689
690 reply_dva = (reg & MPI_REPLY_QUEUE_ADDRESS_MASK) << 1;
691
692 i = (reply_dva - (u_int32_t)MPI_DMA_DVA(sc->sc_replies)) /
693 MPI_REPLY_SIZE;
694 rcb = &sc->sc_rcbs[i];
695 reply = rcb->rcb_reply;
696
697 id = letoh32(reply->msg_context);
698
699 bus_dmamap_sync(sc->sc_dmat,
700 MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE,
701 BUS_DMASYNC_PREREAD);
702 } else {
703 switch (reg & MPI_REPLY_QUEUE_TYPE_MASK) {
704 case MPI_REPLY_QUEUE_TYPE_INIT:
705 id = reg & MPI_REPLY_QUEUE_CONTEXT;
706 break;
707
708 default:
709 panic("%s: unsupported context reply\n",
710 DEVNAME(sc));
711 }
712 }
713
714 DNPRINTF(MPI_D_INTR, "%s: mpi_reply id: %d reply: %p\n",
715 DEVNAME(sc), id, reply);
716
717 ccb = &sc->sc_ccbs[id];
718
719 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests),
720 ccb->ccb_offset, MPI_REQUEST_SIZE,
721 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
722 ccb->ccb_state = MPI_CCB_READY;
723 ccb->ccb_rcb = rcb;
724
725 ccb->ccb_done(ccb);
726
727 return (id);
728 }
729
730 struct mpi_dmamem *
731 mpi_dmamem_alloc(struct mpi_softc *sc, size_t size)
732 {
733 struct mpi_dmamem *mdm;
734 int nsegs;
735
736 mdm = malloc(sizeof(struct mpi_dmamem), M_DEVBUF, M_NOWAIT);
737 if (mdm == NULL)
738 return (NULL);
739
740 bzero(mdm, sizeof(struct mpi_dmamem));
741 mdm->mdm_size = size;
742
743 if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
744 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0)
745 goto mdmfree;
746
747 if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mdm->mdm_seg,
748 1, &nsegs, BUS_DMA_NOWAIT) != 0)
749 goto destroy;
750
751 if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size,
752 &mdm->mdm_kva, BUS_DMA_NOWAIT) != 0)
753 goto free;
754
755 if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size,
756 NULL, BUS_DMA_NOWAIT) != 0)
757 goto unmap;
758
759 bzero(mdm->mdm_kva, size);
760
761 DNPRINTF(MPI_D_MEM, "%s: mpi_dmamem_alloc size: %d mdm: %#x "
762 "map: %#x nsegs: %d segs: %#x kva: %x\n",
763 DEVNAME(sc), size, mdm->mdm_map, nsegs, mdm->mdm_seg, mdm->mdm_kva);
764
765 return (mdm);
766
767 unmap:
768 bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size);
769 free:
770 bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
771 destroy:
772 bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
773 mdmfree:
774 free(mdm, M_DEVBUF);
775
776 return (NULL);
777 }
778
779 void
780 mpi_dmamem_free(struct mpi_softc *sc, struct mpi_dmamem *mdm)
781 {
782 DNPRINTF(MPI_D_MEM, "%s: mpi_dmamem_free %#x\n", DEVNAME(sc), mdm);
783
784 bus_dmamap_unload(sc->sc_dmat, mdm->mdm_map);
785 bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size);
786 bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
787 bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
788 free(mdm, M_DEVBUF);
789 }
790
791 int
792 mpi_alloc_ccbs(struct mpi_softc *sc)
793 {
794 struct mpi_ccb *ccb;
795 u_int8_t *cmd;
796 int i;
797
798 TAILQ_INIT(&sc->sc_ccb_free);
799
800 sc->sc_ccbs = malloc(sizeof(struct mpi_ccb) * sc->sc_maxcmds,
801 M_DEVBUF, M_WAITOK|M_CANFAIL);
802 if (sc->sc_ccbs == NULL) {
803 printf("%s: unable to allocate ccbs\n", DEVNAME(sc));
804 return (1);
805 }
806 bzero(sc->sc_ccbs, sizeof(struct mpi_ccb) * sc->sc_maxcmds);
807
808 sc->sc_requests = mpi_dmamem_alloc(sc,
809 MPI_REQUEST_SIZE * sc->sc_maxcmds);
810 if (sc->sc_requests == NULL) {
811 printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
812 goto free_ccbs;
813 }
814 cmd = MPI_DMA_KVA(sc->sc_requests);
815 bzero(cmd, MPI_REQUEST_SIZE * sc->sc_maxcmds);
816
817 for (i = 0; i < sc->sc_maxcmds; i++) {
818 ccb = &sc->sc_ccbs[i];
819
820 if (bus_dmamap_create(sc->sc_dmat, MAXPHYS,
821 sc->sc_max_sgl_len, MAXPHYS, 0, 0,
822 &ccb->ccb_dmamap) != 0) {
823 printf("%s: unable to create dma map\n", DEVNAME(sc));
824 goto free_maps;
825 }
826
827 ccb->ccb_sc = sc;
828 ccb->ccb_id = i;
829 ccb->ccb_offset = MPI_REQUEST_SIZE * i;
830
831 ccb->ccb_cmd = &cmd[ccb->ccb_offset];
832 ccb->ccb_cmd_dva = (u_int32_t)MPI_DMA_DVA(sc->sc_requests) +
833 ccb->ccb_offset;
834
835 DNPRINTF(MPI_D_CCB, "%s: mpi_alloc_ccbs(%d) ccb: %#x map: %#x "
836 "sc: %#x id: %#x offs: %#x cmd: %#x dva: %#x\n",
837 DEVNAME(sc), i, ccb, ccb->ccb_dmamap, ccb->ccb_sc,
838 ccb->ccb_id, ccb->ccb_offset, ccb->ccb_cmd,
839 ccb->ccb_cmd_dva);
840
841 mpi_put_ccb(sc, ccb);
842 }
843
844 return (0);
845
846 free_maps:
847 while ((ccb = mpi_get_ccb(sc)) != NULL)
848 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
849
850 mpi_dmamem_free(sc, sc->sc_requests);
851 free_ccbs:
852 free(sc->sc_ccbs, M_DEVBUF);
853
854 return (1);
855 }
856
857 struct mpi_ccb *
858 mpi_get_ccb(struct mpi_softc *sc)
859 {
860 struct mpi_ccb *ccb;
861
862 ccb = TAILQ_FIRST(&sc->sc_ccb_free);
863 if (ccb == NULL) {
864 DNPRINTF(MPI_D_CCB, "%s: mpi_get_ccb == NULL\n", DEVNAME(sc));
865 return (NULL);
866 }
867
868 TAILQ_REMOVE(&sc->sc_ccb_free, ccb, ccb_link);
869
870 ccb->ccb_state = MPI_CCB_READY;
871
872 DNPRINTF(MPI_D_CCB, "%s: mpi_get_ccb %#x\n", DEVNAME(sc), ccb);
873
874 return (ccb);
875 }
876
877 void
878 mpi_put_ccb(struct mpi_softc *sc, struct mpi_ccb *ccb)
879 {
880 DNPRINTF(MPI_D_CCB, "%s: mpi_put_ccb %#x\n", DEVNAME(sc), ccb);
881
882 ccb->ccb_state = MPI_CCB_FREE;
883 ccb->ccb_xs = NULL;
884 ccb->ccb_done = NULL;
885 bzero(ccb->ccb_cmd, MPI_REQUEST_SIZE);
886 TAILQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_link);
887 }
888
889 int
890 mpi_alloc_replies(struct mpi_softc *sc)
891 {
892 DNPRINTF(MPI_D_MISC, "%s: mpi_alloc_replies\n", DEVNAME(sc));
893
894 sc->sc_rcbs = malloc(MPI_REPLY_COUNT * sizeof(struct mpi_rcb),
895 M_DEVBUF, M_WAITOK|M_CANFAIL);
896 if (sc->sc_rcbs == NULL)
897 return (1);
898
899 sc->sc_replies = mpi_dmamem_alloc(sc, PAGE_SIZE);
900 if (sc->sc_replies == NULL) {
901 free(sc->sc_rcbs, M_DEVBUF);
902 return (1);
903 }
904
905 return (0);
906 }
907
908 void
909 mpi_push_replies(struct mpi_softc *sc)
910 {
911 struct mpi_rcb *rcb;
912 char *kva = MPI_DMA_KVA(sc->sc_replies);
913 int i;
914
915 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies),
916 0, PAGE_SIZE, BUS_DMASYNC_PREREAD);
917
918 for (i = 0; i < MPI_REPLY_COUNT; i++) {
919 rcb = &sc->sc_rcbs[i];
920
921 rcb->rcb_reply = kva + MPI_REPLY_SIZE * i;
922 rcb->rcb_reply_dva = (u_int32_t)MPI_DMA_DVA(sc->sc_replies) +
923 MPI_REPLY_SIZE * i;
924 mpi_push_reply(sc, rcb->rcb_reply_dva);
925 }
926 }
927
928 void
929 mpi_start(struct mpi_softc *sc, struct mpi_ccb *ccb)
930 {
931 DNPRINTF(MPI_D_RW, "%s: mpi_start %#x\n", DEVNAME(sc),
932 ccb->ccb_cmd_dva);
933
934 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests),
935 ccb->ccb_offset, MPI_REQUEST_SIZE,
936 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
937
938 ccb->ccb_state = MPI_CCB_QUEUED;
939 mpi_write(sc, MPI_REQ_QUEUE, ccb->ccb_cmd_dva);
940 }
941
942 int
943 mpi_complete(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout)
944 {
945 u_int32_t reg;
946 int id = -1;
947
948 DNPRINTF(MPI_D_INTR, "%s: mpi_complete timeout %d\n", DEVNAME(sc),
949 timeout);
950
951 do {
952 reg = mpi_pop_reply(sc);
953 if (reg == 0xffffffff) {
954 if (timeout-- == 0)
955 return (1);
956
957 delay(1000);
958 continue;
959 }
960
961 id = mpi_reply(sc, reg);
962
963 } while (ccb->ccb_id != id);
964
965 return (0);
966 }
967
968 int
969 mpi_poll(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout)
970 {
971 int error;
972 int s;
973
974 DNPRINTF(MPI_D_CMD, "%s: mpi_poll\n", DEVNAME(sc));
975
976 s = splbio();
977 mpi_start(sc, ccb);
978 error = mpi_complete(sc, ccb, timeout);
979 splx(s);
980
981 return (error);
982 }
983
984 int
985 mpi_scsi_cmd(struct scsi_xfer *xs)
986 {
987 struct scsi_link *link = xs->sc_link;
988 struct mpi_softc *sc = link->adapter_softc;
989 struct mpi_ccb *ccb;
990 struct mpi_ccb_bundle *mcb;
991 struct mpi_msg_scsi_io *io;
992 int s;
993
994 DNPRINTF(MPI_D_CMD, "%s: mpi_scsi_cmd\n", DEVNAME(sc));
995
996 if (xs->cmdlen > MPI_CDB_LEN) {
997 DNPRINTF(MPI_D_CMD, "%s: CBD too big %d\n",
998 DEVNAME(sc), xs->cmdlen);
999 bzero(&xs->sense, sizeof(xs->sense));
1000 xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
1001 xs->sense.flags = SKEY_ILLEGAL_REQUEST;
1002 xs->sense.add_sense_code = 0x20;
1003 xs->error = XS_SENSE;
1004 s = splbio();
1005 scsi_done(xs);
1006 splx(s);
1007 return (COMPLETE);
1008 }
1009
1010 s = splbio();
1011 ccb = mpi_get_ccb(sc);
1012 splx(s);
1013 if (ccb == NULL) {
1014 xs->error = XS_DRIVER_STUFFUP;
1015 s = splbio();
1016 scsi_done(xs);
1017 splx(s);
1018 return (COMPLETE);
1019 }
1020 DNPRINTF(MPI_D_CMD, "%s: ccb_id: %d xs->flags: 0x%x\n",
1021 DEVNAME(sc), ccb->ccb_id, xs->flags);
1022
1023 ccb->ccb_xs = xs;
1024 ccb->ccb_done = mpi_scsi_cmd_done;
1025
1026 mcb = ccb->ccb_cmd;
1027 io = &mcb->mcb_io;
1028
1029 io->function = MPI_FUNCTION_SCSI_IO_REQUEST;
1030
1031
1032
1033
1034 io->target_id = link->target;
1035
1036 io->cdb_length = xs->cmdlen;
1037 io->sense_buf_len = sizeof(xs->sense);
1038 io->msg_flags = MPI_SCSIIO_SENSE_BUF_ADDR_WIDTH_64;
1039
1040 io->msg_context = htole32(ccb->ccb_id);
1041
1042 io->lun[0] = htobe16(link->lun);
1043
1044 switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1045 case SCSI_DATA_IN:
1046 io->direction = MPI_SCSIIO_DIR_READ;
1047 break;
1048 case SCSI_DATA_OUT:
1049 io->direction = MPI_SCSIIO_DIR_WRITE;
1050 break;
1051 default:
1052 io->direction = MPI_SCSIIO_DIR_NONE;
1053 break;
1054 }
1055
1056 if (link->quirks & SDEV_NOTAGS)
1057 io->tagging = MPI_SCSIIO_ATTR_UNTAGGED;
1058 else
1059 io->tagging = MPI_SCSIIO_ATTR_SIMPLE_Q;
1060
1061 bcopy(xs->cmd, io->cdb, xs->cmdlen);
1062
1063 io->data_length = htole32(xs->datalen);
1064
1065 io->sense_buf_low_addr = htole32(ccb->ccb_cmd_dva +
1066 ((u_int8_t *)&mcb->mcb_sense - (u_int8_t *)mcb));
1067
1068 if (mpi_load_xs(ccb) != 0) {
1069 xs->error = XS_DRIVER_STUFFUP;
1070 s = splbio();
1071 mpi_put_ccb(sc, ccb);
1072 scsi_done(xs);
1073 splx(s);
1074 return (COMPLETE);
1075 }
1076
1077 timeout_set(&xs->stimeout, mpi_timeout_xs, ccb);
1078
1079 if (xs->flags & SCSI_POLL) {
1080 if (mpi_poll(sc, ccb, xs->timeout) != 0)
1081 xs->error = XS_DRIVER_STUFFUP;
1082 return (COMPLETE);
1083 }
1084
1085 s = splbio();
1086 mpi_start(sc, ccb);
1087 splx(s);
1088 return (SUCCESSFULLY_QUEUED);
1089 }
1090
1091 void
1092 mpi_scsi_cmd_done(struct mpi_ccb *ccb)
1093 {
1094 struct mpi_softc *sc = ccb->ccb_sc;
1095 struct scsi_xfer *xs = ccb->ccb_xs;
1096 struct mpi_ccb_bundle *mcb = ccb->ccb_cmd;
1097 bus_dmamap_t dmap = ccb->ccb_dmamap;
1098 struct mpi_msg_scsi_io_error *sie;
1099
1100 if (xs->datalen != 0) {
1101 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
1102 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
1103 BUS_DMASYNC_POSTWRITE);
1104
1105 bus_dmamap_unload(sc->sc_dmat, dmap);
1106 }
1107
1108
1109 xs->error = XS_NOERROR;
1110 xs->resid = 0;
1111 xs->flags |= ITSDONE;
1112
1113 if (ccb->ccb_rcb == NULL) {
1114
1115 xs->status = SCSI_OK;
1116 mpi_put_ccb(sc, ccb);
1117 scsi_done(xs);
1118 return;
1119 }
1120
1121 sie = ccb->ccb_rcb->rcb_reply;
1122
1123 DNPRINTF(MPI_D_CMD, "%s: mpi_scsi_cmd_done xs cmd: 0x%02x len: %d "
1124 "flags 0x%x\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen,
1125 xs->flags);
1126 DNPRINTF(MPI_D_CMD, "%s: target_id: %d bus: %d msg_length: %d "
1127 "function: 0x%02x\n", DEVNAME(sc), sie->target_id, sie->bus,
1128 sie->msg_length, sie->function);
1129 DNPRINTF(MPI_D_CMD, "%s: cdb_length: %d sense_buf_length: %d "
1130 "msg_flags: 0x%02x\n", DEVNAME(sc), sie->cdb_length,
1131 sie->sense_buf_len, sie->msg_flags);
1132 DNPRINTF(MPI_D_CMD, "%s: msg_context: 0x%08x\n", DEVNAME(sc),
1133 letoh32(sie->msg_context));
1134 DNPRINTF(MPI_D_CMD, "%s: scsi_status: 0x%02x scsi_state: 0x%02x "
1135 "ioc_status: 0x%04x\n", DEVNAME(sc), sie->scsi_status,
1136 sie->scsi_state, letoh16(sie->ioc_status));
1137 DNPRINTF(MPI_D_CMD, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1138 letoh32(sie->ioc_loginfo));
1139 DNPRINTF(MPI_D_CMD, "%s: transfer_count: %d\n", DEVNAME(sc),
1140 letoh32(sie->transfer_count));
1141 DNPRINTF(MPI_D_CMD, "%s: sense_count: %d\n", DEVNAME(sc),
1142 letoh32(sie->sense_count));
1143 DNPRINTF(MPI_D_CMD, "%s: response_info: 0x%08x\n", DEVNAME(sc),
1144 letoh32(sie->response_info));
1145 DNPRINTF(MPI_D_CMD, "%s: tag: 0x%04x\n", DEVNAME(sc),
1146 letoh16(sie->tag));
1147
1148 xs->status = sie->scsi_status;
1149 switch (letoh16(sie->ioc_status)) {
1150 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
1151 xs->resid = xs->datalen - letoh32(sie->transfer_count);
1152 if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_NO_SCSI_STATUS) {
1153 xs->error = XS_DRIVER_STUFFUP;
1154 break;
1155 }
1156
1157 case MPI_IOCSTATUS_SUCCESS:
1158 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:
1159 switch (xs->status) {
1160 case SCSI_OK:
1161 xs->resid = 0;
1162 break;
1163
1164 case SCSI_CHECK:
1165 xs->error = XS_SENSE;
1166 break;
1167
1168 case SCSI_BUSY:
1169 case SCSI_QUEUE_FULL:
1170 xs->error = XS_BUSY;
1171 break;
1172
1173 default:
1174 xs->error = XS_DRIVER_STUFFUP;
1175 break;
1176 }
1177 break;
1178
1179 case MPI_IOCSTATUS_BUSY:
1180 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
1181 xs->error = XS_BUSY;
1182 break;
1183
1184 case MPI_IOCSTATUS_SCSI_INVALID_BUS:
1185 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
1186 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
1187 xs->error = XS_SELTIMEOUT;
1188 break;
1189
1190 default:
1191 xs->error = XS_DRIVER_STUFFUP;
1192 break;
1193 }
1194
1195 if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_AUTOSENSE_VALID)
1196 bcopy(&mcb->mcb_sense, &xs->sense, sizeof(xs->sense));
1197
1198 DNPRINTF(MPI_D_CMD, "%s: xs err: 0x%02x status: %d\n", DEVNAME(sc),
1199 xs->error, xs->status);
1200
1201 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
1202 mpi_put_ccb(sc, ccb);
1203 scsi_done(xs);
1204 }
1205
1206 void
1207 mpi_timeout_xs(void *arg)
1208 {
1209
1210 }
1211
1212 int
1213 mpi_load_xs(struct mpi_ccb *ccb)
1214 {
1215 struct mpi_softc *sc = ccb->ccb_sc;
1216 struct scsi_xfer *xs = ccb->ccb_xs;
1217 struct mpi_ccb_bundle *mcb = ccb->ccb_cmd;
1218 struct mpi_msg_scsi_io *io = &mcb->mcb_io;
1219 struct mpi_sge *sge, *nsge = &mcb->mcb_sgl[0];
1220 struct mpi_sge *ce = NULL, *nce;
1221 u_int64_t ce_dva;
1222 bus_dmamap_t dmap = ccb->ccb_dmamap;
1223 u_int32_t addr, flags;
1224 int i, error;
1225
1226 if (xs->datalen == 0) {
1227 nsge->sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
1228 MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL);
1229 return (0);
1230 }
1231
1232 error = bus_dmamap_load(sc->sc_dmat, dmap,
1233 xs->data, xs->datalen, NULL,
1234 (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
1235 if (error) {
1236 printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
1237 return (1);
1238 }
1239
1240 flags = MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_SIZE_64;
1241 if (xs->flags & SCSI_DATA_OUT)
1242 flags |= MPI_SGE_FL_DIR_OUT;
1243
1244 if (dmap->dm_nsegs > sc->sc_first_sgl_len) {
1245 ce = &mcb->mcb_sgl[sc->sc_first_sgl_len - 1];
1246 io->chain_offset = ((u_int8_t *)ce - (u_int8_t *)io) / 4;
1247 }
1248
1249 for (i = 0; i < dmap->dm_nsegs; i++) {
1250
1251 if (nsge == ce) {
1252 nsge++;
1253 sge->sg_hdr |= htole32(MPI_SGE_FL_LAST);
1254
1255 DNPRINTF(MPI_D_DMA, "%s: - 0x%08x 0x%08x 0x%08x\n",
1256 DEVNAME(sc), sge->sg_hdr,
1257 sge->sg_hi_addr, sge->sg_lo_addr);
1258
1259 if ((dmap->dm_nsegs - i) > sc->sc_chain_len) {
1260 nce = &nsge[sc->sc_chain_len - 1];
1261 addr = ((u_int8_t *)nce - (u_int8_t *)nsge) / 4;
1262 addr = addr << 16 |
1263 sizeof(struct mpi_sge) * sc->sc_chain_len;
1264 } else {
1265 nce = NULL;
1266 addr = sizeof(struct mpi_sge) *
1267 (dmap->dm_nsegs - i);
1268 }
1269
1270 ce->sg_hdr = htole32(MPI_SGE_FL_TYPE_CHAIN |
1271 MPI_SGE_FL_SIZE_64 | addr);
1272
1273 ce_dva = ccb->ccb_cmd_dva +
1274 ((u_int8_t *)nsge - (u_int8_t *)mcb);
1275
1276 addr = (u_int32_t)(ce_dva >> 32);
1277 ce->sg_hi_addr = htole32(addr);
1278 addr = (u_int32_t)ce_dva;
1279 ce->sg_lo_addr = htole32(addr);
1280
1281 DNPRINTF(MPI_D_DMA, "%s: ce: 0x%08x 0x%08x 0x%08x\n",
1282 DEVNAME(sc), ce->sg_hdr, ce->sg_hi_addr,
1283 ce->sg_lo_addr);
1284
1285 ce = nce;
1286 }
1287
1288 DNPRINTF(MPI_D_DMA, "%s: %d: %d 0x%016llx\n", DEVNAME(sc),
1289 i, dmap->dm_segs[i].ds_len,
1290 (u_int64_t)dmap->dm_segs[i].ds_addr);
1291
1292 sge = nsge;
1293
1294 sge->sg_hdr = htole32(flags | dmap->dm_segs[i].ds_len);
1295 addr = (u_int32_t)((u_int64_t)dmap->dm_segs[i].ds_addr >> 32);
1296 sge->sg_hi_addr = htole32(addr);
1297 addr = (u_int32_t)dmap->dm_segs[i].ds_addr;
1298 sge->sg_lo_addr = htole32(addr);
1299
1300 DNPRINTF(MPI_D_DMA, "%s: %d: 0x%08x 0x%08x 0x%08x\n",
1301 DEVNAME(sc), i, sge->sg_hdr, sge->sg_hi_addr,
1302 sge->sg_lo_addr);
1303
1304 nsge = sge + 1;
1305 }
1306
1307
1308 sge->sg_hdr |= htole32(MPI_SGE_FL_LAST | MPI_SGE_FL_EOB |
1309 MPI_SGE_FL_EOL);
1310
1311 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
1312 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1313 BUS_DMASYNC_PREWRITE);
1314
1315 return (0);
1316 }
1317
1318 void
1319 mpi_minphys(struct buf *bp)
1320 {
1321
1322 if (bp->b_bcount > MAXPHYS)
1323 bp->b_bcount = MAXPHYS;
1324 minphys(bp);
1325 }
1326
1327 int
1328 mpi_scsi_ioctl(struct scsi_link *a, u_long b, caddr_t c, int d, struct proc *e)
1329 {
1330 return (ENOTTY);
1331 }
1332
1333 u_int32_t
1334 mpi_read(struct mpi_softc *sc, bus_size_t r)
1335 {
1336 u_int32_t rv;
1337
1338 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1339 BUS_SPACE_BARRIER_READ);
1340 rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
1341
1342 DNPRINTF(MPI_D_RW, "%s: mpi_read %#x %#x\n", DEVNAME(sc), r, rv);
1343
1344 return (rv);
1345 }
1346
1347 void
1348 mpi_write(struct mpi_softc *sc, bus_size_t r, u_int32_t v)
1349 {
1350 DNPRINTF(MPI_D_RW, "%s: mpi_write %#x %#x\n", DEVNAME(sc), r, v);
1351
1352 bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
1353 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1354 BUS_SPACE_BARRIER_WRITE);
1355 }
1356
1357 int
1358 mpi_wait_eq(struct mpi_softc *sc, bus_size_t r, u_int32_t mask,
1359 u_int32_t target)
1360 {
1361 int i;
1362
1363 DNPRINTF(MPI_D_RW, "%s: mpi_wait_eq %#x %#x %#x\n", DEVNAME(sc), r,
1364 mask, target);
1365
1366 for (i = 0; i < 10000; i++) {
1367 if ((mpi_read(sc, r) & mask) == target)
1368 return (0);
1369 delay(1000);
1370 }
1371
1372 return (1);
1373 }
1374
1375 int
1376 mpi_wait_ne(struct mpi_softc *sc, bus_size_t r, u_int32_t mask,
1377 u_int32_t target)
1378 {
1379 int i;
1380
1381 DNPRINTF(MPI_D_RW, "%s: mpi_wait_ne %#x %#x %#x\n", DEVNAME(sc), r,
1382 mask, target);
1383
1384 for (i = 0; i < 10000; i++) {
1385 if ((mpi_read(sc, r) & mask) != target)
1386 return (0);
1387 delay(1000);
1388 }
1389
1390 return (1);
1391 }
1392
1393 int
1394 mpi_init(struct mpi_softc *sc)
1395 {
1396 u_int32_t db;
1397 int i;
1398
1399
1400 if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
1401 MPI_DOORBELL_STATE_RESET) != 0) {
1402 DNPRINTF(MPI_D_MISC, "%s: mpi_init timeout waiting to leave "
1403 "reset state\n", DEVNAME(sc));
1404 return (1);
1405 }
1406
1407
1408 db = mpi_read_db(sc);
1409 if ((db & MPI_DOORBELL_WHOINIT) == MPI_DOORBELL_WHOINIT_PCIPEER) {
1410 DNPRINTF(MPI_D_MISC, "%s: mpi_init initialised by pci peer\n",
1411 DEVNAME(sc));
1412 return (0);
1413 }
1414
1415 for (i = 0; i < 5; i++) {
1416 switch (db & MPI_DOORBELL_STATE) {
1417 case MPI_DOORBELL_STATE_READY:
1418 DNPRINTF(MPI_D_MISC, "%s: mpi_init ioc is ready\n",
1419 DEVNAME(sc));
1420 return (0);
1421
1422 case MPI_DOORBELL_STATE_OPER:
1423 case MPI_DOORBELL_STATE_FAULT:
1424 DNPRINTF(MPI_D_MISC, "%s: mpi_init ioc is being "
1425 "reset\n" , DEVNAME(sc));
1426 if (mpi_reset_soft(sc) != 0)
1427 mpi_reset_hard(sc);
1428 break;
1429
1430 case MPI_DOORBELL_STATE_RESET:
1431 DNPRINTF(MPI_D_MISC, "%s: mpi_init waiting to come "
1432 "out of reset\n", DEVNAME(sc));
1433 if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
1434 MPI_DOORBELL_STATE_RESET) != 0)
1435 return (1);
1436 break;
1437 }
1438 db = mpi_read_db(sc);
1439 }
1440
1441 return (1);
1442 }
1443
1444 int
1445 mpi_reset_soft(struct mpi_softc *sc)
1446 {
1447 DNPRINTF(MPI_D_MISC, "%s: mpi_reset_soft\n", DEVNAME(sc));
1448
1449 if (mpi_read_db(sc) & MPI_DOORBELL_INUSE)
1450 return (1);
1451
1452 mpi_write_db(sc,
1453 MPI_DOORBELL_FUNCTION(MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET));
1454 if (mpi_wait_eq(sc, MPI_INTR_STATUS,
1455 MPI_INTR_STATUS_IOCDOORBELL, 0) != 0)
1456 return (1);
1457
1458 if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
1459 MPI_DOORBELL_STATE_READY) != 0)
1460 return (1);
1461
1462 return (0);
1463 }
1464
1465 int
1466 mpi_reset_hard(struct mpi_softc *sc)
1467 {
1468 DNPRINTF(MPI_D_MISC, "%s: mpi_reset_hard\n", DEVNAME(sc));
1469
1470
1471 mpi_write(sc, MPI_WRITESEQ, 0xff);
1472 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_1);
1473 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_2);
1474 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_3);
1475 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_4);
1476 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_5);
1477
1478
1479 mpi_write(sc, MPI_HOSTDIAG, MPI_HOSTDIAG_RESET_ADAPTER);
1480
1481 delay(10000);
1482
1483
1484 mpi_write(sc, MPI_WRITESEQ, 0xff);
1485
1486
1487
1488
1489 return (0);
1490 }
1491
1492 int
1493 mpi_handshake_send(struct mpi_softc *sc, void *buf, size_t dwords)
1494 {
1495 u_int32_t *query = buf;
1496 int i;
1497
1498
1499 if (mpi_read_db(sc) & MPI_DOORBELL_INUSE)
1500 return (1);
1501
1502
1503 if (mpi_read_intr(sc) & MPI_INTR_STATUS_DOORBELL)
1504 mpi_write_intr(sc, 0);
1505
1506
1507
1508
1509
1510 mpi_write_db(sc, MPI_DOORBELL_FUNCTION(MPI_FUNCTION_HANDSHAKE) |
1511 MPI_DOORBELL_DWORDS(dwords));
1512
1513
1514
1515
1516
1517 if (mpi_wait_db_int(sc) != 0)
1518 return (1);
1519 mpi_write_intr(sc, 0);
1520
1521
1522 if (mpi_wait_db_ack(sc) != 0)
1523 return (1);
1524
1525
1526 for (i = 0; i < dwords; i++) {
1527 mpi_write_db(sc, htole32(query[i]));
1528 if (mpi_wait_db_ack(sc) != 0)
1529 return (1);
1530 }
1531
1532 return (0);
1533 }
1534
1535 int
1536 mpi_handshake_recv_dword(struct mpi_softc *sc, u_int32_t *dword)
1537 {
1538 u_int16_t *words = (u_int16_t *)dword;
1539 int i;
1540
1541 for (i = 0; i < 2; i++) {
1542 if (mpi_wait_db_int(sc) != 0)
1543 return (1);
1544 words[i] = letoh16(mpi_read_db(sc) & MPI_DOORBELL_DATA_MASK);
1545 mpi_write_intr(sc, 0);
1546 }
1547
1548 return (0);
1549 }
1550
1551 int
1552 mpi_handshake_recv(struct mpi_softc *sc, void *buf, size_t dwords)
1553 {
1554 struct mpi_msg_reply *reply = buf;
1555 u_int32_t *dbuf = buf, dummy;
1556 int i;
1557
1558
1559 if (mpi_handshake_recv_dword(sc, &dbuf[0]) != 0)
1560 return (1);
1561
1562 DNPRINTF(MPI_D_CMD, "%s: mpi_handshake_recv dwords: %d reply: %d\n",
1563 DEVNAME(sc), dwords, reply->msg_length);
1564
1565
1566
1567
1568
1569 for (i = 1; i < MIN(dwords, reply->msg_length); i++) {
1570 if (mpi_handshake_recv_dword(sc, &dbuf[i]) != 0)
1571 return (1);
1572 }
1573
1574
1575 while (i++ < reply->msg_length) {
1576 if (mpi_handshake_recv_dword(sc, &dummy) != 0)
1577 return (1);
1578 DNPRINTF(MPI_D_CMD, "%s: mpi_handshake_recv dummy read: "
1579 "0x%08x\n", DEVNAME(sc), dummy);
1580 }
1581
1582
1583 if (mpi_wait_db_int(sc) != 0)
1584 return (1);
1585 mpi_write_intr(sc, 0);
1586
1587 return (0);
1588 }
1589
1590 void
1591 mpi_empty_done(struct mpi_ccb *ccb)
1592 {
1593
1594 }
1595
1596 int
1597 mpi_iocfacts(struct mpi_softc *sc)
1598 {
1599 struct mpi_msg_iocfacts_request ifq;
1600 struct mpi_msg_iocfacts_reply ifp;
1601
1602 DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts\n", DEVNAME(sc));
1603
1604 bzero(&ifq, sizeof(ifq));
1605 bzero(&ifp, sizeof(ifp));
1606
1607 ifq.function = MPI_FUNCTION_IOC_FACTS;
1608 ifq.chain_offset = 0;
1609 ifq.msg_flags = 0;
1610 ifq.msg_context = htole32(0xdeadbeef);
1611
1612 if (mpi_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) {
1613 DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts send failed\n",
1614 DEVNAME(sc));
1615 return (1);
1616 }
1617
1618 if (mpi_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) {
1619 DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts recv failed\n",
1620 DEVNAME(sc));
1621 return (1);
1622 }
1623
1624 DNPRINTF(MPI_D_MISC, "%s: func: 0x%02x len: %d msgver: %d.%d\n",
1625 DEVNAME(sc), ifp.function, ifp.msg_length,
1626 ifp.msg_version_maj, ifp.msg_version_min);
1627 DNPRINTF(MPI_D_MISC, "%s: msgflags: 0x%02x iocnumber: 0x%02x "
1628 "hdrver: %d.%d\n", DEVNAME(sc), ifp.msg_flags,
1629 ifp.ioc_number, ifp.header_version_maj,
1630 ifp.header_version_min);
1631 DNPRINTF(MPI_D_MISC, "%s: message context: 0x%08x\n", DEVNAME(sc),
1632 letoh32(ifp.msg_context));
1633 DNPRINTF(MPI_D_MISC, "%s: iocstatus: 0x%04x ioexcept: 0x%04x\n",
1634 DEVNAME(sc), letoh16(ifp.ioc_status),
1635 letoh16(ifp.ioc_exceptions));
1636 DNPRINTF(MPI_D_MISC, "%s: iocloginfo: 0x%08x\n", DEVNAME(sc),
1637 letoh32(ifp.ioc_loginfo));
1638 DNPRINTF(MPI_D_MISC, "%s: flags: 0x%02x blocksize: %d whoinit: 0x%02x "
1639 "maxchdepth: %d\n", DEVNAME(sc), ifp.flags,
1640 ifp.block_size, ifp.whoinit, ifp.max_chain_depth);
1641 DNPRINTF(MPI_D_MISC, "%s: reqfrsize: %d replyqdepth: %d\n",
1642 DEVNAME(sc), letoh16(ifp.request_frame_size),
1643 letoh16(ifp.reply_queue_depth));
1644 DNPRINTF(MPI_D_MISC, "%s: productid: 0x%04x\n", DEVNAME(sc),
1645 letoh16(ifp.product_id));
1646 DNPRINTF(MPI_D_MISC, "%s: hostmfahiaddr: 0x%08x\n", DEVNAME(sc),
1647 letoh32(ifp.current_host_mfa_hi_addr));
1648 DNPRINTF(MPI_D_MISC, "%s: event_state: 0x%02x number_of_ports: %d "
1649 "global_credits: %d\n",
1650 DEVNAME(sc), ifp.event_state, ifp.number_of_ports,
1651 letoh16(ifp.global_credits));
1652 DNPRINTF(MPI_D_MISC, "%s: sensebufhiaddr: 0x%08x\n", DEVNAME(sc),
1653 letoh32(ifp.current_sense_buffer_hi_addr));
1654 DNPRINTF(MPI_D_MISC, "%s: maxbus: %d maxdev: %d replyfrsize: %d\n",
1655 DEVNAME(sc), ifp.max_buses, ifp.max_devices,
1656 letoh16(ifp.current_reply_frame_size));
1657 DNPRINTF(MPI_D_MISC, "%s: fw_image_size: %d\n", DEVNAME(sc),
1658 letoh32(ifp.fw_image_size));
1659 DNPRINTF(MPI_D_MISC, "%s: ioc_capabilities: 0x%08x\n", DEVNAME(sc),
1660 letoh32(ifp.ioc_capabilities));
1661 DNPRINTF(MPI_D_MISC, "%s: fw_version: %d.%d fw_version_unit: 0x%02x "
1662 "fw_version_dev: 0x%02x\n", DEVNAME(sc),
1663 ifp.fw_version_maj, ifp.fw_version_min,
1664 ifp.fw_version_unit, ifp.fw_version_dev);
1665 DNPRINTF(MPI_D_MISC, "%s: hi_priority_queue_depth: 0x%04x\n",
1666 DEVNAME(sc), letoh16(ifp.hi_priority_queue_depth));
1667 DNPRINTF(MPI_D_MISC, "%s: host_page_buffer_sge: hdr: 0x%08x "
1668 "addr 0x%08x %08x\n", DEVNAME(sc),
1669 letoh32(ifp.host_page_buffer_sge.sg_hdr),
1670 letoh32(ifp.host_page_buffer_sge.sg_hi_addr),
1671 letoh32(ifp.host_page_buffer_sge.sg_lo_addr));
1672
1673 sc->sc_maxcmds = letoh16(ifp.global_credits);
1674 sc->sc_maxchdepth = ifp.max_chain_depth;
1675 sc->sc_ioc_number = ifp.ioc_number;
1676 if (sc->sc_flags & MPI_F_SPI)
1677 sc->sc_buswidth = 16;
1678 else
1679 sc->sc_buswidth =
1680 (ifp.max_devices == 0) ? 256 : ifp.max_devices;
1681 if (ifp.flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
1682 sc->sc_fw_len = letoh32(ifp.fw_image_size);
1683
1684
1685
1686
1687
1688 sc->sc_first_sgl_len = ((letoh16(ifp.request_frame_size) * 4) -
1689 sizeof(struct mpi_msg_scsi_io)) / sizeof(struct mpi_sge);
1690 DNPRINTF(MPI_D_MISC, "%s: first sgl len: %d\n", DEVNAME(sc),
1691 sc->sc_first_sgl_len);
1692
1693 sc->sc_chain_len = (letoh16(ifp.request_frame_size) * 4) /
1694 sizeof(struct mpi_sge);
1695 DNPRINTF(MPI_D_MISC, "%s: chain len: %d\n", DEVNAME(sc),
1696 sc->sc_chain_len);
1697
1698
1699 sc->sc_max_sgl_len = MPI_MAX_SGL - 1;
1700
1701 sc->sc_max_sgl_len -= (MPI_MAX_SGL - sc->sc_first_sgl_len) /
1702 sc->sc_chain_len;
1703 DNPRINTF(MPI_D_MISC, "%s: max sgl len: %d\n", DEVNAME(sc),
1704 sc->sc_max_sgl_len);
1705
1706
1707
1708 return (0);
1709 }
1710
1711 int
1712 mpi_iocinit(struct mpi_softc *sc)
1713 {
1714 struct mpi_msg_iocinit_request iiq;
1715 struct mpi_msg_iocinit_reply iip;
1716 u_int32_t hi_addr;
1717
1718 DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit\n", DEVNAME(sc));
1719
1720 bzero(&iiq, sizeof(iiq));
1721 bzero(&iip, sizeof(iip));
1722
1723 iiq.function = MPI_FUNCTION_IOC_INIT;
1724 iiq.whoinit = MPI_WHOINIT_HOST_DRIVER;
1725
1726 iiq.max_devices = (sc->sc_buswidth == 256) ? 0 : sc->sc_buswidth;
1727 iiq.max_buses = 1;
1728
1729 iiq.msg_context = htole32(0xd00fd00f);
1730
1731 iiq.reply_frame_size = htole16(MPI_REPLY_SIZE);
1732
1733 hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_requests) >> 32);
1734 iiq.host_mfa_hi_addr = htole32(hi_addr);
1735 iiq.sense_buffer_hi_addr = htole32(hi_addr);
1736
1737 hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_replies) >> 32);
1738 iiq.reply_fifo_host_signalling_addr = htole32(hi_addr);
1739
1740 iiq.msg_version_maj = 0x01;
1741 iiq.msg_version_min = 0x02;
1742
1743 iiq.hdr_version_unit = 0x0d;
1744 iiq.hdr_version_dev = 0x00;
1745
1746 if (mpi_handshake_send(sc, &iiq, dwordsof(iiq)) != 0) {
1747 DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit send failed\n",
1748 DEVNAME(sc));
1749 return (1);
1750 }
1751
1752 if (mpi_handshake_recv(sc, &iip, dwordsof(iip)) != 0) {
1753 DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit recv failed\n",
1754 DEVNAME(sc));
1755 return (1);
1756 }
1757
1758 DNPRINTF(MPI_D_MISC, "%s: function: 0x%02x msg_length: %d "
1759 "whoinit: 0x%02x\n", DEVNAME(sc), iip.function,
1760 iip.msg_length, iip.whoinit);
1761 DNPRINTF(MPI_D_MISC, "%s: msg_flags: 0x%02x max_buses: %d "
1762 "max_devices: %d flags: 0x%02x\n", DEVNAME(sc), iip.msg_flags,
1763 iip.max_buses, iip.max_devices, iip.flags);
1764 DNPRINTF(MPI_D_MISC, "%s: msg_context: 0x%08x\n", DEVNAME(sc),
1765 letoh32(iip.msg_context));
1766 DNPRINTF(MPI_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc),
1767 letoh16(iip.ioc_status));
1768 DNPRINTF(MPI_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1769 letoh32(iip.ioc_loginfo));
1770
1771 return (0);
1772 }
1773
1774 int
1775 mpi_portfacts(struct mpi_softc *sc)
1776 {
1777 struct mpi_ccb *ccb;
1778 struct mpi_msg_portfacts_request *pfq;
1779 volatile struct mpi_msg_portfacts_reply *pfp;
1780 int s, rv = 1;
1781
1782 DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts\n", DEVNAME(sc));
1783
1784 s = splbio();
1785 ccb = mpi_get_ccb(sc);
1786 splx(s);
1787 if (ccb == NULL) {
1788 DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts ccb_get\n",
1789 DEVNAME(sc));
1790 return (rv);
1791 }
1792
1793 ccb->ccb_done = mpi_empty_done;
1794 pfq = ccb->ccb_cmd;
1795
1796 pfq->function = MPI_FUNCTION_PORT_FACTS;
1797 pfq->chain_offset = 0;
1798 pfq->msg_flags = 0;
1799 pfq->port_number = 0;
1800 pfq->msg_context = htole32(ccb->ccb_id);
1801
1802 if (mpi_poll(sc, ccb, 50000) != 0) {
1803 DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts poll\n", DEVNAME(sc));
1804 goto err;
1805 }
1806
1807 if (ccb->ccb_rcb == NULL) {
1808 DNPRINTF(MPI_D_MISC, "%s: empty portfacts reply\n",
1809 DEVNAME(sc));
1810 goto err;
1811 }
1812 pfp = ccb->ccb_rcb->rcb_reply;
1813
1814 DNPRINTF(MPI_D_MISC, "%s: function: 0x%02x msg_length: %d\n",
1815 DEVNAME(sc), pfp->function, pfp->msg_length);
1816 DNPRINTF(MPI_D_MISC, "%s: msg_flags: 0x%02x port_number: %d\n",
1817 DEVNAME(sc), pfp->msg_flags, pfp->port_number);
1818 DNPRINTF(MPI_D_MISC, "%s: msg_context: 0x%08x\n", DEVNAME(sc),
1819 letoh32(pfp->msg_context));
1820 DNPRINTF(MPI_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc),
1821 letoh16(pfp->ioc_status));
1822 DNPRINTF(MPI_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1823 letoh32(pfp->ioc_loginfo));
1824 DNPRINTF(MPI_D_MISC, "%s: max_devices: %d port_type: 0x%02x\n",
1825 DEVNAME(sc), letoh16(pfp->max_devices), pfp->port_type);
1826 DNPRINTF(MPI_D_MISC, "%s: protocol_flags: 0x%04x port_scsi_id: %d\n",
1827 DEVNAME(sc), letoh16(pfp->protocol_flags),
1828 letoh16(pfp->port_scsi_id));
1829 DNPRINTF(MPI_D_MISC, "%s: max_persistent_ids: %d "
1830 "max_posted_cmd_buffers: %d\n", DEVNAME(sc),
1831 letoh16(pfp->max_persistent_ids),
1832 letoh16(pfp->max_posted_cmd_buffers));
1833 DNPRINTF(MPI_D_MISC, "%s: max_lan_buckets: %d\n", DEVNAME(sc),
1834 letoh16(pfp->max_lan_buckets));
1835
1836 sc->sc_porttype = pfp->port_type;
1837 sc->sc_target = letoh16(pfp->port_scsi_id);
1838
1839 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
1840 rv = 0;
1841 err:
1842 mpi_put_ccb(sc, ccb);
1843
1844 return (rv);
1845 }
1846
1847 int
1848 mpi_eventnotify(struct mpi_softc *sc)
1849 {
1850 struct mpi_ccb *ccb;
1851 struct mpi_msg_event_request *enq;
1852 int s;
1853
1854 s = splbio();
1855 ccb = mpi_get_ccb(sc);
1856 splx(s);
1857 if (ccb == NULL) {
1858 DNPRINTF(MPI_D_MISC, "%s: mpi_eventnotify ccb_get\n",
1859 DEVNAME(sc));
1860 return (1);
1861 }
1862
1863 ccb->ccb_done = mpi_eventnotify_done;
1864 enq = ccb->ccb_cmd;
1865
1866 enq->function = MPI_FUNCTION_EVENT_NOTIFICATION;
1867 enq->chain_offset = 0;
1868 enq->event_switch = MPI_EVENT_SWITCH_ON;
1869 enq->msg_context = htole32(ccb->ccb_id);
1870
1871 mpi_start(sc, ccb);
1872 return (0);
1873 }
1874
1875 void
1876 mpi_eventnotify_done(struct mpi_ccb *ccb)
1877 {
1878 struct mpi_softc *sc = ccb->ccb_sc;
1879 struct mpi_msg_event_reply *enp = ccb->ccb_rcb->rcb_reply;
1880 int deferred = 0;
1881
1882 DNPRINTF(MPI_D_EVT, "%s: mpi_eventnotify_done\n", DEVNAME(sc));
1883
1884 DNPRINTF(MPI_D_EVT, "%s: function: 0x%02x msg_length: %d "
1885 "data_length: %d\n", DEVNAME(sc), enp->function, enp->msg_length,
1886 letoh16(enp->data_length));
1887 DNPRINTF(MPI_D_EVT, "%s: ack_required: %d msg_flags 0x%02x\n",
1888 DEVNAME(sc), enp->ack_required, enp->msg_flags);
1889 DNPRINTF(MPI_D_EVT, "%s: msg_context: 0x%08x\n", DEVNAME(sc),
1890 letoh32(enp->msg_context));
1891 DNPRINTF(MPI_D_EVT, "%s: ioc_status: 0x%04x\n", DEVNAME(sc),
1892 letoh16(enp->ioc_status));
1893 DNPRINTF(MPI_D_EVT, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1894 letoh32(enp->ioc_loginfo));
1895 DNPRINTF(MPI_D_EVT, "%s: event: 0x%08x\n", DEVNAME(sc),
1896 letoh32(enp->event));
1897 DNPRINTF(MPI_D_EVT, "%s: event_context: 0x%08x\n", DEVNAME(sc),
1898 letoh32(enp->event_context));
1899
1900 switch (letoh32(enp->event)) {
1901
1902 case MPI_EVENT_EVENT_CHANGE:
1903 case MPI_EVENT_SAS_PHY_LINK_STATUS:
1904 break;
1905
1906 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1907 if (sc->sc_scsibus == NULL)
1908 break;
1909
1910 if (scsi_task(mpi_evt_sas, sc, ccb->ccb_rcb, 0) != 0) {
1911 printf("%s: unable to run SAS device status change\n",
1912 DEVNAME(sc));
1913 break;
1914 }
1915 deferred = 1;
1916 break;
1917
1918 default:
1919 printf("%s: unhandled event 0x%02x\n", DEVNAME(sc),
1920 letoh32(enp->event));
1921 break;
1922 }
1923
1924 if (!deferred) {
1925 if (enp->ack_required)
1926 mpi_eventack(sc, enp);
1927 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
1928 }
1929
1930 if ((enp->msg_flags & MPI_EVENT_FLAGS_REPLY_KEPT) == 0) {
1931
1932 mpi_put_ccb(sc, ccb);
1933 }
1934 }
1935
1936 void
1937 mpi_evt_sas(void *xsc, void *arg)
1938 {
1939 struct mpi_softc *sc = xsc;
1940 struct mpi_rcb *rcb = arg;
1941 struct mpi_msg_event_reply *enp = rcb->rcb_reply;
1942 struct mpi_evt_sas_change *ch;
1943 u_int8_t *data;
1944 int s;
1945
1946 data = rcb->rcb_reply;
1947 data += sizeof(struct mpi_msg_event_reply);
1948 ch = (struct mpi_evt_sas_change *)data;
1949
1950 if (ch->bus != 0)
1951 return;
1952
1953 switch (ch->reason) {
1954 case MPI_EVT_SASCH_REASON_ADDED:
1955 case MPI_EVT_SASCH_REASON_NO_PERSIST_ADDED:
1956 scsi_probe_target(sc->sc_scsibus, ch->target);
1957 break;
1958
1959 case MPI_EVT_SASCH_REASON_NOT_RESPONDING:
1960 scsi_detach_target(sc->sc_scsibus, ch->target, DETACH_FORCE);
1961 break;
1962
1963 case MPI_EVT_SASCH_REASON_SMART_DATA:
1964 case MPI_EVT_SASCH_REASON_UNSUPPORTED:
1965 case MPI_EVT_SASCH_REASON_INTERNAL_RESET:
1966 break;
1967 default:
1968 printf("%s: unknown reason for SAS device status change: "
1969 "0x%02x\n", DEVNAME(sc), ch->reason);
1970 break;
1971 }
1972
1973 s = splbio();
1974 mpi_push_reply(sc, rcb->rcb_reply_dva);
1975 if (enp->ack_required)
1976 mpi_eventack(sc, enp);
1977 splx(s);
1978 }
1979
1980 void
1981 mpi_eventack(struct mpi_softc *sc, struct mpi_msg_event_reply *enp)
1982 {
1983 struct mpi_ccb *ccb;
1984 struct mpi_msg_eventack_request *eaq;
1985
1986 ccb = mpi_get_ccb(sc);
1987 if (ccb == NULL) {
1988 DNPRINTF(MPI_D_EVT, "%s: mpi_eventack ccb_get\n", DEVNAME(sc));
1989 return;
1990 }
1991
1992 ccb->ccb_done = mpi_eventack_done;
1993 eaq = ccb->ccb_cmd;
1994
1995 eaq->function = MPI_FUNCTION_EVENT_ACK;
1996 eaq->msg_context = htole32(ccb->ccb_id);
1997
1998 eaq->event = enp->event;
1999 eaq->event_context = enp->event_context;
2000
2001 mpi_start(sc, ccb);
2002 return;
2003 }
2004
2005 void
2006 mpi_eventack_done(struct mpi_ccb *ccb)
2007 {
2008 struct mpi_softc *sc = ccb->ccb_sc;
2009
2010 DNPRINTF(MPI_D_EVT, "%s: event ack done\n", DEVNAME(sc));
2011
2012 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
2013 mpi_put_ccb(sc, ccb);
2014 }
2015
2016 int
2017 mpi_portenable(struct mpi_softc *sc)
2018 {
2019 struct mpi_ccb *ccb;
2020 struct mpi_msg_portenable_request *peq;
2021 struct mpi_msg_portenable_repy *pep;
2022 int s;
2023
2024 DNPRINTF(MPI_D_MISC, "%s: mpi_portenable\n", DEVNAME(sc));
2025
2026 s = splbio();
2027 ccb = mpi_get_ccb(sc);
2028 splx(s);
2029 if (ccb == NULL) {
2030 DNPRINTF(MPI_D_MISC, "%s: mpi_portenable ccb_get\n",
2031 DEVNAME(sc));
2032 return (1);
2033 }
2034
2035 ccb->ccb_done = mpi_empty_done;
2036 peq = ccb->ccb_cmd;
2037
2038 peq->function = MPI_FUNCTION_PORT_ENABLE;
2039 peq->port_number = 0;
2040 peq->msg_context = htole32(ccb->ccb_id);
2041
2042 if (mpi_poll(sc, ccb, 50000) != 0) {
2043 DNPRINTF(MPI_D_MISC, "%s: mpi_portenable poll\n", DEVNAME(sc));
2044 return (1);
2045 }
2046
2047 if (ccb->ccb_rcb == NULL) {
2048 DNPRINTF(MPI_D_MISC, "%s: empty portenable reply\n",
2049 DEVNAME(sc));
2050 return (1);
2051 }
2052 pep = ccb->ccb_rcb->rcb_reply;
2053
2054 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
2055 mpi_put_ccb(sc, ccb);
2056
2057 return (0);
2058 }
2059
2060 int
2061 mpi_fwupload(struct mpi_softc *sc)
2062 {
2063 struct mpi_ccb *ccb;
2064 struct {
2065 struct mpi_msg_fwupload_request req;
2066 struct mpi_sge sge;
2067 } __packed *bundle;
2068 struct mpi_msg_fwupload_reply *upp;
2069 u_int64_t addr;
2070 int s;
2071 int rv = 0;
2072
2073 if (sc->sc_fw_len == 0)
2074 return (0);
2075
2076 DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload\n", DEVNAME(sc));
2077
2078 sc->sc_fw = mpi_dmamem_alloc(sc, sc->sc_fw_len);
2079 if (sc->sc_fw == NULL) {
2080 DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload unable to allocate %d\n",
2081 DEVNAME(sc), sc->sc_fw_len);
2082 return (1);
2083 }
2084
2085 s = splbio();
2086 ccb = mpi_get_ccb(sc);
2087 splx(s);
2088 if (ccb == NULL) {
2089 DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload ccb_get\n",
2090 DEVNAME(sc));
2091 goto err;
2092 }
2093
2094 ccb->ccb_done = mpi_empty_done;
2095 bundle = ccb->ccb_cmd;
2096
2097 bundle->req.function = MPI_FUNCTION_FW_UPLOAD;
2098 bundle->req.msg_context = htole32(ccb->ccb_id);
2099
2100 bundle->req.image_type = MPI_FWUPLOAD_IMAGETYPE_IOC_FW;
2101
2102 bundle->req.tce.details_length = 12;
2103 bundle->req.tce.image_size = htole32(sc->sc_fw_len);
2104
2105 bundle->sge.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
2106 MPI_SGE_FL_SIZE_64 | MPI_SGE_FL_LAST | MPI_SGE_FL_EOB |
2107 MPI_SGE_FL_EOL | (u_int32_t)sc->sc_fw_len);
2108 addr = MPI_DMA_DVA(sc->sc_fw);
2109 bundle->sge.sg_hi_addr = htole32((u_int32_t)(addr >> 32));
2110 bundle->sge.sg_lo_addr = htole32((u_int32_t)addr);
2111
2112 if (mpi_poll(sc, ccb, 50000) != 0) {
2113 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header poll\n", DEVNAME(sc));
2114 goto err;
2115 }
2116
2117 if (ccb->ccb_rcb == NULL)
2118 panic("%s: unable to do fw upload\n", DEVNAME(sc));
2119 upp = ccb->ccb_rcb->rcb_reply;
2120
2121 if (letoh16(upp->ioc_status) != MPI_IOCSTATUS_SUCCESS)
2122 rv = 1;
2123
2124 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
2125 mpi_put_ccb(sc, ccb);
2126
2127 return (rv);
2128
2129 err:
2130 mpi_dmamem_free(sc, sc->sc_fw);
2131 return (1);
2132 }
2133
2134 void
2135 mpi_get_raid(struct mpi_softc *sc)
2136 {
2137 struct mpi_cfg_hdr hdr;
2138 struct mpi_cfg_ioc_pg2 *vol_page;
2139 struct mpi_cfg_raid_vol *vol_list, *vol;
2140 size_t pagelen;
2141 u_int32_t capabilities;
2142 struct scsi_link *link;
2143 int i;
2144
2145 DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid\n", DEVNAME(sc));
2146
2147 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_IOC, 2, 0, &hdr) != 0) {
2148 DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to fetch header"
2149 "for IOC page 2\n", DEVNAME(sc));
2150 return;
2151 }
2152
2153 pagelen = hdr.page_length * 4;
2154 vol_page = malloc(pagelen, M_TEMP, M_WAITOK|M_CANFAIL);
2155 if (vol_page == NULL) {
2156 DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to allocate "
2157 "space for ioc config page 2\n", DEVNAME(sc));
2158 return;
2159 }
2160 vol_list = (struct mpi_cfg_raid_vol *)(vol_page + 1);
2161
2162 if (mpi_cfg_page(sc, 0, &hdr, 1, vol_page, pagelen) != 0) {
2163 DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to fetch IOC "
2164 "page 2\n", DEVNAME(sc));
2165 goto out;
2166 }
2167
2168 capabilities = letoh32(vol_page->capabilities);
2169
2170 DNPRINTF(MPI_D_RAID, "%s: capabilities: 0x08%x\n", DEVNAME(sc),
2171 letoh32(vol_page->capabilities));
2172 DNPRINTF(MPI_D_RAID, "%s: active_vols: %d max_vols: %d "
2173 "active_physdisks: %d max_physdisks: %d\n", DEVNAME(sc),
2174 vol_page->active_vols, vol_page->max_vols,
2175 vol_page->active_physdisks, vol_page->max_physdisks);
2176
2177
2178 if (capabilities == 0xdeadbeef) {
2179 printf("%s: deadbeef in raid configuration\n", DEVNAME(sc));
2180 goto out;
2181 }
2182
2183 if ((capabilities & MPI_CFG_IOC_2_CAPABILITIES_RAID) == 0 ||
2184 (vol_page->active_vols == 0))
2185 goto out;
2186
2187 sc->sc_flags |= MPI_F_RAID;
2188
2189 for (i = 0; i < vol_page->active_vols; i++) {
2190 vol = &vol_list[i];
2191
2192 DNPRINTF(MPI_D_RAID, "%s: id: %d bus: %d ioc: %d pg: %d\n",
2193 DEVNAME(sc), vol->vol_id, vol->vol_bus, vol->vol_ioc,
2194 vol->vol_page);
2195 DNPRINTF(MPI_D_RAID, "%s: type: 0x%02x flags: 0x%02x\n",
2196 DEVNAME(sc), vol->vol_type, vol->flags);
2197
2198 if (vol->vol_ioc != sc->sc_ioc_number || vol->vol_bus != 0)
2199 continue;
2200
2201 link = sc->sc_scsibus->sc_link[vol->vol_id][0];
2202 if (link == NULL)
2203 continue;
2204
2205 link->flags |= SDEV_VIRTUAL;
2206 }
2207
2208 out:
2209 free(vol_page, M_TEMP);
2210 }
2211
2212 int
2213 mpi_cfg_header(struct mpi_softc *sc, u_int8_t type, u_int8_t number,
2214 u_int32_t address, struct mpi_cfg_hdr *hdr)
2215 {
2216 struct mpi_ccb *ccb;
2217 struct mpi_msg_config_request *cq;
2218 struct mpi_msg_config_reply *cp;
2219 int rv = 0;
2220 int s;
2221
2222 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header type: %#x number: %x "
2223 "address: %d\n", DEVNAME(sc), type, number, address);
2224
2225 s = splbio();
2226 ccb = mpi_get_ccb(sc);
2227 splx(s);
2228 if (ccb == NULL) {
2229 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header ccb_get\n",
2230 DEVNAME(sc));
2231 return (1);
2232 }
2233
2234 ccb->ccb_done = mpi_empty_done;
2235 cq = ccb->ccb_cmd;
2236
2237 cq->function = MPI_FUNCTION_CONFIG;
2238 cq->msg_context = htole32(ccb->ccb_id);
2239
2240 cq->action = MPI_CONFIG_REQ_ACTION_PAGE_HEADER;
2241
2242 cq->config_header.page_number = number;
2243 cq->config_header.page_type = type;
2244 cq->page_address = htole32(address);
2245 cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
2246 MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL);
2247
2248 if (mpi_poll(sc, ccb, 50000) != 0) {
2249 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header poll\n", DEVNAME(sc));
2250 return (1);
2251 }
2252
2253 if (ccb->ccb_rcb == NULL)
2254 panic("%s: unable to fetch config header\n", DEVNAME(sc));
2255 cp = ccb->ccb_rcb->rcb_reply;
2256
2257 DNPRINTF(MPI_D_MISC, "%s: action: 0x%02x msg_length: %d function: "
2258 "0x%02x\n", DEVNAME(sc), cp->action, cp->msg_length, cp->function);
2259 DNPRINTF(MPI_D_MISC, "%s: ext_page_length: %d ext_page_type: 0x%02x "
2260 "msg_flags: 0x%02x\n", DEVNAME(sc),
2261 letoh16(cp->ext_page_length), cp->ext_page_type,
2262 cp->msg_flags);
2263 DNPRINTF(MPI_D_MISC, "%s: msg_context: 0x%08x\n", DEVNAME(sc),
2264 letoh32(cp->msg_context));
2265 DNPRINTF(MPI_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc),
2266 letoh16(cp->ioc_status));
2267 DNPRINTF(MPI_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc),
2268 letoh32(cp->ioc_loginfo));
2269 DNPRINTF(MPI_D_MISC, "%s: page_version: 0x%02x page_length: %d "
2270 "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
2271 cp->config_header.page_version,
2272 cp->config_header.page_length,
2273 cp->config_header.page_number,
2274 cp->config_header.page_type);
2275
2276 if (letoh16(cp->ioc_status) != MPI_IOCSTATUS_SUCCESS)
2277 rv = 1;
2278 else
2279 *hdr = cp->config_header;
2280
2281 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
2282 mpi_put_ccb(sc, ccb);
2283
2284 return (rv);
2285 }
2286
2287 int
2288 mpi_cfg_page(struct mpi_softc *sc, u_int32_t address, struct mpi_cfg_hdr *hdr,
2289 int read, void *page, size_t len)
2290 {
2291 struct mpi_ccb *ccb;
2292 struct mpi_msg_config_request *cq;
2293 struct mpi_msg_config_reply *cp;
2294 u_int64_t dva;
2295 char *kva;
2296 int rv = 0;
2297 int s;
2298
2299 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page address: %d read: %d type: %x\n",
2300 DEVNAME(sc), address, read, hdr->page_type);
2301
2302 if (len > MPI_REQUEST_SIZE - sizeof(struct mpi_msg_config_request) ||
2303 len < hdr->page_length * 4)
2304 return (1);
2305
2306 s = splbio();
2307 ccb = mpi_get_ccb(sc);
2308 splx(s);
2309 if (ccb == NULL) {
2310 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page ccb_get\n", DEVNAME(sc));
2311 return (1);
2312 }
2313
2314 ccb->ccb_done = mpi_empty_done;
2315 cq = ccb->ccb_cmd;
2316
2317 cq->function = MPI_FUNCTION_CONFIG;
2318 cq->msg_context = htole32(ccb->ccb_id);
2319
2320 cq->action = (read ? MPI_CONFIG_REQ_ACTION_PAGE_READ_CURRENT :
2321 MPI_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT);
2322
2323 cq->config_header = *hdr;
2324 cq->config_header.page_type &= MPI_CONFIG_REQ_PAGE_TYPE_MASK;
2325 cq->page_address = htole32(address);
2326 cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
2327 MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL |
2328 (hdr->page_length * 4) |
2329 (read ? MPI_SGE_FL_DIR_IN : MPI_SGE_FL_DIR_OUT));
2330
2331
2332 dva = ccb->ccb_cmd_dva + sizeof(struct mpi_msg_config_request);
2333
2334 cq->page_buffer.sg_hi_addr = htole32((u_int32_t)(dva >> 32));
2335 cq->page_buffer.sg_lo_addr = htole32((u_int32_t)dva);
2336
2337 kva = ccb->ccb_cmd;
2338 kva += sizeof(struct mpi_msg_config_request);
2339 if (!read)
2340 bcopy(page, kva, len);
2341
2342 if (mpi_poll(sc, ccb, 50000) != 0) {
2343 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page poll\n", DEVNAME(sc));
2344 return (1);
2345 }
2346
2347 if (ccb->ccb_rcb == NULL) {
2348 mpi_put_ccb(sc, ccb);
2349 return (1);
2350 }
2351 cp = ccb->ccb_rcb->rcb_reply;
2352
2353 DNPRINTF(MPI_D_MISC, "%s: action: 0x%02x msg_length: %d function: "
2354 "0x%02x\n", DEVNAME(sc), cp->action, cp->msg_length, cp->function);
2355 DNPRINTF(MPI_D_MISC, "%s: ext_page_length: %d ext_page_type: 0x%02x "
2356 "msg_flags: 0x%02x\n", DEVNAME(sc),
2357 letoh16(cp->ext_page_length), cp->ext_page_type,
2358 cp->msg_flags);
2359 DNPRINTF(MPI_D_MISC, "%s: msg_context: 0x%08x\n", DEVNAME(sc),
2360 letoh32(cp->msg_context));
2361 DNPRINTF(MPI_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc),
2362 letoh16(cp->ioc_status));
2363 DNPRINTF(MPI_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc),
2364 letoh32(cp->ioc_loginfo));
2365 DNPRINTF(MPI_D_MISC, "%s: page_version: 0x%02x page_length: %d "
2366 "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
2367 cp->config_header.page_version,
2368 cp->config_header.page_length,
2369 cp->config_header.page_number,
2370 cp->config_header.page_type);
2371
2372 if (letoh16(cp->ioc_status) != MPI_IOCSTATUS_SUCCESS)
2373 rv = 1;
2374 else if (read)
2375 bcopy(kva, page, len);
2376
2377 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
2378 mpi_put_ccb(sc, ccb);
2379
2380 return (rv);
2381 }