mpt.h revision 155521
1/* $FreeBSD: head/sys/dev/mpt/mpt.h 155521 2006-02-11 01:35:29Z mjacob $ */ 2/*- 3 * Generic defines for LSI '909 FC adapters. 4 * FreeBSD Version. 5 * 6 * Copyright (c) 2000, 2001 by Greg Ansley 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice immediately at the beginning of the file, without modification, 13 * this list of conditions, and the following disclaimer. 14 * 2. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * Additional Copyright (c) 2002 by Matthew Jacob under same license. 30 */ 31/* 32 * Copyright (c) 2004, Avid Technology, Inc. and its contributors. 33 * Copyright (c) 2004, 2005 Justin T. Gibbs 34 * Copyright (c) 2005, WHEEL Sp. z o.o. 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions are 39 * met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 43 * substantially similar to the "NO WARRANTY" disclaimer below 44 * ("Disclaimer") and any redistribution must be conditioned upon including 45 * a substantially similar Disclaimer requirement for further binary 46 * redistribution. 47 * 3. Neither the names of the above listed copyright holders nor the names 48 * of any contributors may be used to endorse or promote products derived 49 * from this software without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 52 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 55 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 61 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64#ifndef _MPT_H_ 65#define _MPT_H_ 66 67/********************************* OS Includes ********************************/ 68#include <sys/types.h> 69#include <sys/param.h> 70#include <sys/systm.h> 71#include <sys/endian.h> 72#include <sys/eventhandler.h> 73#if __FreeBSD_version < 500000 74#include <sys/kernel.h> 75#include <sys/queue.h> 76#include <sys/malloc.h> 77#else 78#include <sys/lock.h> 79#include <sys/kernel.h> 80#include <sys/queue.h> 81#include <sys/malloc.h> 82#include <sys/mutex.h> 83#include <sys/condvar.h> 84#endif 85#include <sys/proc.h> 86#include <sys/bus.h> 87#include <sys/module.h> 88 89#include <machine/clock.h> 90#include <machine/cpu.h> 91#include <machine/resource.h> 92 93#include <sys/rman.h> 94 95#if __FreeBSD_version < 500000 96#include <pci/pcireg.h> 97#include <pci/pcivar.h> 98#else 99#include <dev/pci/pcireg.h> 100#include <dev/pci/pcivar.h> 101#endif 102 103#include <machine/bus.h> 104#include "opt_ddb.h" 105 106/**************************** Register Definitions ****************************/ 107#include <dev/mpt/mpt_reg.h> 108 109/******************************* MPI Definitions ******************************/ 110#include <dev/mpt/mpilib/mpi_type.h> 111#include <dev/mpt/mpilib/mpi.h> 112#include <dev/mpt/mpilib/mpi_cnfg.h> 113#include <dev/mpt/mpilib/mpi_ioc.h> 114#include <dev/mpt/mpilib/mpi_raid.h> 115 116/* XXX For mpt_debug.c */ 117#include <dev/mpt/mpilib/mpi_init.h> 118 119/****************************** Misc Definitions ******************************/ 120#define MPT_OK (0) 121#define MPT_FAIL (0x10000) 122 123#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array)) 124 125/**************************** Forward Declarations ****************************/ 126struct mpt_softc; 127struct mpt_personality; 128typedef struct req_entry request_t; 129 130/************************* Personality Module Support *************************/ 131typedef int mpt_load_handler_t(struct mpt_personality *); 132typedef int mpt_probe_handler_t(struct mpt_softc *); 133typedef int mpt_attach_handler_t(struct mpt_softc *); 134typedef int mpt_event_handler_t(struct mpt_softc *, request_t *, 135 MSG_EVENT_NOTIFY_REPLY *); 136typedef void mpt_reset_handler_t(struct mpt_softc *, int /*type*/); 137/* XXX Add return value and use for veto? */ 138typedef void mpt_shutdown_handler_t(struct mpt_softc *); 139typedef void mpt_detach_handler_t(struct mpt_softc *); 140typedef int mpt_unload_handler_t(struct mpt_personality *); 141 142struct mpt_personality 143{ 144 const char *name; 145 uint32_t id; /* Assigned identifier. */ 146 u_int use_count; /* Instances using personality*/ 147 mpt_load_handler_t *load; /* configure personailty */ 148#define MPT_PERS_FIRST_HANDLER(pers) (&(pers)->load) 149 mpt_probe_handler_t *probe; /* configure personailty */ 150 mpt_attach_handler_t *attach; /* initialize device instance */ 151 mpt_event_handler_t *event; /* Handle MPI event. */ 152 mpt_reset_handler_t *reset; /* Re-init after reset. */ 153 mpt_shutdown_handler_t *shutdown; /* Shutdown instance. */ 154 mpt_detach_handler_t *detach; /* release device instance */ 155 mpt_unload_handler_t *unload; /* Shutdown personality */ 156#define MPT_PERS_LAST_HANDLER(pers) (&(pers)->unload) 157}; 158 159int mpt_modevent(module_t, int, void *); 160 161/* Maximum supported number of personalities. */ 162#define MPT_MAX_PERSONALITIES (15) 163 164#define MPT_PERSONALITY_DEPEND(name, dep, vmin, vpref, vmax) \ 165 MODULE_DEPEND(name, dep, vmin, vpref, vmax) 166 167#define DECLARE_MPT_PERSONALITY(name, order) \ 168 static moduledata_t name##_mod = { \ 169 #name, mpt_modevent, &name##_personality \ 170 }; \ 171 DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, order); \ 172 MODULE_VERSION(name, 1); \ 173 MPT_PERSONALITY_DEPEND(name, mpt_core, 1, 1, 1) 174 175/******************************* Bus DMA Support ******************************/ 176/* XXX Need to update bus_dmamap_sync to take a range argument. */ 177#define bus_dmamap_sync_range(dma_tag, dmamap, offset, len, op) \ 178 bus_dmamap_sync(dma_tag, dmamap, op) 179 180#if __FreeBSD_version >= 501102 181#define mpt_dma_tag_create(mpt, parent_tag, alignment, boundary, \ 182 lowaddr, highaddr, filter, filterarg, \ 183 maxsize, nsegments, maxsegsz, flags, \ 184 dma_tagp) \ 185 bus_dma_tag_create(parent_tag, alignment, boundary, \ 186 lowaddr, highaddr, filter, filterarg, \ 187 maxsize, nsegments, maxsegsz, flags, \ 188 busdma_lock_mutex, &Giant, \ 189 dma_tagp) 190#else 191#define mpt_dma_tag_create(mpt, parent_tag, alignment, boundary, \ 192 lowaddr, highaddr, filter, filterarg, \ 193 maxsize, nsegments, maxsegsz, flags, \ 194 dma_tagp) \ 195 bus_dma_tag_create(parent_tag, alignment, boundary, \ 196 lowaddr, highaddr, filter, filterarg, \ 197 maxsize, nsegments, maxsegsz, flags, \ 198 dma_tagp) 199#endif 200 201struct mpt_map_info { 202 struct mpt_softc *mpt; 203 int error; 204 uint32_t phys; 205}; 206 207void mpt_map_rquest(void *, bus_dma_segment_t *, int, int); 208 209/**************************** Kernel Thread Support ***************************/ 210#if __FreeBSD_version > 500005 211#define mpt_kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \ 212 kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) 213#else 214#define mpt_kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \ 215 kthread_create(func, farg, proc_ptr, fmtstr, arg) 216#endif 217 218/****************************** Timer Facilities ******************************/ 219#if __FreeBSD_version > 500000 220#define mpt_callout_init(c) callout_init(c, /*mpsafe*/0); 221#else 222#define mpt_callout_init(c) callout_init(c); 223#endif 224 225/********************************** Endianess *********************************/ 226static __inline uint64_t 227u64toh(U64 s) 228{ 229 uint64_t result; 230 231 result = le32toh(s.Low); 232 result |= ((uint64_t)le32toh(s.High)) << 32; 233 return (result); 234} 235 236/**************************** MPI Transaction State ***************************/ 237typedef enum { 238 REQ_STATE_FREE = 0x00, 239 REQ_STATE_ALLOCATED = 0x01, 240 REQ_STATE_QUEUED = 0x02, 241 REQ_STATE_DONE = 0x04, 242 REQ_STATE_TIMEDOUT = 0x08, 243 REQ_STATE_NEED_WAKEUP = 0x10, 244 REQ_STATE_MASK = 0xFF 245} mpt_req_state_t; 246 247struct req_entry { 248 TAILQ_ENTRY(req_entry) links; /* Pointer to next in list */ 249 mpt_req_state_t state; /* Request State Information */ 250 uint16_t index; /* Index of this entry */ 251 uint16_t IOCStatus; /* Completion status */ 252 union ccb *ccb; /* CAM request */ 253 void *req_vbuf; /* Virtual Address of Entry */ 254 void *sense_vbuf; /* Virtual Address of sense data */ 255 bus_addr_t req_pbuf; /* Physical Address of Entry */ 256 bus_addr_t sense_pbuf; /* Physical Address of sense data */ 257 bus_dmamap_t dmap; /* DMA map for data buffer */ 258 struct req_entry *chain; /* for SGE overallocations */ 259}; 260 261/**************************** Handler Registration ****************************/ 262/* 263 * Global table of registered reply handlers. The 264 * handler is indicated by byte 3 of the request 265 * index submitted to the IOC. This allows the 266 * driver core to perform generic processing without 267 * any knowledge of per-personality behavior. 268 * 269 * MPT_NUM_REPLY_HANDLERS must be a power of 2 270 * to allow the easy generation of a mask. 271 * 272 * The handler offsets used by the core are hard coded 273 * allowing faster code generation when assigning a handler 274 * to a request. All "personalities" must use the 275 * the handler registration mechanism. 276 * 277 * The IOC handlers that are rarely executed are placed 278 * at the tail of the table to make it more likely that 279 * all commonly executed handlers fit in a single cache 280 * line. 281 */ 282#define MPT_NUM_REPLY_HANDLERS (16) 283#define MPT_REPLY_HANDLER_EVENTS MPT_CBI_TO_HID(0) 284#define MPT_REPLY_HANDLER_CONFIG MPT_CBI_TO_HID(MPT_NUM_REPLY_HANDLERS-1) 285#define MPT_REPLY_HANDLER_HANDSHAKE MPT_CBI_TO_HID(MPT_NUM_REPLY_HANDLERS-2) 286typedef int mpt_reply_handler_t(struct mpt_softc *mpt, request_t *request, 287 MSG_DEFAULT_REPLY *reply_frame); 288typedef union { 289 mpt_reply_handler_t *reply_handler; 290} mpt_handler_t; 291 292typedef enum { 293 MPT_HANDLER_REPLY, 294 MPT_HANDLER_EVENT, 295 MPT_HANDLER_RESET, 296 MPT_HANDLER_SHUTDOWN 297} mpt_handler_type; 298 299struct mpt_handler_record 300{ 301 LIST_ENTRY(mpt_handler_record) links; 302 mpt_handler_t handler; 303}; 304 305LIST_HEAD(mpt_handler_list, mpt_handler_record); 306 307/* 308 * The handler_id is currently unused but would contain the 309 * handler ID used in the MsgContext field to allow direction 310 * of replies to the handler. Registrations that don't require 311 * a handler id can pass in NULL for the handler_id. 312 * 313 * Deregistrations for handlers without a handler id should 314 * pass in MPT_HANDLER_ID_NONE. 315 */ 316#define MPT_HANDLER_ID_NONE (0xFFFFFFFF) 317int mpt_register_handler(struct mpt_softc *, mpt_handler_type, 318 mpt_handler_t, uint32_t *); 319int mpt_deregister_handler(struct mpt_softc *, mpt_handler_type, 320 mpt_handler_t, uint32_t); 321 322/******************* Per-Controller Instance Data Structures ******************/ 323TAILQ_HEAD(req_queue, req_entry); 324 325/* Structure for saving proper values for modifyable PCI config registers */ 326struct mpt_pci_cfg { 327 uint16_t Command; 328 uint16_t LatencyTimer_LineSize; 329 uint32_t IO_BAR; 330 uint32_t Mem0_BAR[2]; 331 uint32_t Mem1_BAR[2]; 332 uint32_t ROM_BAR; 333 uint8_t IntLine; 334 uint32_t PMCSR; 335}; 336 337typedef enum { 338 MPT_RVF_NONE = 0x0, 339 MPT_RVF_ACTIVE = 0x1, 340 MPT_RVF_ANNOUNCED = 0x2, 341 MPT_RVF_UP2DATE = 0x4, 342 MPT_RVF_REFERENCED = 0x8, 343 MPT_RVF_WCE_CHANGED = 0x10 344} mpt_raid_volume_flags; 345 346struct mpt_raid_volume { 347 CONFIG_PAGE_RAID_VOL_0 *config_page; 348 MPI_RAID_VOL_INDICATOR sync_progress; 349 mpt_raid_volume_flags flags; 350 u_int quieced_disks; 351}; 352 353typedef enum { 354 MPT_RDF_NONE = 0x00, 355 MPT_RDF_ACTIVE = 0x01, 356 MPT_RDF_ANNOUNCED = 0x02, 357 MPT_RDF_UP2DATE = 0x04, 358 MPT_RDF_REFERENCED = 0x08, 359 MPT_RDF_QUIESCING = 0x10, 360 MPT_RDF_QUIESCED = 0x20 361} mpt_raid_disk_flags; 362 363struct mpt_raid_disk { 364 CONFIG_PAGE_RAID_PHYS_DISK_0 config_page; 365 struct mpt_raid_volume *volume; 366 u_int member_number; 367 u_int pass_thru_active; 368 mpt_raid_disk_flags flags; 369}; 370 371struct mpt_evtf_record { 372 MSG_EVENT_NOTIFY_REPLY reply; 373 uint32_t context; 374 LIST_ENTRY(mpt_evtf_record) links; 375}; 376 377LIST_HEAD(mpt_evtf_list, mpt_evtf_record); 378 379struct mpt_softc { 380 device_t dev; 381#if __FreeBSD_version < 500000 382 int mpt_splsaved; 383 uint32_t mpt_islocked; 384#else 385 struct mtx mpt_lock; 386#endif 387 uint32_t mpt_pers_mask; 388 uint32_t : 14, 389 is_sas : 1, 390 raid_mwce_set : 1, 391 getreqwaiter : 1, 392 shutdwn_raid : 1, 393 shutdwn_recovery: 1, 394 unit : 8, 395 outofbeer : 1, 396 mpt_locksetup : 1, 397 disabled : 1, 398 is_fc : 1, 399 bus : 1; /* FC929/1030 have two busses */ 400 401 u_int verbose; 402 403 /* 404 * IOC Facts 405 */ 406 uint16_t mpt_global_credits; 407 uint16_t request_frame_size; 408 uint8_t mpt_max_devices; 409 uint8_t mpt_max_buses; 410 uint8_t ioc_facts_flags; 411 412 /* 413 * Port Facts 414 * XXX - Add multi-port support!. 415 */ 416 uint16_t mpt_ini_id; 417 uint16_t mpt_port_type; 418 uint16_t mpt_proto_flags; 419 420 /* 421 * Device Configuration Information 422 */ 423 union { 424 struct mpt_spi_cfg { 425 CONFIG_PAGE_SCSI_PORT_0 _port_page0; 426 CONFIG_PAGE_SCSI_PORT_1 _port_page1; 427 CONFIG_PAGE_SCSI_PORT_2 _port_page2; 428 CONFIG_PAGE_SCSI_DEVICE_0 _dev_page0[16]; 429 CONFIG_PAGE_SCSI_DEVICE_1 _dev_page1[16]; 430 uint16_t _tag_enable; 431 uint16_t _disc_enable; 432 uint16_t _update_params0; 433 uint16_t _update_params1; 434 } spi; 435#define mpt_port_page0 cfg.spi._port_page0 436#define mpt_port_page1 cfg.spi._port_page1 437#define mpt_port_page2 cfg.spi._port_page2 438#define mpt_dev_page0 cfg.spi._dev_page0 439#define mpt_dev_page1 cfg.spi._dev_page1 440#define mpt_tag_enable cfg.spi._tag_enable 441#define mpt_disc_enable cfg.spi._disc_enable 442#define mpt_update_params0 cfg.spi._update_params0 443#define mpt_update_params1 cfg.spi._update_params1 444 struct mpi_fc_cfg { 445 uint8_t nada; 446 } fc; 447 } cfg; 448 449 /* Controller Info */ 450 CONFIG_PAGE_IOC_2 * ioc_page2; 451 CONFIG_PAGE_IOC_3 * ioc_page3; 452 453 /* Raid Data */ 454 struct mpt_raid_volume* raid_volumes; 455 struct mpt_raid_disk* raid_disks; 456 u_int raid_max_volumes; 457 u_int raid_max_disks; 458 u_int raid_page0_len; 459 u_int raid_wakeup; 460 u_int raid_rescan; 461 u_int raid_resync_rate; 462 u_int raid_mwce_setting; 463 u_int raid_queue_depth; 464 u_int raid_nonopt_volumes; 465 struct proc *raid_thread; 466 struct callout raid_timer; 467 468 /* 469 * PCI Hardware info 470 */ 471 struct resource * pci_irq; /* Interrupt map for chip */ 472 void * ih; /* Interupt handle */ 473 struct mpt_pci_cfg pci_cfg; /* saved PCI conf registers */ 474 475 /* 476 * DMA Mapping Stuff 477 */ 478 struct resource * pci_reg; /* Register map for chip */ 479 int pci_mem_rid; /* Resource ID */ 480 bus_space_tag_t pci_st; /* Bus tag for registers */ 481 bus_space_handle_t pci_sh; /* Bus handle for registers */ 482 /* PIO versions of above. */ 483 int pci_pio_rid; 484 struct resource * pci_pio_reg; 485 bus_space_tag_t pci_pio_st; 486 bus_space_handle_t pci_pio_sh; 487 488 bus_dma_tag_t parent_dmat; /* DMA tag for parent PCI bus */ 489 bus_dma_tag_t reply_dmat; /* DMA tag for reply memory */ 490 bus_dmamap_t reply_dmap; /* DMA map for reply memory */ 491 uint8_t *reply; /* KVA of reply memory */ 492 bus_addr_t reply_phys; /* BusAddr of reply memory */ 493 494 bus_dma_tag_t buffer_dmat; /* DMA tag for buffers */ 495 bus_dma_tag_t request_dmat; /* DMA tag for request memroy */ 496 bus_dmamap_t request_dmap; /* DMA map for request memroy */ 497 uint8_t *request; /* KVA of Request memory */ 498 bus_addr_t request_phys; /* BusADdr of request memory */ 499 500 uint32_t max_seg_cnt; /* calculated after IOC facts */ 501 502 /* 503 * Hardware management 504 */ 505 u_int reset_cnt; 506 507 /* 508 * CAM && Software Management 509 */ 510 request_t *request_pool; 511 struct req_queue request_free_list; 512 struct req_queue request_pending_list; 513 struct req_queue request_timeout_list; 514 515 /* 516 * Deferred frame acks due to resource shortage. 517 */ 518 struct mpt_evtf_list ack_frames; 519 520 521 struct cam_sim *sim; 522 struct cam_path *path; 523 524 struct cam_sim *phydisk_sim; 525 struct cam_path *phydisk_path; 526 527 struct proc *recovery_thread; 528 request_t *tmf_req; 529 530 uint32_t sequence; /* Sequence Number */ 531 uint32_t timeouts; /* timeout count */ 532 uint32_t success; /* successes afer timeout */ 533 534 /* Opposing port in a 929 or 1030, or NULL */ 535 struct mpt_softc * mpt2; 536 537 /* FW Image management */ 538 uint32_t fw_image_size; 539 uint8_t *fw_image; 540 bus_dma_tag_t fw_dmat; /* DMA tag for firmware image */ 541 bus_dmamap_t fw_dmap; /* DMA map for firmware image */ 542 bus_addr_t fw_phys; /* BusAddr of request memory */ 543 544 /* Shutdown Event Handler. */ 545 eventhandler_tag eh; 546 547 TAILQ_ENTRY(mpt_softc) links; 548}; 549 550/***************************** Locking Primatives *****************************/ 551#if __FreeBSD_version < 500000 552#define MPT_IFLAGS INTR_TYPE_CAM 553#define MPT_LOCK(mpt) mpt_lockspl(mpt) 554#define MPT_UNLOCK(mpt) mpt_unlockspl(mpt) 555#define MPTLOCK_2_CAMLOCK MPT_UNLOCK 556#define CAMLOCK_2_MPTLOCK MPT_LOCK 557#define MPT_LOCK_SETUP(mpt) 558#define MPT_LOCK_DESTROY(mpt) 559 560static __inline void mpt_lockspl(struct mpt_softc *mpt); 561static __inline void mpt_unlockspl(struct mpt_softc *mpt); 562 563static __inline void 564mpt_lockspl(struct mpt_softc *mpt) 565{ 566 int s; 567 568 s = splcam(); 569 if (mpt->mpt_islocked++ == 0) { 570 mpt->mpt_splsaved = s; 571 } else { 572 splx(s); 573 panic("Recursed lock with mask: 0x%x\n", s); 574 } 575} 576 577static __inline void 578mpt_unlockspl(struct mpt_softc *mpt) 579{ 580 if (mpt->mpt_islocked) { 581 if (--mpt->mpt_islocked == 0) { 582 splx(mpt->mpt_splsaved); 583 } 584 } else 585 panic("Negative lock count\n"); 586} 587 588static __inline int 589mpt_sleep(struct mpt_softc *mpt, void *ident, int priority, 590 const char *wmesg, int timo) 591{ 592 int saved_cnt; 593 int saved_spl; 594 int error; 595 596 KASSERT(mpt->mpt_islocked <= 1, ("Invalid lock count on tsleep")); 597 saved_cnt = mpt->mpt_islocked; 598 saved_spl = mpt->mpt_splsaved; 599 mpt->mpt_islocked = 0; 600 error = tsleep(ident, priority, wmesg, timo); 601 KASSERT(mpt->mpt_islocked = 0, ("Invalid lock count on wakeup")); 602 mpt->mpt_islocked = saved_cnt; 603 mpt->mpt_splsaved = saved_spl; 604 return (error); 605} 606 607#else 608#ifdef LOCKING_WORKED_AS_IT_SHOULD 609#error "Shouldn't Be Here!" 610#define MPT_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE 611#define MPT_LOCK_SETUP(mpt) \ 612 mtx_init(&mpt->mpt_lock, "mpt", NULL, MTX_DEF); \ 613 mpt->mpt_locksetup = 1 614#define MPT_LOCK_DESTROY(mpt) \ 615 if (mpt->mpt_locksetup) { \ 616 mtx_destroy(&mpt->mpt_lock); \ 617 mpt->mpt_locksetup = 0; \ 618 } 619 620#define MPT_LOCK(mpt) mtx_lock(&(mpt)->mpt_lock) 621#define MPT_UNLOCK(mpt) mtx_unlock(&(mpt)->mpt_lock) 622#define MPTLOCK_2_CAMLOCK(mpt) \ 623 mtx_unlock(&(mpt)->mpt_lock); mtx_lock(&Giant) 624#define CAMLOCK_2_MPTLOCK(mpt) \ 625 mtx_unlock(&Giant); mtx_lock(&(mpt)->mpt_lock) 626#define mpt_sleep(mpt, ident, priority, wmesg, timo) \ 627 msleep(ident, &(mpt)->mpt_lock, priority, wmesg, timo) 628#else 629#define MPT_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY 630#define MPT_LOCK_SETUP(mpt) do { } while (0) 631#define MPT_LOCK_DESTROY(mpt) do { } while (0) 632#define MPT_LOCK(mpt) do { } while (0) 633#define MPT_UNLOCK(mpt) do { } while (0) 634#define MPTLOCK_2_CAMLOCK(mpt) do { } while (0) 635#define CAMLOCK_2_MPTLOCK(mpt) do { } while (0) 636#define mpt_sleep(mpt, ident, priority, wmesg, timo) \ 637 tsleep(ident, priority, wmesg, timo) 638#endif 639#endif 640 641/******************************* Register Access ******************************/ 642static __inline void mpt_write(struct mpt_softc *, size_t, uint32_t); 643static __inline uint32_t mpt_read(struct mpt_softc *, int); 644static __inline void mpt_pio_write(struct mpt_softc *, size_t, uint32_t); 645static __inline uint32_t mpt_pio_read(struct mpt_softc *, int); 646 647static __inline void 648mpt_write(struct mpt_softc *mpt, size_t offset, uint32_t val) 649{ 650 bus_space_write_4(mpt->pci_st, mpt->pci_sh, offset, val); 651} 652 653static __inline uint32_t 654mpt_read(struct mpt_softc *mpt, int offset) 655{ 656 return (bus_space_read_4(mpt->pci_st, mpt->pci_sh, offset)); 657} 658 659/* 660 * Some operations (e.g. diagnostic register writes while the ARM proccessor 661 * is disabled), must be performed using "PCI pio" operations. On non-PCI 662 * busses, these operations likely map to normal register accesses. 663 */ 664static __inline void 665mpt_pio_write(struct mpt_softc *mpt, size_t offset, uint32_t val) 666{ 667 bus_space_write_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset, val); 668} 669 670static __inline uint32_t 671mpt_pio_read(struct mpt_softc *mpt, int offset) 672{ 673 return (bus_space_read_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset)); 674} 675/*********************** Reply Frame/Request Management ***********************/ 676/* Max MPT Reply we are willing to accept (must be power of 2) */ 677#define MPT_REPLY_SIZE 256 678 679#define MPT_MAX_REQUESTS(mpt) 512 680#define MPT_REQUEST_AREA 512 681#define MPT_SENSE_SIZE 32 /* included in MPT_REQUEST_AREA */ 682#define MPT_REQ_MEM_SIZE(mpt) (MPT_MAX_REQUESTS(mpt) * MPT_REQUEST_AREA) 683 684#define MPT_CONTEXT_CB_SHIFT (16) 685#define MPT_CBI(handle) (handle >> MPT_CONTEXT_CB_SHIFT) 686#define MPT_CBI_TO_HID(cbi) ((cbi) << MPT_CONTEXT_CB_SHIFT) 687#define MPT_CONTEXT_TO_CBI(x) \ 688 (((x) >> MPT_CONTEXT_CB_SHIFT) & (MPT_NUM_REPLY_HANDLERS - 1)) 689#define MPT_CONTEXT_REQI_MASK 0xFFFF 690#define MPT_CONTEXT_TO_REQI(x) \ 691 ((x) & MPT_CONTEXT_REQI_MASK) 692 693/* 694 * Convert a 32bit physical address returned from IOC to an 695 * offset into our reply frame memory or the kvm address needed 696 * to access the data. The returned address is only the low 697 * 32 bits, so mask our base physical address accordingly. 698 */ 699#define MPT_REPLY_BADDR(x) \ 700 (x << 1) 701#define MPT_REPLY_OTOV(m, i) \ 702 ((void *)(&m->reply[i])) 703 704#define MPT_DUMP_REPLY_FRAME(mpt, reply_frame) \ 705do { \ 706 if (mpt->verbose >= MPT_PRT_DEBUG) \ 707 mpt_dump_reply_frame(mpt, reply_frame); \ 708} while(0) 709 710static __inline uint32_t mpt_pop_reply_queue(struct mpt_softc *mpt); 711static __inline void mpt_free_reply(struct mpt_softc *mpt, uint32_t ptr); 712 713/* 714 * Give the reply buffer back to the IOC after we have 715 * finished processing it. 716 */ 717static __inline void 718mpt_free_reply(struct mpt_softc *mpt, uint32_t ptr) 719{ 720 mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr); 721} 722 723/* Get a reply from the IOC */ 724static __inline uint32_t 725mpt_pop_reply_queue(struct mpt_softc *mpt) 726{ 727 return mpt_read(mpt, MPT_OFFSET_REPLY_Q); 728} 729 730void mpt_complete_request_chain(struct mpt_softc *mpt, 731 struct req_queue *chain, u_int iocstatus); 732/************************** Scatter Gather Managment **************************/ 733/* MPT_RQSL- size of request frame, in bytes */ 734#define MPT_RQSL(mpt) (mpt->request_frame_size << 2) 735 736/* MPT_NSGL- how many SG entries can fit in a request frame size */ 737#define MPT_NSGL(mpt) (MPT_RQSL(mpt) / sizeof (SGE_IO_UNION)) 738 739/* MPT_NRFM- how many request frames can fit in each request alloc we make */ 740#define MPT_NRFM(mpt) (MPT_REQUEST_AREA / MPT_RQSL(mpt)) 741 742/* 743 * MPT_NSGL_FIRST- # of SG elements that can fit after 744 * an I/O request but still within the request frame. 745 * Do this safely based upon SGE_IO_UNION. 746 * 747 * Note that the first element is *within* the SCSI request. 748 */ 749#define MPT_NSGL_FIRST(mpt) \ 750 ((MPT_RQSL(mpt) - sizeof (MSG_SCSI_IO_REQUEST) + sizeof (SGE_IO_UNION)) / \ 751 sizeof (SGE_IO_UNION)) 752 753/***************************** IOC Initialization *****************************/ 754int mpt_reset(struct mpt_softc *, int /*reinit*/); 755 756/****************************** Debugging/Logging *****************************/ 757typedef struct mpt_decode_entry { 758 char *name; 759 u_int value; 760 u_int mask; 761} mpt_decode_entry_t; 762 763int mpt_decode_value(mpt_decode_entry_t *table, u_int num_entries, 764 const char *name, u_int value, u_int *cur_column, 765 u_int wrap_point); 766 767enum { 768 MPT_PRT_ALWAYS, 769 MPT_PRT_FATAL, 770 MPT_PRT_ERROR, 771 MPT_PRT_WARN, 772 MPT_PRT_INFO, 773 MPT_PRT_DEBUG, 774 MPT_PRT_TRACE, 775 MPT_PRT_NONE=100 776}; 777 778#define mpt_lprt(mpt, level, ...) \ 779do { \ 780 if (level <= (mpt)->verbose) \ 781 mpt_prt(mpt, __VA_ARGS__); \ 782} while (0) 783 784#define mpt_lprtc(mpt, level, ...) \ 785do { \ 786 if (level <= (mpt)->debug_level) \ 787 mpt_prtc(mpt, __VA_ARGS__); \ 788} while (0) 789 790void mpt_prt(struct mpt_softc *, const char *, ...); 791void mpt_prtc(struct mpt_softc *, const char *, ...); 792 793/**************************** Unclassified Routines ***************************/ 794void mpt_send_cmd(struct mpt_softc *mpt, request_t *req); 795int mpt_recv_handshake_reply(struct mpt_softc *mpt, 796 size_t reply_len, void *reply); 797int mpt_wait_req(struct mpt_softc *mpt, request_t *req, 798 mpt_req_state_t state, mpt_req_state_t mask, 799 int sleep_ok, int time_ms); 800void mpt_enable_ints(struct mpt_softc *mpt); 801void mpt_disable_ints(struct mpt_softc *mpt); 802int mpt_attach(struct mpt_softc *mpt); 803int mpt_shutdown(struct mpt_softc *mpt); 804int mpt_detach(struct mpt_softc *mpt); 805int mpt_send_handshake_cmd(struct mpt_softc *mpt, 806 size_t len, void *cmd); 807request_t * mpt_get_request(struct mpt_softc *mpt, int sleep_ok); 808void mpt_free_request(struct mpt_softc *mpt, request_t *req); 809void mpt_intr(void *arg); 810void mpt_check_doorbell(struct mpt_softc *mpt); 811void mpt_dump_reply_frame(struct mpt_softc *mpt, 812 MSG_DEFAULT_REPLY *reply_frame); 813 814void mpt_set_config_regs(struct mpt_softc *); 815int mpt_issue_cfg_req(struct mpt_softc */*mpt*/, request_t */*req*/, 816 u_int /*Action*/, u_int /*PageVersion*/, 817 u_int /*PageLength*/, u_int /*PageNumber*/, 818 u_int /*PageType*/, uint32_t /*PageAddress*/, 819 bus_addr_t /*addr*/, bus_size_t/*len*/, 820 int /*sleep_ok*/, int /*timeout_ms*/); 821int mpt_read_cfg_header(struct mpt_softc *, int /*PageType*/, 822 int /*PageNumber*/, 823 uint32_t /*PageAddress*/, 824 CONFIG_PAGE_HEADER *, 825 int /*sleep_ok*/, int /*timeout_ms*/); 826int mpt_read_cfg_page(struct mpt_softc *t, int /*Action*/, 827 uint32_t /*PageAddress*/, 828 CONFIG_PAGE_HEADER *, size_t /*len*/, 829 int /*sleep_ok*/, int /*timeout_ms*/); 830int mpt_write_cfg_page(struct mpt_softc *, int /*Action*/, 831 uint32_t /*PageAddress*/, 832 CONFIG_PAGE_HEADER *, size_t /*len*/, 833 int /*sleep_ok*/, int /*timeout_ms*/); 834static __inline int 835mpt_read_cur_cfg_page(struct mpt_softc *mpt, uint32_t PageAddress, 836 CONFIG_PAGE_HEADER *hdr, size_t len, 837 int sleep_ok, int timeout_ms) 838{ 839 return (mpt_read_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, 840 PageAddress, hdr, len, sleep_ok, timeout_ms)); 841} 842 843static __inline int 844mpt_write_cur_cfg_page(struct mpt_softc *mpt, uint32_t PageAddress, 845 CONFIG_PAGE_HEADER *hdr, size_t len, int sleep_ok, 846 int timeout_ms) 847{ 848 return (mpt_write_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT, 849 PageAddress, hdr, len, sleep_ok, 850 timeout_ms)); 851} 852 853/* mpt_debug.c functions */ 854void mpt_print_reply(void *vmsg); 855void mpt_print_db(uint32_t mb); 856void mpt_print_config_reply(void *vmsg); 857char *mpt_ioc_diag(uint32_t diag); 858void mpt_req_state(mpt_req_state_t state); 859void mpt_print_config_request(void *vmsg); 860void mpt_print_request(void *vmsg); 861void mpt_print_scsi_io_request(MSG_SCSI_IO_REQUEST *msg); 862void mpt_dump_sgl(SGE_IO_UNION *se, int offset); 863#endif /* _MPT_H_ */ 864