Annotation of sys/dev/pci/arc.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: arc.c,v 1.65 2007/07/11 19:01:30 otto Exp $ */
2:
3: /*
4: * Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include "bio.h"
20:
21: #include <sys/param.h>
22: #include <sys/systm.h>
23: #include <sys/buf.h>
24: #include <sys/kernel.h>
25: #include <sys/malloc.h>
26: #include <sys/device.h>
27: #include <sys/proc.h>
28: #include <sys/rwlock.h>
29:
30: #include <machine/bus.h>
31:
32: #include <dev/pci/pcireg.h>
33: #include <dev/pci/pcivar.h>
34: #include <dev/pci/pcidevs.h>
35:
36: #include <scsi/scsi_all.h>
37: #include <scsi/scsiconf.h>
38:
39: #include <sys/sensors.h>
40: #if NBIO > 0
41: #include <sys/ioctl.h>
42: #include <dev/biovar.h>
43: #endif
44:
45: #ifdef ARC_DEBUG
46: #define ARC_D_INIT (1<<0)
47: #define ARC_D_RW (1<<1)
48: #define ARC_D_DB (1<<2)
49:
50: int arcdebug = 0;
51:
52: #define DPRINTF(p...) do { if (arcdebug) printf(p); } while (0)
53: #define DNPRINTF(n, p...) do { if ((n) & arcdebug) printf(p); } while (0)
54:
55: #else
56: #define DPRINTF(p...) /* p */
57: #define DNPRINTF(n, p...) /* n, p */
58: #endif
59:
60: static const struct pci_matchid arc_devices[] = {
61: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1110 },
62: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1120 },
63: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1130 },
64: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1160 },
65: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1170 },
66: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1210 },
67: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1220 },
68: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1230 },
69: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1260 },
70: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1270 },
71: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1280 },
72: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1380 },
73: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1381 },
74: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1680 },
75: { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1681 }
76: };
77:
78: #define ARC_PCI_BAR PCI_MAPREG_START
79:
80: #define ARC_REG_INB_MSG0 0x0010
81: #define ARC_REG_INB_MSG0_NOP (0x00000000)
82: #define ARC_REG_INB_MSG0_GET_CONFIG (0x00000001)
83: #define ARC_REG_INB_MSG0_SET_CONFIG (0x00000002)
84: #define ARC_REG_INB_MSG0_ABORT_CMD (0x00000003)
85: #define ARC_REG_INB_MSG0_STOP_BGRB (0x00000004)
86: #define ARC_REG_INB_MSG0_FLUSH_CACHE (0x00000005)
87: #define ARC_REG_INB_MSG0_START_BGRB (0x00000006)
88: #define ARC_REG_INB_MSG0_CHK331PENDING (0x00000007)
89: #define ARC_REG_INB_MSG0_SYNC_TIMER (0x00000008)
90: #define ARC_REG_INB_MSG1 0x0014
91: #define ARC_REG_OUTB_ADDR0 0x0018
92: #define ARC_REG_OUTB_ADDR1 0x001c
93: #define ARC_REG_OUTB_ADDR1_FIRMWARE_OK (1<<31)
94: #define ARC_REG_INB_DOORBELL 0x0020
95: #define ARC_REG_INB_DOORBELL_WRITE_OK (1<<0)
96: #define ARC_REG_INB_DOORBELL_READ_OK (1<<1)
97: #define ARC_REG_OUTB_DOORBELL 0x002c
98: #define ARC_REG_OUTB_DOORBELL_WRITE_OK (1<<0)
99: #define ARC_REG_OUTB_DOORBELL_READ_OK (1<<1)
100: #define ARC_REG_INTRSTAT 0x0030
101: #define ARC_REG_INTRSTAT_MSG0 (1<<0)
102: #define ARC_REG_INTRSTAT_MSG1 (1<<1)
103: #define ARC_REG_INTRSTAT_DOORBELL (1<<2)
104: #define ARC_REG_INTRSTAT_POSTQUEUE (1<<3)
105: #define ARC_REG_INTRSTAT_PCI (1<<4)
106: #define ARC_REG_INTRMASK 0x0034
107: #define ARC_REG_INTRMASK_MSG0 (1<<0)
108: #define ARC_REG_INTRMASK_MSG1 (1<<1)
109: #define ARC_REG_INTRMASK_DOORBELL (1<<2)
110: #define ARC_REG_INTRMASK_POSTQUEUE (1<<3)
111: #define ARC_REG_INTRMASK_PCI (1<<4)
112: #define ARC_REG_POST_QUEUE 0x0040
113: #define ARC_REG_POST_QUEUE_ADDR_SHIFT 5
114: #define ARC_REG_POST_QUEUE_IAMBIOS (1<<30)
115: #define ARC_REG_POST_QUEUE_BIGFRAME (1<<31)
116: #define ARC_REG_REPLY_QUEUE 0x0044
117: #define ARC_REG_REPLY_QUEUE_ADDR_SHIFT 5
118: #define ARC_REG_REPLY_QUEUE_ERR (1<<28)
119: #define ARC_REG_REPLY_QUEUE_IAMBIOS (1<<30)
120: #define ARC_REG_MSGBUF 0x0a00
121: #define ARC_REG_MSGBUF_LEN 1024
122: #define ARC_REG_IOC_WBUF_LEN 0x0e00
123: #define ARC_REG_IOC_WBUF 0x0e04
124: #define ARC_REG_IOC_RBUF_LEN 0x0f00
125: #define ARC_REG_IOC_RBUF 0x0f04
126: #define ARC_REG_IOC_RWBUF_MAXLEN 124 /* for both RBUF and WBUF */
127:
128: struct arc_msg_firmware_info {
129: u_int32_t signature;
130: #define ARC_FWINFO_SIGNATURE_GET_CONFIG (0x87974060)
131: u_int32_t request_len;
132: u_int32_t queue_len;
133: u_int32_t sdram_size;
134: u_int32_t sata_ports;
135: u_int8_t vendor[40];
136: u_int8_t model[8];
137: u_int8_t fw_version[16];
138: u_int8_t device_map[16];
139: } __packed;
140:
141: struct arc_msg_scsicmd {
142: u_int8_t bus;
143: u_int8_t target;
144: u_int8_t lun;
145: u_int8_t function;
146:
147: u_int8_t cdb_len;
148: u_int8_t sgl_len;
149: u_int8_t flags;
150: #define ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512 (1<<0)
151: #define ARC_MSG_SCSICMD_FLAG_FROM_BIOS (1<<1)
152: #define ARC_MSG_SCSICMD_FLAG_WRITE (1<<2)
153: #define ARC_MSG_SCSICMD_FLAG_SIMPLEQ (0x00)
154: #define ARC_MSG_SCSICMD_FLAG_HEADQ (0x08)
155: #define ARC_MSG_SCSICMD_FLAG_ORDERQ (0x10)
156: u_int8_t reserved;
157:
158: u_int32_t context;
159: u_int32_t data_len;
160:
161: #define ARC_MSG_CDBLEN 16
162: u_int8_t cdb[ARC_MSG_CDBLEN];
163:
164: u_int8_t status;
165: #define ARC_MSG_STATUS_SELTIMEOUT 0xf0
166: #define ARC_MSG_STATUS_ABORTED 0xf1
167: #define ARC_MSG_STATUS_INIT_FAIL 0xf2
168: #define ARC_MSG_SENSELEN 15
169: u_int8_t sense_data[ARC_MSG_SENSELEN];
170:
171: /* followed by an sgl */
172: } __packed;
173:
174: struct arc_sge {
175: u_int32_t sg_hdr;
176: #define ARC_SGE_64BIT (1<<24)
177: u_int32_t sg_lo_addr;
178: u_int32_t sg_hi_addr;
179: } __packed;
180:
181: #define ARC_MAX_TARGET 16
182: #define ARC_MAX_LUN 8
183: #define ARC_MAX_IOCMDLEN 512
184: #define ARC_BLOCKSIZE 512
185:
186: /* the firmware deals with up to 256 or 512 byte command frames. */
187: /* sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 38) == 508 */
188: #define ARC_SGL_MAXLEN 38
189: /* sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 17) == 252 */
190: #define ARC_SGL_256LEN 17
191:
192: struct arc_io_cmd {
193: struct arc_msg_scsicmd cmd;
194: struct arc_sge sgl[ARC_SGL_MAXLEN];
195: } __packed;
196:
197: /* definitions of the firmware commands sent via the doorbells */
198:
199: struct arc_fw_hdr {
200: u_int8_t byte1;
201: u_int8_t byte2;
202: u_int8_t byte3;
203: } __packed;
204:
205: /* the fw header must always equal this */
206: struct arc_fw_hdr arc_fw_hdr = { 0x5e, 0x01, 0x61 };
207:
208: struct arc_fw_bufhdr {
209: struct arc_fw_hdr hdr;
210: u_int16_t len;
211: } __packed;
212:
213: #define ARC_FW_RAIDINFO 0x20 /* opcode + raid# */
214: #define ARC_FW_VOLINFO 0x21 /* opcode + vol# */
215: #define ARC_FW_DISKINFO 0x22 /* opcode + physdisk# */
216: #define ARC_FW_SYSINFO 0x23 /* opcode. reply is fw_sysinfo */
217: #define ARC_FW_MUTE_ALARM 0x30 /* opcode only */
218: #define ARC_FW_SET_ALARM 0x31 /* opcode + 1 byte for setting */
219: #define ARC_FW_SET_ALARM_DISABLE 0x00
220: #define ARC_FW_SET_ALARM_ENABLE 0x01
221: #define ARC_FW_NOP 0x38 /* opcode only */
222:
223: #define ARC_FW_CMD_OK 0x41
224:
225: struct arc_fw_comminfo {
226: u_int8_t baud_rate;
227: u_int8_t data_bits;
228: u_int8_t stop_bits;
229: u_int8_t parity;
230: u_int8_t flow_control;
231: } __packed;
232:
233: struct arc_fw_scsiattr {
234: u_int8_t channel;// channel for SCSI target (0/1)
235: u_int8_t target;
236: u_int8_t lun;
237: u_int8_t tagged;
238: u_int8_t cache;
239: u_int8_t speed;
240: } __packed;
241:
242: struct arc_fw_raidinfo {
243: u_int8_t set_name[16];
244: u_int32_t capacity;
245: u_int32_t capacity2;
246: u_int32_t fail_mask;
247: u_int8_t device_array[32];
248: u_int8_t member_devices;
249: u_int8_t new_member_devices;
250: u_int8_t raid_state;
251: u_int8_t volumes;
252: u_int8_t volume_list[16];
253: u_int8_t reserved1[3];
254: u_int8_t free_segments;
255: u_int32_t raw_stripes[8];
256: u_int8_t reserved2[12];
257: } __packed;
258:
259: struct arc_fw_volinfo {
260: u_int8_t set_name[16];
261: u_int32_t capacity;
262: u_int32_t capacity2;
263: u_int32_t fail_mask;
264: u_int32_t stripe_size; /* in blocks */
265: u_int32_t new_fail_mask;
266: u_int32_t new_stripe_size;
267: u_int32_t volume_status;
268: #define ARC_FW_VOL_STATUS_NORMAL 0x00
269: #define ARC_FW_VOL_STATUS_INITTING (1<<0)
270: #define ARC_FW_VOL_STATUS_FAILED (1<<1)
271: #define ARC_FW_VOL_STATUS_MIGRATING (1<<2)
272: #define ARC_FW_VOL_STATUS_REBUILDING (1<<3)
273: #define ARC_FW_VOL_STATUS_NEED_INIT (1<<4)
274: #define ARC_FW_VOL_STATUS_NEED_MIGRATE (1<<5)
275: #define ARC_FW_VOL_STATUS_INIT_FLAG (1<<6)
276: #define ARC_FW_VOL_STATUS_NEED_REGEN (1<<7)
277: #define ARC_FW_VOL_STATUS_CHECKING (1<<8)
278: #define ARC_FW_VOL_STATUS_NEED_CHECK (1<<9)
279: u_int32_t progress;
280: struct arc_fw_scsiattr scsi_attr;
281: u_int8_t member_disks;
282: u_int8_t raid_level;
283: #define ARC_FW_VOL_RAIDLEVEL_0 0x00
284: #define ARC_FW_VOL_RAIDLEVEL_1 0x01
285: #define ARC_FW_VOL_RAIDLEVEL_3 0x02
286: #define ARC_FW_VOL_RAIDLEVEL_5 0x03
287: #define ARC_FW_VOL_RAIDLEVEL_6 0x04
288: #define ARC_FW_VOL_RAIDLEVEL_PASSTHRU 0x05
289: u_int8_t new_member_disks;
290: u_int8_t new_raid_level;
291: u_int8_t raid_set_number;
292: u_int8_t reserved[5];
293: } __packed;
294:
295: struct arc_fw_diskinfo {
296: u_int8_t model[40];
297: u_int8_t serial[20];
298: u_int8_t firmware_rev[8];
299: u_int32_t capacity;
300: u_int32_t capacity2;
301: u_int8_t device_state;
302: u_int8_t pio_mode;
303: u_int8_t current_udma_mode;
304: u_int8_t udma_mode;
305: u_int8_t drive_select;
306: u_int8_t raid_number; // 0xff unowned
307: struct arc_fw_scsiattr scsi_attr;
308: u_int8_t reserved[40];
309: } __packed;
310:
311: struct arc_fw_sysinfo {
312: u_int8_t vendor_name[40];
313: u_int8_t serial_number[16];
314: u_int8_t firmware_version[16];
315: u_int8_t boot_version[16];
316: u_int8_t mb_version[16];
317: u_int8_t model_name[8];
318:
319: u_int8_t local_ip[4];
320: u_int8_t current_ip[4];
321:
322: u_int32_t time_tick;
323: u_int32_t cpu_speed;
324: u_int32_t icache;
325: u_int32_t dcache;
326: u_int32_t scache;
327: u_int32_t memory_size;
328: u_int32_t memory_speed;
329: u_int32_t events;
330:
331: u_int8_t gsiMacAddress[6];
332: u_int8_t gsiDhcp;
333:
334: u_int8_t alarm;
335: u_int8_t channel_usage;
336: u_int8_t max_ata_mode;
337: u_int8_t sdram_ecc;
338: u_int8_t rebuild_priority;
339: struct arc_fw_comminfo comm_a;
340: struct arc_fw_comminfo comm_b;
341: u_int8_t ide_channels;
342: u_int8_t scsi_host_channels;
343: u_int8_t ide_host_channels;
344: u_int8_t max_volume_set;
345: u_int8_t max_raid_set;
346: u_int8_t ether_port;
347: u_int8_t raid6_engine;
348: u_int8_t reserved[75];
349: } __packed;
350:
351: int arc_match(struct device *, void *, void *);
352: void arc_attach(struct device *, struct device *, void *);
353: int arc_detach(struct device *, int);
354: void arc_shutdown(void *);
355: int arc_intr(void *);
356:
357: struct arc_ccb;
358: TAILQ_HEAD(arc_ccb_list, arc_ccb);
359:
360: struct arc_softc {
361: struct device sc_dev;
362: struct scsi_link sc_link;
363:
364: pci_chipset_tag_t sc_pc;
365: pcitag_t sc_tag;
366:
367: bus_space_tag_t sc_iot;
368: bus_space_handle_t sc_ioh;
369: bus_size_t sc_ios;
370: bus_dma_tag_t sc_dmat;
371:
372: void *sc_ih;
373:
374: void *sc_shutdownhook;
375:
376: int sc_req_count;
377:
378: struct arc_dmamem *sc_requests;
379: struct arc_ccb *sc_ccbs;
380: struct arc_ccb_list sc_ccb_free;
381:
382: struct scsibus_softc *sc_scsibus;
383:
384: struct rwlock sc_lock;
385: volatile int sc_talking;
386:
387: struct ksensor *sc_sensors;
388: struct ksensordev sc_sensordev;
389: int sc_nsensors;
390: };
391: #define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
392:
393: struct cfattach arc_ca = {
394: sizeof(struct arc_softc), arc_match, arc_attach, arc_detach
395: };
396:
397: struct cfdriver arc_cd = {
398: NULL, "arc", DV_DULL
399: };
400:
401: /* interface for scsi midlayer to talk to */
402: int arc_scsi_cmd(struct scsi_xfer *);
403: void arc_minphys(struct buf *);
404:
405: struct scsi_adapter arc_switch = {
406: arc_scsi_cmd, arc_minphys, NULL, NULL, NULL
407: };
408:
409: struct scsi_device arc_dev = {
410: NULL, NULL, NULL, NULL
411: };
412:
413: /* code to deal with getting bits in and out of the bus space */
414: u_int32_t arc_read(struct arc_softc *, bus_size_t);
415: void arc_read_region(struct arc_softc *, bus_size_t,
416: void *, size_t);
417: void arc_write(struct arc_softc *, bus_size_t, u_int32_t);
418: void arc_write_region(struct arc_softc *, bus_size_t,
419: void *, size_t);
420: int arc_wait_eq(struct arc_softc *, bus_size_t,
421: u_int32_t, u_int32_t);
422: int arc_wait_ne(struct arc_softc *, bus_size_t,
423: u_int32_t, u_int32_t);
424: int arc_msg0(struct arc_softc *, u_int32_t);
425:
426: #define arc_push(_s, _r) arc_write((_s), ARC_REG_POST_QUEUE, (_r))
427: #define arc_pop(_s) arc_read((_s), ARC_REG_REPLY_QUEUE)
428:
429: /* wrap up the bus_dma api */
430: struct arc_dmamem {
431: bus_dmamap_t adm_map;
432: bus_dma_segment_t adm_seg;
433: size_t adm_size;
434: caddr_t adm_kva;
435: };
436: #define ARC_DMA_MAP(_adm) ((_adm)->adm_map)
437: #define ARC_DMA_DVA(_adm) ((_adm)->adm_map->dm_segs[0].ds_addr)
438: #define ARC_DMA_KVA(_adm) ((void *)(_adm)->adm_kva)
439:
440: struct arc_dmamem *arc_dmamem_alloc(struct arc_softc *, size_t);
441: void arc_dmamem_free(struct arc_softc *,
442: struct arc_dmamem *);
443:
444: /* stuff to manage a scsi command */
445: struct arc_ccb {
446: struct arc_softc *ccb_sc;
447: int ccb_id;
448:
449: struct scsi_xfer *ccb_xs;
450:
451: bus_dmamap_t ccb_dmamap;
452: bus_addr_t ccb_offset;
453: struct arc_io_cmd *ccb_cmd;
454: u_int32_t ccb_cmd_post;
455:
456: TAILQ_ENTRY(arc_ccb) ccb_link;
457: };
458:
459: int arc_alloc_ccbs(struct arc_softc *);
460: struct arc_ccb *arc_get_ccb(struct arc_softc *);
461: void arc_put_ccb(struct arc_softc *, struct arc_ccb *);
462: int arc_load_xs(struct arc_ccb *);
463: int arc_complete(struct arc_softc *, struct arc_ccb *,
464: int);
465: void arc_scsi_cmd_done(struct arc_softc *, struct arc_ccb *,
466: u_int32_t);
467:
468: /* real stuff for dealing with the hardware */
469: int arc_map_pci_resources(struct arc_softc *,
470: struct pci_attach_args *);
471: int arc_query_firmware(struct arc_softc *);
472:
473:
474: #if NBIO > 0
475: /* stuff to do messaging via the doorbells */
476: void arc_lock(struct arc_softc *);
477: void arc_unlock(struct arc_softc *);
478: void arc_wait(struct arc_softc *);
479: u_int8_t arc_msg_cksum(void *, u_int16_t);
480: int arc_msgbuf(struct arc_softc *, void *, size_t,
481: void *, size_t);
482:
483: /* bioctl */
484: int arc_bioctl(struct device *, u_long, caddr_t);
485: int arc_bio_inq(struct arc_softc *, struct bioc_inq *);
486: int arc_bio_vol(struct arc_softc *, struct bioc_vol *);
487: int arc_bio_disk(struct arc_softc *, struct bioc_disk *);
488: int arc_bio_alarm(struct arc_softc *, struct bioc_alarm *);
489: int arc_bio_alarm_state(struct arc_softc *,
490: struct bioc_alarm *);
491:
492: int arc_bio_getvol(struct arc_softc *, int,
493: struct arc_fw_volinfo *);
494:
495: #ifndef SMALL_KERNEL
496: /* sensors */
497: void arc_create_sensors(void *, void *);
498: void arc_refresh_sensors(void *);
499: #endif /* SMALL_KERNEL */
500: #endif
501:
502: int
503: arc_match(struct device *parent, void *match, void *aux)
504: {
505: return (pci_matchbyid((struct pci_attach_args *)aux, arc_devices,
506: sizeof(arc_devices) / sizeof(arc_devices[0])));
507: }
508:
509: void
510: arc_attach(struct device *parent, struct device *self, void *aux)
511: {
512: struct arc_softc *sc = (struct arc_softc *)self;
513: struct pci_attach_args *pa = aux;
514: struct scsibus_attach_args saa;
515: struct device *child;
516:
517: sc->sc_talking = 0;
518: rw_init(&sc->sc_lock, "arcmsg");
519:
520: if (arc_map_pci_resources(sc, pa) != 0) {
521: /* error message printed by arc_map_pci_resources */
522: return;
523: }
524:
525: if (arc_query_firmware(sc) != 0) {
526: /* error message printed by arc_query_firmware */
527: return;
528: }
529:
530: if (arc_alloc_ccbs(sc) != 0) {
531: /* error message printed by arc_alloc_ccbs */
532: return;
533: }
534:
535: sc->sc_shutdownhook = shutdownhook_establish(arc_shutdown, sc);
536: if (sc->sc_shutdownhook == NULL)
537: panic("unable to establish arc powerhook");
538:
539: sc->sc_link.device = &arc_dev;
540: sc->sc_link.adapter = &arc_switch;
541: sc->sc_link.adapter_softc = sc;
542: sc->sc_link.adapter_target = ARC_MAX_TARGET;
543: sc->sc_link.adapter_buswidth = ARC_MAX_TARGET;
544: sc->sc_link.openings = sc->sc_req_count / ARC_MAX_TARGET;
545:
546: bzero(&saa, sizeof(saa));
547: saa.saa_sc_link = &sc->sc_link;
548:
549: child = config_found(self, &saa, scsiprint);
550: sc->sc_scsibus = (struct scsibus_softc *)child;
551:
552: /* enable interrupts */
553: arc_write(sc, ARC_REG_INTRMASK,
554: ~(ARC_REG_INTRMASK_POSTQUEUE|ARC_REG_INTRSTAT_DOORBELL));
555:
556: #if NBIO > 0
557: if (bio_register(self, arc_bioctl) != 0)
558: panic("%s: bioctl registration failed\n", DEVNAME(sc));
559:
560: #ifndef SMALL_KERNEL
561: /*
562: * you need to talk to the firmware to get volume info. our firmware
563: * interface relies on being able to sleep, so we need to use a thread
564: * to do the work.
565: */
566: if (scsi_task(arc_create_sensors, sc, NULL, 1) != 0)
567: printf("%s: unable to schedule arc_create_sensors as a "
568: "scsi task", DEVNAME(sc));
569: #endif
570: #endif
571:
572: return;
573: }
574:
575: int
576: arc_detach(struct device *self, int flags)
577: {
578: struct arc_softc *sc = (struct arc_softc *)self;
579:
580: shutdownhook_disestablish(sc->sc_shutdownhook);
581:
582: if (arc_msg0(sc, ARC_REG_INB_MSG0_STOP_BGRB) != 0)
583: printf("%s: timeout waiting to stop bg rebuild\n", DEVNAME(sc));
584:
585: if (arc_msg0(sc, ARC_REG_INB_MSG0_FLUSH_CACHE) != 0)
586: printf("%s: timeout waiting to flush cache\n", DEVNAME(sc));
587:
588: return (0);
589: }
590:
591: void
592: arc_shutdown(void *xsc)
593: {
594: struct arc_softc *sc = xsc;
595:
596: if (arc_msg0(sc, ARC_REG_INB_MSG0_STOP_BGRB) != 0)
597: printf("%s: timeout waiting to stop bg rebuild\n", DEVNAME(sc));
598:
599: if (arc_msg0(sc, ARC_REG_INB_MSG0_FLUSH_CACHE) != 0)
600: printf("%s: timeout waiting to flush cache\n", DEVNAME(sc));
601: }
602:
603: int
604: arc_intr(void *arg)
605: {
606: struct arc_softc *sc = arg;
607: struct arc_ccb *ccb = NULL;
608: char *kva = ARC_DMA_KVA(sc->sc_requests);
609: struct arc_io_cmd *cmd;
610: u_int32_t reg, intrstat;
611:
612: intrstat = arc_read(sc, ARC_REG_INTRSTAT);
613: if (intrstat == 0x0)
614: return (0);
615: intrstat &= ARC_REG_INTRSTAT_POSTQUEUE | ARC_REG_INTRSTAT_DOORBELL;
616: arc_write(sc, ARC_REG_INTRSTAT, intrstat);
617:
618: if (intrstat & ARC_REG_INTRSTAT_DOORBELL) {
619: if (sc->sc_talking) {
620: /* if an ioctl is talking, wake it up */
621: arc_write(sc, ARC_REG_INTRMASK,
622: ~ARC_REG_INTRMASK_POSTQUEUE);
623: wakeup(sc);
624: } else {
625: /* otherwise drop it */
626: reg = arc_read(sc, ARC_REG_OUTB_DOORBELL);
627: arc_write(sc, ARC_REG_OUTB_DOORBELL, reg);
628: if (reg & ARC_REG_OUTB_DOORBELL_WRITE_OK)
629: arc_write(sc, ARC_REG_INB_DOORBELL,
630: ARC_REG_INB_DOORBELL_READ_OK);
631: }
632: }
633:
634: while ((reg = arc_pop(sc)) != 0xffffffff) {
635: cmd = (struct arc_io_cmd *)(kva +
636: ((reg << ARC_REG_REPLY_QUEUE_ADDR_SHIFT) -
637: (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
638: ccb = &sc->sc_ccbs[letoh32(cmd->cmd.context)];
639:
640: bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
641: ccb->ccb_offset, ARC_MAX_IOCMDLEN,
642: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
643:
644: arc_scsi_cmd_done(sc, ccb, reg);
645: }
646:
647: return (1);
648: }
649:
650: int
651: arc_scsi_cmd(struct scsi_xfer *xs)
652: {
653: struct scsi_link *link = xs->sc_link;
654: struct arc_softc *sc = link->adapter_softc;
655: struct arc_ccb *ccb;
656: struct arc_msg_scsicmd *cmd;
657: u_int32_t reg;
658: int rv = SUCCESSFULLY_QUEUED;
659: int s;
660:
661: if (xs->cmdlen > ARC_MSG_CDBLEN) {
662: bzero(&xs->sense, sizeof(xs->sense));
663: xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
664: xs->sense.flags = SKEY_ILLEGAL_REQUEST;
665: xs->sense.add_sense_code = 0x20;
666: xs->error = XS_SENSE;
667: s = splbio();
668: scsi_done(xs);
669: splx(s);
670: return (COMPLETE);
671: }
672:
673: s = splbio();
674: ccb = arc_get_ccb(sc);
675: splx(s);
676: if (ccb == NULL) {
677: xs->error = XS_DRIVER_STUFFUP;
678: s = splbio();
679: scsi_done(xs);
680: splx(s);
681: return (COMPLETE);
682: }
683:
684: ccb->ccb_xs = xs;
685:
686: if (arc_load_xs(ccb) != 0) {
687: xs->error = XS_DRIVER_STUFFUP;
688: s = splbio();
689: arc_put_ccb(sc, ccb);
690: scsi_done(xs);
691: splx(s);
692: return (COMPLETE);
693: }
694:
695: cmd = &ccb->ccb_cmd->cmd;
696: reg = ccb->ccb_cmd_post;
697:
698: /* bus is always 0 */
699: cmd->target = link->target;
700: cmd->lun = link->lun;
701: cmd->function = 1; /* XXX magic number */
702:
703: cmd->cdb_len = xs->cmdlen;
704: cmd->sgl_len = ccb->ccb_dmamap->dm_nsegs;
705: if (xs->flags & SCSI_DATA_OUT)
706: cmd->flags = ARC_MSG_SCSICMD_FLAG_WRITE;
707: if (ccb->ccb_dmamap->dm_nsegs > ARC_SGL_256LEN) {
708: cmd->flags |= ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512;
709: reg |= ARC_REG_POST_QUEUE_BIGFRAME;
710: }
711:
712: cmd->context = htole32(ccb->ccb_id);
713: cmd->data_len = htole32(xs->datalen);
714:
715: bcopy(xs->cmd, cmd->cdb, xs->cmdlen);
716:
717: /* we've built the command, let's put it on the hw */
718: bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
719: ccb->ccb_offset, ARC_MAX_IOCMDLEN,
720: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
721:
722: s = splbio();
723: arc_push(sc, reg);
724: if (xs->flags & SCSI_POLL) {
725: rv = COMPLETE;
726: if (arc_complete(sc, ccb, xs->timeout) != 0) {
727: xs->error = XS_DRIVER_STUFFUP;
728: scsi_done(xs);
729: }
730: }
731: splx(s);
732:
733: return (rv);
734: }
735:
736: int
737: arc_load_xs(struct arc_ccb *ccb)
738: {
739: struct arc_softc *sc = ccb->ccb_sc;
740: struct scsi_xfer *xs = ccb->ccb_xs;
741: bus_dmamap_t dmap = ccb->ccb_dmamap;
742: struct arc_sge *sgl = ccb->ccb_cmd->sgl, *sge;
743: u_int64_t addr;
744: int i, error;
745:
746: if (xs->datalen == 0)
747: return (0);
748:
749: error = bus_dmamap_load(sc->sc_dmat, dmap,
750: xs->data, xs->datalen, NULL,
751: (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
752: if (error != 0) {
753: printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
754: return (1);
755: }
756:
757: for (i = 0; i < dmap->dm_nsegs; i++) {
758: sge = &sgl[i];
759:
760: sge->sg_hdr = htole32(ARC_SGE_64BIT | dmap->dm_segs[i].ds_len);
761: addr = dmap->dm_segs[i].ds_addr;
762: sge->sg_hi_addr = htole32((u_int32_t)(addr >> 32));
763: sge->sg_lo_addr = htole32((u_int32_t)addr);
764: }
765:
766: bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
767: (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
768: BUS_DMASYNC_PREWRITE);
769:
770: return (0);
771: }
772:
773: void
774: arc_scsi_cmd_done(struct arc_softc *sc, struct arc_ccb *ccb, u_int32_t reg)
775: {
776: struct scsi_xfer *xs = ccb->ccb_xs;
777: struct arc_msg_scsicmd *cmd;
778:
779: if (xs->datalen != 0) {
780: bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
781: ccb->ccb_dmamap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?
782: BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
783: bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
784: }
785:
786: /* timeout_del */
787: xs->flags |= ITSDONE;
788:
789: if (reg & ARC_REG_REPLY_QUEUE_ERR) {
790: cmd = &ccb->ccb_cmd->cmd;
791:
792: switch (cmd->status) {
793: case ARC_MSG_STATUS_SELTIMEOUT:
794: case ARC_MSG_STATUS_ABORTED:
795: case ARC_MSG_STATUS_INIT_FAIL:
796: xs->status = SCSI_OK;
797: xs->error = XS_SELTIMEOUT;
798: break;
799:
800: case SCSI_CHECK:
801: bzero(&xs->sense, sizeof(xs->sense));
802: bcopy(cmd->sense_data, &xs->sense,
803: min(ARC_MSG_SENSELEN, sizeof(xs->sense)));
804: xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
805: xs->status = SCSI_CHECK;
806: xs->error = XS_SENSE;
807: xs->resid = 0;
808: break;
809:
810: default:
811: /* unknown device status */
812: xs->error = XS_BUSY; /* try again later? */
813: xs->status = SCSI_BUSY;
814: break;
815: }
816: } else {
817: xs->status = SCSI_OK;
818: xs->error = XS_NOERROR;
819: xs->resid = 0;
820: }
821:
822: arc_put_ccb(sc, ccb);
823: scsi_done(xs);
824: }
825:
826: int
827: arc_complete(struct arc_softc *sc, struct arc_ccb *nccb, int timeout)
828: {
829: struct arc_ccb *ccb = NULL;
830: char *kva = ARC_DMA_KVA(sc->sc_requests);
831: struct arc_io_cmd *cmd;
832: u_int32_t reg;
833:
834: do {
835: reg = arc_pop(sc);
836: if (reg == 0xffffffff) {
837: if (timeout-- == 0)
838: return (1);
839:
840: delay(1000);
841: continue;
842: }
843:
844: cmd = (struct arc_io_cmd *)(kva +
845: ((reg << ARC_REG_REPLY_QUEUE_ADDR_SHIFT) -
846: ARC_DMA_DVA(sc->sc_requests)));
847: ccb = &sc->sc_ccbs[letoh32(cmd->cmd.context)];
848:
849: bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
850: ccb->ccb_offset, ARC_MAX_IOCMDLEN,
851: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
852:
853: arc_scsi_cmd_done(sc, ccb, reg);
854: } while (nccb != ccb);
855:
856: return (0);
857: }
858:
859: void
860: arc_minphys(struct buf *bp)
861: {
862: if (bp->b_bcount > MAXPHYS)
863: bp->b_bcount = MAXPHYS;
864: minphys(bp);
865: }
866:
867: int
868: arc_map_pci_resources(struct arc_softc *sc, struct pci_attach_args *pa)
869: {
870: pcireg_t memtype;
871: pci_intr_handle_t ih;
872: const char *intrstr;
873:
874: sc->sc_pc = pa->pa_pc;
875: sc->sc_tag = pa->pa_tag;
876: sc->sc_dmat = pa->pa_dmat;
877:
878: memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, ARC_PCI_BAR);
879: if (pci_mapreg_map(pa, ARC_PCI_BAR, memtype, 0, &sc->sc_iot,
880: &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
881: printf(": unable to map system interface register\n");
882: return(1);
883: }
884:
885: if (pci_intr_map(pa, &ih) != 0) {
886: printf(": unable to map interrupt\n");
887: goto unmap;
888: }
889: intrstr = pci_intr_string(pa->pa_pc, ih);
890: sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
891: arc_intr, sc, DEVNAME(sc));
892: if (sc->sc_ih == NULL) {
893: printf(": unable to map interrupt%s%s\n",
894: intrstr == NULL ? "" : " at ",
895: intrstr == NULL ? "" : intrstr);
896: goto unmap;
897: }
898: printf(": %s\n", intrstr);
899:
900: return (0);
901:
902: unmap:
903: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
904: sc->sc_ios = 0;
905: return (1);
906: }
907:
908: int
909: arc_query_firmware(struct arc_softc *sc)
910: {
911: struct arc_msg_firmware_info fwinfo;
912: char string[81]; /* sizeof(vendor)*2+1 */
913:
914: if (arc_wait_eq(sc, ARC_REG_OUTB_ADDR1, ARC_REG_OUTB_ADDR1_FIRMWARE_OK,
915: ARC_REG_OUTB_ADDR1_FIRMWARE_OK) != 0) {
916: printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
917: return (1);
918: }
919:
920: if (arc_msg0(sc, ARC_REG_INB_MSG0_GET_CONFIG) != 0) {
921: printf("%s: timeout waiting for get config\n", DEVNAME(sc));
922: return (1);
923: }
924:
925: arc_read_region(sc, ARC_REG_MSGBUF, &fwinfo, sizeof(fwinfo));
926:
927: DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n", DEVNAME(sc),
928: letoh32(fwinfo.signature));
929:
930: if (letoh32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
931: printf("%s: invalid firmware info from iop\n", DEVNAME(sc));
932: return (1);
933: }
934:
935: DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n", DEVNAME(sc),
936: letoh32(fwinfo.request_len));
937: DNPRINTF(ARC_D_INIT, "%s: queue_len: %d\n", DEVNAME(sc),
938: letoh32(fwinfo.queue_len));
939: DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n", DEVNAME(sc),
940: letoh32(fwinfo.sdram_size));
941: DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n", DEVNAME(sc),
942: letoh32(fwinfo.sata_ports), letoh32(fwinfo.sata_ports));
943:
944: #ifdef ARC_DEBUG
945: scsi_strvis(string, fwinfo.vendor, sizeof(fwinfo.vendor));
946: DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n", DEVNAME(sc), string);
947: scsi_strvis(string, fwinfo.model, sizeof(fwinfo.model));
948: DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
949: #endif /* ARC_DEBUG */
950:
951: scsi_strvis(string, fwinfo.fw_version, sizeof(fwinfo.fw_version));
952: DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
953:
954: if (letoh32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
955: printf("%s: unexpected request frame size (%d != %d)\n",
956: DEVNAME(sc), letoh32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
957: return (1);
958: }
959:
960: sc->sc_req_count = letoh32(fwinfo.queue_len);
961:
962: if (arc_msg0(sc, ARC_REG_INB_MSG0_START_BGRB) != 0) {
963: printf("%s: timeout waiting to start bg rebuild\n",
964: DEVNAME(sc));
965: return (1);
966: }
967:
968: printf("%s: %d SATA Ports, %dMB SDRAM, FW Version: %s\n",
969: DEVNAME(sc), letoh32(fwinfo.sata_ports),
970: letoh32(fwinfo.sdram_size), string);
971:
972: return (0);
973: }
974:
975: #if NBIO > 0
976: int
977: arc_bioctl(struct device *self, u_long cmd, caddr_t addr)
978: {
979: struct arc_softc *sc = (struct arc_softc *)self;
980: int error = 0;
981:
982: switch (cmd) {
983: case BIOCINQ:
984: error = arc_bio_inq(sc, (struct bioc_inq *)addr);
985: break;
986:
987: case BIOCVOL:
988: error = arc_bio_vol(sc, (struct bioc_vol *)addr);
989: break;
990:
991: case BIOCDISK:
992: error = arc_bio_disk(sc, (struct bioc_disk *)addr);
993: break;
994:
995: case BIOCALARM:
996: error = arc_bio_alarm(sc, (struct bioc_alarm *)addr);
997: break;
998:
999: default:
1000: error = ENOTTY;
1001: break;
1002: }
1003:
1004: return (error);
1005: }
1006:
1007: int
1008: arc_bio_alarm(struct arc_softc *sc, struct bioc_alarm *ba)
1009: {
1010: u_int8_t request[2];
1011: u_int8_t reply[1];
1012: size_t len;
1013: int error = 0;
1014:
1015: switch (ba->ba_opcode) {
1016: case BIOC_SAENABLE:
1017: case BIOC_SADISABLE:
1018: request[0] = ARC_FW_SET_ALARM;
1019: request[1] = (ba->ba_opcode == BIOC_SAENABLE) ?
1020: ARC_FW_SET_ALARM_ENABLE : ARC_FW_SET_ALARM_DISABLE;
1021: len = sizeof(request);
1022:
1023: break;
1024:
1025: case BIOC_SASILENCE:
1026: request[0] = ARC_FW_MUTE_ALARM;
1027: len = 1;
1028:
1029: break;
1030:
1031: case BIOC_GASTATUS:
1032: /* system info is too big/ugly to deal with here */
1033: return (arc_bio_alarm_state(sc, ba));
1034:
1035: default:
1036: return (EOPNOTSUPP);
1037: }
1038:
1039: arc_lock(sc);
1040: error = arc_msgbuf(sc, request, len, reply, sizeof(reply));
1041: arc_unlock(sc);
1042:
1043: if (error != 0)
1044: return (error);
1045:
1046: if (reply[0] != ARC_FW_CMD_OK)
1047: return (EIO);
1048:
1049: return (0);
1050: }
1051:
1052: int
1053: arc_bio_alarm_state(struct arc_softc *sc, struct bioc_alarm *ba)
1054: {
1055: u_int8_t request = ARC_FW_SYSINFO;
1056: struct arc_fw_sysinfo *sysinfo;
1057: int error = 0;
1058:
1059: sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
1060:
1061: request = ARC_FW_SYSINFO;
1062:
1063: arc_lock(sc);
1064: error = arc_msgbuf(sc, &request, sizeof(request),
1065: sysinfo, sizeof(struct arc_fw_sysinfo));
1066: arc_unlock(sc);
1067:
1068: if (error != 0)
1069: goto out;
1070:
1071: ba->ba_status = sysinfo->alarm;
1072:
1073: out:
1074: free(sysinfo, M_TEMP);
1075: return (error);
1076: }
1077:
1078:
1079: int
1080: arc_bio_inq(struct arc_softc *sc, struct bioc_inq *bi)
1081: {
1082: u_int8_t request[2];
1083: struct arc_fw_sysinfo *sysinfo;
1084: struct arc_fw_volinfo *volinfo;
1085: int maxvols, nvols = 0, i;
1086: int error = 0;
1087:
1088: sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
1089: volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
1090:
1091: arc_lock(sc);
1092:
1093: request[0] = ARC_FW_SYSINFO;
1094: error = arc_msgbuf(sc, request, 1, sysinfo,
1095: sizeof(struct arc_fw_sysinfo));
1096: if (error != 0)
1097: goto out;
1098:
1099: maxvols = sysinfo->max_volume_set;
1100:
1101: request[0] = ARC_FW_VOLINFO;
1102: for (i = 0; i < maxvols; i++) {
1103: request[1] = i;
1104: error = arc_msgbuf(sc, request, sizeof(request), volinfo,
1105: sizeof(struct arc_fw_volinfo));
1106: if (error != 0)
1107: goto out;
1108:
1109: /*
1110: * I can't find an easy way to see if the volume exists or not
1111: * except to say that if it has no capacity then it isn't there.
1112: * Ignore passthru volumes, bioc_vol doesn't understand them.
1113: */
1114: if ((volinfo->capacity != 0 || volinfo->capacity2 != 0) &&
1115: volinfo->raid_level != ARC_FW_VOL_RAIDLEVEL_PASSTHRU)
1116: nvols++;
1117: }
1118:
1119: strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
1120: bi->bi_novol = nvols;
1121: out:
1122: arc_unlock(sc);
1123: free(volinfo, M_TEMP);
1124: free(sysinfo, M_TEMP);
1125: return (error);
1126: }
1127:
1128: int
1129: arc_bio_getvol(struct arc_softc *sc, int vol, struct arc_fw_volinfo *volinfo)
1130: {
1131: u_int8_t request[2];
1132: struct arc_fw_sysinfo *sysinfo;
1133: int error = 0;
1134: int maxvols, nvols = 0, i;
1135:
1136: sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
1137:
1138: request[0] = ARC_FW_SYSINFO;
1139: error = arc_msgbuf(sc, request, 1, sysinfo,
1140: sizeof(struct arc_fw_sysinfo));
1141: if (error != 0)
1142: goto out;
1143:
1144: maxvols = sysinfo->max_volume_set;
1145:
1146: request[0] = ARC_FW_VOLINFO;
1147: for (i = 0; i < maxvols; i++) {
1148: request[1] = i;
1149: error = arc_msgbuf(sc, request, sizeof(request), volinfo,
1150: sizeof(struct arc_fw_volinfo));
1151: if (error != 0)
1152: goto out;
1153:
1154: if ((volinfo->capacity == 0 && volinfo->capacity2 == 0) ||
1155: volinfo->raid_level == ARC_FW_VOL_RAIDLEVEL_PASSTHRU)
1156: continue;
1157:
1158: if (nvols == vol)
1159: break;
1160:
1161: nvols++;
1162: }
1163:
1164: if (nvols != vol ||
1165: (volinfo->capacity == 0 && volinfo->capacity2 == 0) ||
1166: volinfo->raid_level == ARC_FW_VOL_RAIDLEVEL_PASSTHRU) {
1167: error = ENODEV;
1168: goto out;
1169: }
1170:
1171: out:
1172: free(sysinfo, M_TEMP);
1173: return (error);
1174: }
1175:
1176: int
1177: arc_bio_vol(struct arc_softc *sc, struct bioc_vol *bv)
1178: {
1179: struct arc_fw_volinfo *volinfo;
1180: struct scsi_link *sc_link;
1181: struct device *dev;
1182: u_int64_t blocks;
1183: u_int32_t status;
1184: int error = 0;
1185:
1186: volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
1187:
1188: arc_lock(sc);
1189: error = arc_bio_getvol(sc, bv->bv_volid, volinfo);
1190: arc_unlock(sc);
1191:
1192: if (error != 0)
1193: goto out;
1194:
1195: bv->bv_percent = -1;
1196: bv->bv_seconds = 0;
1197:
1198: status = letoh32(volinfo->volume_status);
1199: if (status == 0x0) {
1200: if (letoh32(volinfo->fail_mask) == 0x0)
1201: bv->bv_status = BIOC_SVONLINE;
1202: else
1203: bv->bv_status = BIOC_SVDEGRADED;
1204: } else if (status & ARC_FW_VOL_STATUS_NEED_REGEN)
1205: bv->bv_status = BIOC_SVDEGRADED;
1206: else if (status & ARC_FW_VOL_STATUS_FAILED)
1207: bv->bv_status = BIOC_SVOFFLINE;
1208: else if (status & ARC_FW_VOL_STATUS_INITTING) {
1209: bv->bv_status = BIOC_SVBUILDING;
1210: bv->bv_percent = letoh32(volinfo->progress) / 10;
1211: } else if (status & ARC_FW_VOL_STATUS_REBUILDING) {
1212: bv->bv_status = BIOC_SVREBUILD;
1213: bv->bv_percent = letoh32(volinfo->progress) / 10;
1214: }
1215:
1216: blocks = (u_int64_t)letoh32(volinfo->capacity2) << 32;
1217: blocks += (u_int64_t)letoh32(volinfo->capacity);
1218: bv->bv_size = blocks * ARC_BLOCKSIZE; /* XXX */
1219:
1220: switch (volinfo->raid_level) {
1221: case ARC_FW_VOL_RAIDLEVEL_0:
1222: bv->bv_level = 0;
1223: break;
1224: case ARC_FW_VOL_RAIDLEVEL_1:
1225: bv->bv_level = 1;
1226: break;
1227: case ARC_FW_VOL_RAIDLEVEL_3:
1228: bv->bv_level = 3;
1229: break;
1230: case ARC_FW_VOL_RAIDLEVEL_5:
1231: bv->bv_level = 5;
1232: break;
1233: case ARC_FW_VOL_RAIDLEVEL_6:
1234: bv->bv_level = 6;
1235: break;
1236: case ARC_FW_VOL_RAIDLEVEL_PASSTHRU:
1237: default:
1238: bv->bv_level = -1;
1239: break;
1240: }
1241:
1242: bv->bv_nodisk = volinfo->member_disks;
1243: sc_link = sc->sc_scsibus->sc_link[volinfo->scsi_attr.target]
1244: [volinfo->scsi_attr.lun];
1245: if (sc_link != NULL) {
1246: dev = sc_link->device_softc;
1247: strlcpy(bv->bv_dev, dev->dv_xname, sizeof(bv->bv_dev));
1248: }
1249:
1250: out:
1251: free(volinfo, M_TEMP);
1252: return (error);
1253: }
1254:
1255: int
1256: arc_bio_disk(struct arc_softc *sc, struct bioc_disk *bd)
1257: {
1258: u_int8_t request[2];
1259: struct arc_fw_volinfo *volinfo;
1260: struct arc_fw_raidinfo *raidinfo;
1261: struct arc_fw_diskinfo *diskinfo;
1262: int error = 0;
1263: u_int64_t blocks;
1264: char model[81];
1265: char serial[41];
1266: char rev[17];
1267:
1268: volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
1269: raidinfo = malloc(sizeof(struct arc_fw_raidinfo), M_TEMP, M_WAITOK);
1270: diskinfo = malloc(sizeof(struct arc_fw_diskinfo), M_TEMP, M_WAITOK);
1271:
1272: arc_lock(sc);
1273:
1274: error = arc_bio_getvol(sc, bd->bd_volid, volinfo);
1275: if (error != 0)
1276: goto out;
1277:
1278: request[0] = ARC_FW_RAIDINFO;
1279: request[1] = volinfo->raid_set_number;
1280: error = arc_msgbuf(sc, request, sizeof(request), raidinfo,
1281: sizeof(struct arc_fw_raidinfo));
1282: if (error != 0)
1283: goto out;
1284:
1285: if (bd->bd_diskid > raidinfo->member_devices) {
1286: error = ENODEV;
1287: goto out;
1288: }
1289:
1290: if (raidinfo->device_array[bd->bd_diskid] == 0xff) {
1291: /*
1292: * the disk doesn't exist anymore. bio is too dumb to be
1293: * able to display that, so put it on another bus
1294: */
1295: bd->bd_channel = 1;
1296: bd->bd_target = 0;
1297: bd->bd_lun = 0;
1298: bd->bd_status = BIOC_SDOFFLINE;
1299: strlcpy(bd->bd_vendor, "disk missing", sizeof(bd->bd_vendor));
1300: goto out;
1301: }
1302:
1303: request[0] = ARC_FW_DISKINFO;
1304: request[1] = raidinfo->device_array[bd->bd_diskid];
1305: error = arc_msgbuf(sc, request, sizeof(request), diskinfo,
1306: sizeof(struct arc_fw_diskinfo));
1307: if (error != 0)
1308: goto out;
1309:
1310: #if 0
1311: bd->bd_channel = diskinfo->scsi_attr.channel;
1312: bd->bd_target = diskinfo->scsi_attr.target;
1313: bd->bd_lun = diskinfo->scsi_attr.lun;
1314: #endif
1315: /*
1316: * the firwmare doesnt seem to fill scsi_attr in, so fake it with
1317: * the diskid.
1318: */
1319: bd->bd_channel = 0;
1320: bd->bd_target = raidinfo->device_array[bd->bd_diskid];
1321: bd->bd_lun = 0;
1322:
1323: bd->bd_status = BIOC_SDONLINE;
1324: blocks = (u_int64_t)letoh32(diskinfo->capacity2) << 32;
1325: blocks += (u_int64_t)letoh32(diskinfo->capacity);
1326: bd->bd_size = blocks * ARC_BLOCKSIZE; /* XXX */
1327:
1328: scsi_strvis(model, diskinfo->model, sizeof(diskinfo->model));
1329: scsi_strvis(serial, diskinfo->serial, sizeof(diskinfo->serial));
1330: scsi_strvis(rev, diskinfo->firmware_rev,
1331: sizeof(diskinfo->firmware_rev));
1332:
1333: snprintf(bd->bd_vendor, sizeof(bd->bd_vendor), "%s %s",
1334: model, rev);
1335: strlcpy(bd->bd_serial, serial, sizeof(bd->bd_serial));
1336:
1337: out:
1338: arc_unlock(sc);
1339: free(diskinfo, M_TEMP);
1340: free(raidinfo, M_TEMP);
1341: free(volinfo, M_TEMP);
1342: return (error);
1343: }
1344:
1345: u_int8_t
1346: arc_msg_cksum(void *cmd, u_int16_t len)
1347: {
1348: u_int8_t *buf = cmd;
1349: u_int8_t cksum;
1350: int i;
1351:
1352: cksum = (u_int8_t)(len >> 8) + (u_int8_t)len;
1353: for (i = 0; i < len; i++)
1354: cksum += buf[i];
1355:
1356: return (cksum);
1357: }
1358:
1359:
1360: int
1361: arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wbuflen, void *rptr,
1362: size_t rbuflen)
1363: {
1364: u_int8_t rwbuf[ARC_REG_IOC_RWBUF_MAXLEN];
1365: u_int8_t *wbuf, *rbuf;
1366: int wlen, wdone = 0, rlen, rdone = 0;
1367: struct arc_fw_bufhdr *bufhdr;
1368: u_int32_t reg, rwlen;
1369: int error = 0;
1370: #ifdef ARC_DEBUG
1371: int i;
1372: #endif
1373:
1374: DNPRINTF(ARC_D_DB, "%s: arc_msgbuf wbuflen: %d rbuflen: %d\n",
1375: DEVNAME(sc), wbuflen, rbuflen);
1376:
1377: if (arc_read(sc, ARC_REG_OUTB_DOORBELL) != 0)
1378: return (EBUSY);
1379:
1380: wlen = sizeof(struct arc_fw_bufhdr) + wbuflen + 1; /* 1 for cksum */
1381: wbuf = malloc(wlen, M_TEMP, M_WAITOK);
1382:
1383: rlen = sizeof(struct arc_fw_bufhdr) + rbuflen + 1; /* 1 for cksum */
1384: rbuf = malloc(rlen, M_TEMP, M_WAITOK);
1385:
1386: DNPRINTF(ARC_D_DB, "%s: arc_msgbuf wlen: %d rlen: %d\n", DEVNAME(sc),
1387: wlen, rlen);
1388:
1389: bufhdr = (struct arc_fw_bufhdr *)wbuf;
1390: bufhdr->hdr = arc_fw_hdr;
1391: bufhdr->len = htole16(wbuflen);
1392: bcopy(wptr, wbuf + sizeof(struct arc_fw_bufhdr), wbuflen);
1393: wbuf[wlen - 1] = arc_msg_cksum(wptr, wbuflen);
1394:
1395: reg = ARC_REG_OUTB_DOORBELL_READ_OK;
1396:
1397: do {
1398: if ((reg & ARC_REG_OUTB_DOORBELL_READ_OK) && wdone < wlen) {
1399: bzero(rwbuf, sizeof(rwbuf));
1400: rwlen = (wlen - wdone) % sizeof(rwbuf);
1401: bcopy(&wbuf[wdone], rwbuf, rwlen);
1402:
1403: #ifdef ARC_DEBUG
1404: if (arcdebug & ARC_D_DB) {
1405: printf("%s: write %d:", DEVNAME(sc), rwlen);
1406: for (i = 0; i < rwlen; i++)
1407: printf(" 0x%02x", rwbuf[i]);
1408: printf("\n");
1409: }
1410: #endif
1411:
1412: /* copy the chunk to the hw */
1413: arc_write(sc, ARC_REG_IOC_WBUF_LEN, rwlen);
1414: arc_write_region(sc, ARC_REG_IOC_WBUF, rwbuf,
1415: sizeof(rwbuf));
1416:
1417: /* say we have a buffer for the hw */
1418: arc_write(sc, ARC_REG_INB_DOORBELL,
1419: ARC_REG_INB_DOORBELL_WRITE_OK);
1420:
1421: wdone += rwlen;
1422: }
1423:
1424: while ((reg = arc_read(sc, ARC_REG_OUTB_DOORBELL)) == 0)
1425: arc_wait(sc);
1426: arc_write(sc, ARC_REG_OUTB_DOORBELL, reg);
1427:
1428: DNPRINTF(ARC_D_DB, "%s: reg: 0x%08x\n", DEVNAME(sc), reg);
1429:
1430: if ((reg & ARC_REG_OUTB_DOORBELL_WRITE_OK) && rdone < rlen) {
1431: rwlen = arc_read(sc, ARC_REG_IOC_RBUF_LEN);
1432: if (rwlen > sizeof(rwbuf)) {
1433: DNPRINTF(ARC_D_DB, "%s: rwlen too big\n",
1434: DEVNAME(sc));
1435: error = EIO;
1436: goto out;
1437: }
1438:
1439: arc_read_region(sc, ARC_REG_IOC_RBUF, rwbuf,
1440: sizeof(rwbuf));
1441:
1442: arc_write(sc, ARC_REG_INB_DOORBELL,
1443: ARC_REG_INB_DOORBELL_READ_OK);
1444:
1445: #ifdef ARC_DEBUG
1446: printf("%s: len: %d+%d=%d/%d\n", DEVNAME(sc),
1447: rwlen, rdone, rwlen + rdone, rlen);
1448: if (arcdebug & ARC_D_DB) {
1449: printf("%s: read:", DEVNAME(sc));
1450: for (i = 0; i < rwlen; i++)
1451: printf(" 0x%02x", rwbuf[i]);
1452: printf("\n");
1453: }
1454: #endif
1455:
1456: if ((rdone + rwlen) > rlen) {
1457: DNPRINTF(ARC_D_DB, "%s: rwbuf too big\n",
1458: DEVNAME(sc));
1459: error = EIO;
1460: goto out;
1461: }
1462:
1463: bcopy(rwbuf, &rbuf[rdone], rwlen);
1464: rdone += rwlen;
1465: }
1466: } while (rdone != rlen);
1467:
1468: bufhdr = (struct arc_fw_bufhdr *)rbuf;
1469: if (memcmp(&bufhdr->hdr, &arc_fw_hdr, sizeof(bufhdr->hdr)) != 0 ||
1470: bufhdr->len != htole16(rbuflen)) {
1471: DNPRINTF(ARC_D_DB, "%s: rbuf hdr is wrong\n", DEVNAME(sc));
1472: error = EIO;
1473: goto out;
1474: }
1475:
1476: bcopy(rbuf + sizeof(struct arc_fw_bufhdr), rptr, rbuflen);
1477:
1478: if (rbuf[rlen - 1] != arc_msg_cksum(rptr, rbuflen)) {
1479: DNPRINTF(ARC_D_DB, "%s: invalid cksum\n", DEVNAME(sc));
1480: error = EIO;
1481: goto out;
1482: }
1483:
1484: out:
1485: free(wbuf, M_TEMP);
1486: free(rbuf, M_TEMP);
1487:
1488: return (error);
1489: }
1490:
1491: void
1492: arc_lock(struct arc_softc *sc)
1493: {
1494: int s;
1495:
1496: rw_enter_write(&sc->sc_lock);
1497: s = splbio();
1498: arc_write(sc, ARC_REG_INTRMASK, ~ARC_REG_INTRMASK_POSTQUEUE);
1499: sc->sc_talking = 1;
1500: splx(s);
1501: }
1502:
1503: void
1504: arc_unlock(struct arc_softc *sc)
1505: {
1506: int s;
1507:
1508: s = splbio();
1509: sc->sc_talking = 0;
1510: arc_write(sc, ARC_REG_INTRMASK,
1511: ~(ARC_REG_INTRMASK_POSTQUEUE|ARC_REG_INTRMASK_DOORBELL));
1512: splx(s);
1513: rw_exit_write(&sc->sc_lock);
1514: }
1515:
1516: void
1517: arc_wait(struct arc_softc *sc)
1518: {
1519: int s;
1520:
1521: s = splbio();
1522: arc_write(sc, ARC_REG_INTRMASK,
1523: ~(ARC_REG_INTRMASK_POSTQUEUE|ARC_REG_INTRMASK_DOORBELL));
1524: if (tsleep(sc, PWAIT, "arcdb", hz) == EWOULDBLOCK)
1525: arc_write(sc, ARC_REG_INTRMASK, ~ARC_REG_INTRMASK_POSTQUEUE);
1526: splx(s);
1527: }
1528:
1529: #ifndef SMALL_KERNEL
1530: void
1531: arc_create_sensors(void *xsc, void *arg)
1532: {
1533: struct arc_softc *sc = xsc;
1534: struct bioc_inq bi;
1535: struct bioc_vol bv;
1536: int i;
1537:
1538: /*
1539: * XXX * this is bollocks. the firmware has garbage coming out of it
1540: * so we have to wait a bit for it to finish spewing.
1541: */
1542: tsleep(sc, PWAIT, "arcspew", 2 * hz);
1543:
1544: bzero(&bi, sizeof(bi));
1545: if (arc_bio_inq(sc, &bi) != 0) {
1546: printf("%s: unable to query firmware for sensor info\n",
1547: DEVNAME(sc));
1548: return;
1549: }
1550: sc->sc_nsensors = bi.bi_novol;
1551:
1552: sc->sc_sensors = malloc(sizeof(struct ksensor) * sc->sc_nsensors,
1553: M_DEVBUF, M_WAITOK);
1554: bzero(sc->sc_sensors, sizeof(struct ksensor) * sc->sc_nsensors);
1555:
1556: strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
1557: sizeof(sc->sc_sensordev.xname));
1558:
1559: for (i = 0; i < sc->sc_nsensors; i++) {
1560: bzero(&bv, sizeof(bv));
1561: bv.bv_volid = i;
1562: if (arc_bio_vol(sc, &bv) != 0)
1563: goto bad;
1564:
1565: sc->sc_sensors[i].type = SENSOR_DRIVE;
1566: sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
1567:
1568: strlcpy(sc->sc_sensors[i].desc, bv.bv_dev,
1569: sizeof(sc->sc_sensors[i].desc));
1570:
1571: sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
1572: }
1573:
1574: if (sensor_task_register(sc, arc_refresh_sensors, 120) == NULL)
1575: goto bad;
1576:
1577: sensordev_install(&sc->sc_sensordev);
1578:
1579: return;
1580:
1581: bad:
1582: free(sc->sc_sensors, M_DEVBUF);
1583: }
1584:
1585: void
1586: arc_refresh_sensors(void *arg)
1587: {
1588: struct arc_softc *sc = arg;
1589: struct bioc_vol bv;
1590: int i;
1591:
1592: for (i = 0; i < sc->sc_nsensors; i++) {
1593: bzero(&bv, sizeof(bv));
1594: bv.bv_volid = i;
1595: if (arc_bio_vol(sc, &bv)) {
1596: sc->sc_sensors[i].flags = SENSOR_FINVALID;
1597: return;
1598: }
1599:
1600: switch(bv.bv_status) {
1601: case BIOC_SVOFFLINE:
1602: sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL;
1603: sc->sc_sensors[i].status = SENSOR_S_CRIT;
1604: break;
1605:
1606: case BIOC_SVDEGRADED:
1607: sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL;
1608: sc->sc_sensors[i].status = SENSOR_S_WARN;
1609: break;
1610:
1611: case BIOC_SVSCRUB:
1612: case BIOC_SVONLINE:
1613: sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE;
1614: sc->sc_sensors[i].status = SENSOR_S_OK;
1615: break;
1616:
1617: case BIOC_SVINVALID:
1618: /* FALLTRHOUGH */
1619: default:
1620: sc->sc_sensors[i].value = 0; /* unknown */
1621: sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
1622: }
1623:
1624: }
1625: }
1626: #endif /* SMALL_KERNEL */
1627: #endif /* NBIO > 0 */
1628:
1629: u_int32_t
1630: arc_read(struct arc_softc *sc, bus_size_t r)
1631: {
1632: u_int32_t v;
1633:
1634: bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1635: BUS_SPACE_BARRIER_READ);
1636: v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
1637:
1638: DNPRINTF(ARC_D_RW, "%s: arc_read 0x%x 0x%08x\n", DEVNAME(sc), r, v);
1639:
1640: return (v);
1641: }
1642:
1643: void
1644: arc_read_region(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
1645: {
1646: bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, len,
1647: BUS_SPACE_BARRIER_READ);
1648: bus_space_read_raw_region_4(sc->sc_iot, sc->sc_ioh, r, buf, len);
1649: }
1650:
1651: void
1652: arc_write(struct arc_softc *sc, bus_size_t r, u_int32_t v)
1653: {
1654: DNPRINTF(ARC_D_RW, "%s: arc_write 0x%x 0x%08x\n", DEVNAME(sc), r, v);
1655:
1656: bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
1657: bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1658: BUS_SPACE_BARRIER_WRITE);
1659: }
1660:
1661: void
1662: arc_write_region(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
1663: {
1664: bus_space_write_raw_region_4(sc->sc_iot, sc->sc_ioh, r, buf, len);
1665: bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, len,
1666: BUS_SPACE_BARRIER_WRITE);
1667: }
1668:
1669: int
1670: arc_wait_eq(struct arc_softc *sc, bus_size_t r, u_int32_t mask,
1671: u_int32_t target)
1672: {
1673: int i;
1674:
1675: DNPRINTF(ARC_D_RW, "%s: arc_wait_eq 0x%x 0x%08x 0x%08x\n",
1676: DEVNAME(sc), r, mask, target);
1677:
1678: for (i = 0; i < 10000; i++) {
1679: if ((arc_read(sc, r) & mask) == target)
1680: return (0);
1681: delay(1000);
1682: }
1683:
1684: return (1);
1685: }
1686:
1687: int
1688: arc_wait_ne(struct arc_softc *sc, bus_size_t r, u_int32_t mask,
1689: u_int32_t target)
1690: {
1691: int i;
1692:
1693: DNPRINTF(ARC_D_RW, "%s: arc_wait_ne 0x%x 0x%08x 0x%08x\n",
1694: DEVNAME(sc), r, mask, target);
1695:
1696: for (i = 0; i < 10000; i++) {
1697: if ((arc_read(sc, r) & mask) != target)
1698: return (0);
1699: delay(1000);
1700: }
1701:
1702: return (1);
1703: }
1704:
1705: int
1706: arc_msg0(struct arc_softc *sc, u_int32_t m)
1707: {
1708: /* post message */
1709: arc_write(sc, ARC_REG_INB_MSG0, m);
1710: /* wait for the fw to do it */
1711: if (arc_wait_eq(sc, ARC_REG_INTRSTAT, ARC_REG_INTRSTAT_MSG0,
1712: ARC_REG_INTRSTAT_MSG0) != 0)
1713: return (1);
1714:
1715: /* ack it */
1716: arc_write(sc, ARC_REG_INTRSTAT, ARC_REG_INTRSTAT_MSG0);
1717:
1718: return (0);
1719: }
1720:
1721: struct arc_dmamem *
1722: arc_dmamem_alloc(struct arc_softc *sc, size_t size)
1723: {
1724: struct arc_dmamem *adm;
1725: int nsegs;
1726:
1727: adm = malloc(sizeof(struct arc_dmamem), M_DEVBUF, M_NOWAIT);
1728: if (adm == NULL)
1729: return (NULL);
1730:
1731: bzero(adm, sizeof(struct arc_dmamem));
1732: adm->adm_size = size;
1733:
1734: if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
1735: BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &adm->adm_map) != 0)
1736: goto admfree;
1737:
1738: if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &adm->adm_seg,
1739: 1, &nsegs, BUS_DMA_NOWAIT) != 0)
1740: goto destroy;
1741:
1742: if (bus_dmamem_map(sc->sc_dmat, &adm->adm_seg, nsegs, size,
1743: &adm->adm_kva, BUS_DMA_NOWAIT) != 0)
1744: goto free;
1745:
1746: if (bus_dmamap_load(sc->sc_dmat, adm->adm_map, adm->adm_kva, size,
1747: NULL, BUS_DMA_NOWAIT) != 0)
1748: goto unmap;
1749:
1750: bzero(adm->adm_kva, size);
1751:
1752: return (adm);
1753:
1754: unmap:
1755: bus_dmamem_unmap(sc->sc_dmat, adm->adm_kva, size);
1756: free:
1757: bus_dmamem_free(sc->sc_dmat, &adm->adm_seg, 1);
1758: destroy:
1759: bus_dmamap_destroy(sc->sc_dmat, adm->adm_map);
1760: admfree:
1761: free(adm, M_DEVBUF);
1762:
1763: return (NULL);
1764: }
1765:
1766: void
1767: arc_dmamem_free(struct arc_softc *sc, struct arc_dmamem *adm)
1768: {
1769: bus_dmamap_unload(sc->sc_dmat, adm->adm_map);
1770: bus_dmamem_unmap(sc->sc_dmat, adm->adm_kva, adm->adm_size);
1771: bus_dmamem_free(sc->sc_dmat, &adm->adm_seg, 1);
1772: bus_dmamap_destroy(sc->sc_dmat, adm->adm_map);
1773: free(adm, M_DEVBUF);
1774: }
1775:
1776: int
1777: arc_alloc_ccbs(struct arc_softc *sc)
1778: {
1779: struct arc_ccb *ccb;
1780: u_int8_t *cmd;
1781: int i;
1782:
1783: TAILQ_INIT(&sc->sc_ccb_free);
1784:
1785: sc->sc_ccbs = malloc(sizeof(struct arc_ccb) * sc->sc_req_count,
1786: M_DEVBUF, M_WAITOK);
1787: bzero(sc->sc_ccbs, sizeof(struct arc_ccb) * sc->sc_req_count);
1788:
1789: sc->sc_requests = arc_dmamem_alloc(sc,
1790: ARC_MAX_IOCMDLEN * sc->sc_req_count);
1791: if (sc->sc_requests == NULL) {
1792: printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
1793: goto free_ccbs;
1794: }
1795: cmd = ARC_DMA_KVA(sc->sc_requests);
1796:
1797: for (i = 0; i < sc->sc_req_count; i++) {
1798: ccb = &sc->sc_ccbs[i];
1799:
1800: if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, ARC_SGL_MAXLEN,
1801: MAXPHYS, 0, 0, &ccb->ccb_dmamap) != 0) {
1802: printf("%s: unable to create dmamap for ccb %d\n",
1803: DEVNAME(sc), i);
1804: goto free_maps;
1805: }
1806:
1807: ccb->ccb_sc = sc;
1808: ccb->ccb_id = i;
1809: ccb->ccb_offset = ARC_MAX_IOCMDLEN * i;
1810:
1811: ccb->ccb_cmd = (struct arc_io_cmd *)&cmd[ccb->ccb_offset];
1812: ccb->ccb_cmd_post = (ARC_DMA_DVA(sc->sc_requests) +
1813: ccb->ccb_offset) >> ARC_REG_POST_QUEUE_ADDR_SHIFT;
1814:
1815: arc_put_ccb(sc, ccb);
1816: }
1817:
1818: return (0);
1819:
1820: free_maps:
1821: while ((ccb = arc_get_ccb(sc)) != NULL)
1822: bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
1823: arc_dmamem_free(sc, sc->sc_requests);
1824:
1825: free_ccbs:
1826: free(sc->sc_ccbs, M_DEVBUF);
1827:
1828: return (1);
1829: }
1830:
1831: struct arc_ccb *
1832: arc_get_ccb(struct arc_softc *sc)
1833: {
1834: struct arc_ccb *ccb;
1835:
1836: ccb = TAILQ_FIRST(&sc->sc_ccb_free);
1837: if (ccb != NULL)
1838: TAILQ_REMOVE(&sc->sc_ccb_free, ccb, ccb_link);
1839:
1840: return (ccb);
1841: }
1842:
1843: void
1844: arc_put_ccb(struct arc_softc *sc, struct arc_ccb *ccb)
1845: {
1846: ccb->ccb_xs = NULL;
1847: bzero(ccb->ccb_cmd, ARC_MAX_IOCMDLEN);
1848: TAILQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_link);
1849: }
CVSweb