10Sduke/* 26078Salanb * Copyright (c) HighPoint Technologies, Inc. 30Sduke * All rights reserved. 40Sduke * 50Sduke * Redistribution and use in source and binary forms, with or without 60Sduke * modification, are permitted provided that the following conditions 70Sduke * are met: 80Sduke * 1. Redistributions of source code must retain the above copyright 90Sduke * notice, this list of conditions and the following disclaimer. 100Sduke * 2. Redistributions in binary form must reproduce the above copyright 110Sduke * notice, this list of conditions and the following disclaimer in the 120Sduke * documentation and/or other materials provided with the distribution. 130Sduke * 140Sduke * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 150Sduke * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 160Sduke * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 170Sduke * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 180Sduke * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 192362Sohair * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 202362Sohair * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 212362Sohair * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 220Sduke * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 230Sduke * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 240Sduke * SUCH DAMAGE. 256078Salanb * 260Sduke * $FreeBSD$ 272546Salanb */ 2811822Sdarcy#include <dev/hptrr/hptrr_config.h> 290Sduke/* 300Sduke * $Id: ldm.h,v 1.69 2007/11/22 07:31:55 gmm Exp $ 310Sduke * Copyright (C) 2004-2005 HighPoint Technologies, Inc. All rights reserved. 320Sduke */ 330Sduke#ifndef _HPT_LDM_H_ 346078Salanb#define _HPT_LDM_H_ 356078Salanb 366078Salanb#define VERMAGIC_LDM 69 376078Salanb 380Sduke#if defined(__cplusplus) 390Sdukeextern "C" { 400Sduke#endif 410Sduke 420Sduke 430Sduke#define __hpt_set_ver(x, v1, v2, v3, v4, v5) x ## _R_ ## v1 ## _ ## v2 ## _ ## v3 ## _ ## v4 ## _ ## v5 440Sduke#define _hpt_set_ver(x, v1, v2, v3, v4, v5) __hpt_set_ver(x, v1, v2, v3, v4, v5) 450Sduke#define hpt_set_ver(x) _hpt_set_ver(x, VERMAGIC_OSM, VERMAGIC_HIM, VERMAGIC_LDM, VERMAGIC_ARRAY, MAX_MEMBERS) 460Sduke 476078Salanb#define ldm_register_him hpt_set_ver(ldm_register_him) 480Sduke#define ldm_register_vdev_class hpt_set_ver(ldm_register_vdev_class) 490Sduke#define ldm_alloc_cmds hpt_set_ver(ldm_alloc_cmds) 500Sduke 510Sduke 520Sduke#ifndef HPT_INTERFACE_VERSION 530Sduke#define HPT_INTERFACE_VERSION 0x02000001 540Sduke#endif 550Sduke 560Sduke#define MAX_PARTITIONS_PER_DISK 4 570Sduke#if defined(__MAX_PARTITIONS_PER_DISK) && MAX_PARTITIONS_PER_DISK > __MAX_PARTITIONS_PER_DISK 580Sduke#error "Please redefine MAX_PARTITIONS_PER_DISK!!!" 590Sduke#endif 606078Salanb 616078Salanb#define MAX(a,b) (((a)>(b))?(a):(b)) 626078Salanb#define MIN(a,b) (((a)<(b))?(a):(b)) 636078Salanb 646078Salanb 656078Salanbtypedef char check_HPT_TIME_is_unsigned[ (HPT_TIME)(-1) > 0 ? 1 : -1 ]; 666078Salanb 676078Salanb#define hpt_time_after_eq(a, b) ((long)(a) - (long)(b) >= 0) 686078Salanb#define hpt_time_after(a, b) ((long)(a) - (long)(b) > 0) 696078Salanb 706078Salanb 716078Salanb 726078Salanbstruct freelist { 736078Salanb int dma; 746078Salanb HPT_UINT alignment; 750Sduke HPT_UINT count; 760Sduke HPT_UINT size; 770Sduke void * head; 780Sduke struct freelist *next; 790Sduke#if DBG 800Sduke char *tag; 810Sduke HPT_UINT reserved_count; 820Sduke #define freelist_debug_tag(list, _tag) (list)->tag = _tag 830Sduke#else 840Sduke #define freelist_debug_tag(list, _tag) 850Sduke#endif 860Sduke}; 870Sduke 880Sduke 890Sdukevoid freelist_reserve(struct freelist *list, void *osext, HPT_UINT size, HPT_UINT count); 900Sduke 910Sdukevoid *freelist_get(struct freelist *); 926078Salanbvoid freelist_put(struct freelist *, void *p); 936078Salanb 946078Salanbvoid freelist_reserve_dma(struct freelist *list, void *osext, HPT_UINT size, HPT_UINT alignment, HPT_UINT count); 956078Salanbvoid *freelist_get_dma(struct freelist *, BUS_ADDRESS *busaddr); 966078Salanbvoid freelist_put_dma(struct freelist *, void *p, BUS_ADDRESS busaddr); 976078Salanb 986078Salanb 996078Salanb#define freelist_reserve_with_tag(list, osext, size, count) \ 1000Sduke do {\ 1010Sduke freelist_debug_tag(list, #list " at " __FILE__);\ 1020Sduke freelist_reserve(list, osext, size, count);\ 1030Sduke }while(0) 1040Sduke 1050Sduke#define freelist_reserve_dma_with_tag(list, osext, size, alignment, count) \ 1060Sduke do {\ 1076078Salanb freelist_debug_tag(list, #list " at " __FILE__);\ 1086078Salanb freelist_reserve_dma(list, osext, size, alignment, count);\ 1096078Salanb }while(0) 1106078Salanb 1110Sdukestruct lock_request { 1120Sduke HPT_U64 start, end; 1130Sduke struct lock_request *next; 1140Sduke struct list_head waiters; /* blocked commands */ 1150Sduke struct tq_item callback; 1160Sduke int lock_cc; 1170Sduke}; 1186078Salanb 1190Sduke#define INIT_LOCK_REQUEST(req, _start, _end, _cb, _arg, _cc) \ 1200Sduke do {\ 1210Sduke (req)->next = 0;\ 1226078Salanb (req)->start = _start;\ 1236078Salanb (req)->end = _end;\ 1240Sduke INIT_TQ_ITEM(&(req)->callback, _cb, _arg);\ 1256078Salanb INIT_LIST_HEAD(&(req)->waiters);\ 1266078Salanb (req)->lock_cc = _cc;\ 1276078Salanb } while (0) 1280Sduke 1296078Salanbstruct task_queue { 1306078Salanb struct tq_item *head, *tail; 1310Sduke}; 1326078Salanb 1336078Salanb#define TQ_EMPTY(tq) ((tq)->head==0) 1346078Salanb 1356078Salanbstruct dmapool_order { 1360Sduke HPT_UINT npages; 1376078Salanb struct tq_item wakeup_fn; 1386078Salanb struct dmapool_order *next; 1396078Salanb}; 1406078Salanb 1416078Salanbstruct dmapool_client { 1426078Salanb void * handle; 1430Sduke HPT_UINT (*shrink)(void *handle, HPT_UINT npages); 1440Sduke int (*resume)(void *handle); 1450Sduke struct dmapool_client *next; 1460Sduke}; 1470Sduke 1480Sduketypedef struct _VBUS * PVBUS; 1490Sduketypedef struct _VDEV * PVDEV; 1500Sduke 1510Sduke 1526078Salanbvoid dmapool_register_client(PVBUS vbus, struct dmapool_client *client); 1530Sduke 1540Sduke 1550Sdukevoid dmapool_active(PVBUS vbus); 1566078Salanb 1576078Salanb/* return 0 if the request is immediately satisfied, non-zero otherwise. */ 1586078Salanbint dmapool_make_order(PVBUS vbus, struct dmapool_order *order); 1596078Salanb 1606078Salanb 1616078Salanbvoid *dmapool_get_page(PVBUS vbus, BUS_ADDRESS *busaddr); 1620Sdukevoid *dmapool_get_page_at(PVBUS vbus, void *p, BUS_ADDRESS *busaddr); 1636078Salanbvoid dmapool_put_page(PVBUS vbus, void *p, BUS_ADDRESS busaddr); 1646078Salanbvoid dmapool_init(PVBUS vbus); 1656078SalanbHPT_UINT dmapool_max_class_pages(PVBUS vbus); 1660Sduke 1676078Salanb 1686078Salanbstruct timer_call { 1696078Salanb HPT_U32 interval; /*microseconds*/ 1706078Salanb HPT_TIME expire_time; /*microseconds*/ 1716078Salanb void (*proc)(void * arg); 1726078Salanb void * arg; 1730Sduke struct timer_call ** pprev; 1740Sduke struct timer_call * next; 1750Sduke}; 1760Sduke 1770Sduke#define ldm_init_timer(timer) do { (timer)->next=0; (timer)->pprev=0; } while (0) 1786078Salanb 1790Sduke#define INIT_TIMER_CALL(timer, _interval, _proc, _arg) \ 1800Sduke do { \ 1810Sduke HPT_ASSERT((timer)->next==0 && (timer)->pprev==0);\ 1826078Salanb (timer)->interval = _interval;\ 1836078Salanb (timer)->proc = _proc;\ 1846078Salanb (timer)->arg = _arg;\ 1856078Salanb } while(0) 1866078Salanb 1876078Salanbvoid ldm_request_timer(PVBUS vbus, struct timer_call * tc); 1886078Salanbvoid ldm_remove_timer(PVBUS vbus, struct timer_call * tc); 1896078Salanbvoid ldm_on_timer(PVBUS vbus); 1906078Salanb 1916078Salanb 1926078Salanbtypedef struct _LDM_ADAPTER 1936078Salanb{ 1946078Salanb struct _LDM_ADAPTER *next; 1956078Salanb HIM *him; 1966078Salanb void *him_handle; 1976078Salanb PVBUS vbus; 1986078Salanb struct freelist freelist_dev; 1996078Salanb struct freelist freelist_plugged_dpc; 2006078Salanb HPT_BOOL master; 2016078Salanb} 2026078SalanbLDM_ADAPTER, *PLDM_ADAPTER; 2036078Salanb 2046078Salanbtypedef struct _IOCTL_ARG 2056078Salanb{ 2066078Salanb struct list_head link; 2076078Salanb PVBUS vbus; 2086078Salanb HPT_U32 dwIoControlCode; 2096078Salanb HPT_U32 nInBufferSize; 2100Sduke HPT_U32 nOutBufferSize; 2116078Salanb void * lpInBuffer; 2126078Salanb void * lpOutBuffer; 2136078Salanb HPT_U32 *lpBytesReturned; 2146078Salanb void * ioctl_cmnd; 2156078Salanb void (* done)(struct _IOCTL_ARG *); 2166078Salanb int result; /* HPT_IOCTL_RESULT_ */ 2176078Salanb struct tq_item dpc; 2186078Salanb} IOCTL_ARG; 2196078Salanb 2206078Salanb#define HPT_IOCTL_RESULT_OK 0 2216078Salanb#define HPT_IOCTL_RESULT_FAILED (-1) 2226078Salanb#define HPT_IOCTL_RESULT_INVALID (-2) 2236078Salanb#define HPT_IOCTL_RESULT_RETRY (-3) 2246078Salanb#define HPT_IOCTL_RESULT_WRONG_VBUS (-4) 2256078Salanb 2266078Salanbvoid ldm_ioctl( PVBUS vbus, IOCTL_ARG *IAPnt); 2276078SalanbHPT_U32 ldm_get_device_id(PVDEV vd); /* for ioctl */ 2286078Salanbvoid ldm_set_rebuild_priority(PVBUS vbus, int priority); 2296078Salanbvoid ldm_set_autorebuild(PVBUS vbus, int enable); 2306078Salanbvoid ldm_set_spindown_disks_timeout(PVBUS vbus, HPT_U8 timeout); 2316078Salanb 2326078Salanb#ifndef __HPT_RAW_LBA 2336078Salanb#define __HPT_RAW_LBA HPT_RAW_LBA 2346078Salanb#endif 2356078Salanb 2366078Salanb#include <dev/hptrr/array.h> 2376078Salanb 2386078Salanbtypedef struct hpt_raw_disk 2396078Salanb{ 2400Sduke#ifdef SUPPORT_ARRAY 2410Sduke PRAW_PARTITION raw_part_list; 2420Sduke __HPT_RAW_LBA max_available_capacity; 2436078Salanb __HPT_RAW_LBA total_available_capacity; 2446078Salanb#endif 2456078Salanb __HPT_RAW_LBA real_capacity; 2466078Salanb __HPT_RAW_LBA head_position; 2476078Salanb 2486078Salanb HPT_U16 max_sectors_per_cmd; 2496078Salanb HPT_U8 max_queue_depth; 2506078Salanb HPT_U8 user_select_mode; 2516078Salanb 2526078Salanb HPT_UINT uninitialized : 1; 2536078Salanb HPT_UINT legacy_disk : 1; 2546078Salanb HPT_UINT is_spare : 1; 2556078Salanb HPT_UINT v3_format : 1; 2566078Salanb HPT_UINT need_sync : 1; 2576078Salanb HPT_UINT temp_spare : 1; 2586078Salanb HPT_UINT need_check_array : 1; 2596078Salanb HPT_UINT df_user_mode_set: 1; 2606078Salanb 2616078Salanb HPT_UINT df_read_ahead_set: 1; 2626078Salanb HPT_UINT enable_read_ahead : 1; 2636078Salanb HPT_UINT df_write_cache_set: 1; 2646078Salanb HPT_UINT enable_write_cache : 1; 2656078Salanb HPT_UINT df_tcq_set: 1; 2666078Salanb HPT_UINT enable_tcq : 1; 2676078Salanb HPT_UINT df_ncq_set: 1; 2686078Salanb HPT_UINT enable_ncq : 1; 2696078Salanb 2706078Salanb HIM * him; 2716078Salanb int index; 2726078Salanb PLDM_ADAPTER adapter; 2736078Salanb void * phy_dev; 2746078Salanb PIDENTIFY_DATA2 identify_data; 2756078Salanb char model[40]; 2766078Salanb 2776078Salanb struct tq_item reset_dpc; 2786078Salanb int reset_pending; 2796078Salanb 2806078Salanb struct tq_item fail_dpc; 2816078Salanb int fail_pending; 2826078Salanb} 2836078SalanbHPT_RAW_DISK, *PHPT_RAW_DISK; 2846078Salanb 2856078Salanbstruct vdev_class 2866078Salanb{ 2876078Salanb struct vdev_class *next; 2886078Salanb 2896078Salanb HPT_U8 __type; 2906078Salanb HPT_U8 stripped; /* RAID0,3,5,6 */ 2916078Salanb HPT_U8 redundancy; /* RAID1-1, RAID3/5-1, RAID6-2 */ 2926078Salanb HPT_U8 must_init; /* RAID3,5,6 */ 2936078Salanb HPT_U8 docache; 2946078Salanb 2956078Salanb HPT_UINT vbus_ext_size; 2966078Salanb HPT_UINT vbus_ext_offset; /* used by LDM */ 2976078Salanb HPT_UINT dev_ext_size; 2986078Salanb HPT_UINT cmd_ext_size; 2996078Salanb 3006078Salanb 3016078Salanb void (*get_mem_info)(PVBUS vbus, void *osext, int phydev_count); 3026078Salanb void (*queue_cmd)(PCOMMAND cmd); 3036078Salanb void (*member_failed)(struct _VDEV * vd); 3046078Salanb 3056078Salanb 3066078Salanb void (*initialize)(PVBUS vbus); 3070Sduke void (*release)(PVBUS vbus); 308 int (*add)(PVDEV vd); 309 void (*remove)(PVDEV vd); 310 void (*reset)(PVDEV vd); 311 void (*sync_stamp)(PVDEV vd); 312 int (*support_type)(int type); 313}; 314 315 316#define VDEV_CLASS_CONSTRUCTOR(type, prefix) { \ 317 0, \ 318 type, \ 319 prefix ## _stripped, \ 320 prefix ## _redundancy, \ 321 prefix ## _must_init, \ 322 0, \ 323 prefix ## _vbus_ext_size, \ 324 0, \ 325 prefix ## _dev_ext_size, \ 326 prefix ## _cmd_ext_size, \ 327 prefix ## _get_mem_info, \ 328 prefix ## _queue_cmd, \ 329 prefix ## _member_failed, \ 330 prefix ## _initialize, \ 331 prefix ## _release, \ 332 prefix ## _add, \ 333 prefix ## _remove, \ 334 prefix ## _reset, \ 335 prefix ## _sync_stamp, \ 336 0 \ 337} 338 339#define VD_RAW 1 340#define VD_PARTITION 4 341 342#define mIsArray(vdev_type) ((vdev_type)>VD_PARTITION) 343 344#define VD_RAID0 5 345#define VD_RAID1 6 346#define VD_JBOD 7 347#define VD_RAID5 8 348#define VD_RAID6 9 349#define VD_RAID3 10 350#define VD_RAID4 11 351#define VD_RAID1E 12 352 353#define MAX_VD_TYPE_ID 12 354 355struct vdev_class *ldm_find_vdev_class(HPT_U8 type); 356 357typedef struct _VDEV { 358 PVBUS vbus; 359 struct vdev_class *Class; 360 HPT_U8 type; 361 PVDEV parent; 362 void * ext; 363 HPT_U64 capacity; 364 int target_id; 365 HPT_UINT cmds_per_request; 366 367 union { 368#ifdef SUPPORT_ARRAY 369 HPT_ARRAY array; 370 HPT_PARTITION partition; 371#endif 372 HPT_RAW_DISK raw; 373 } u; 374 375 HPT_U8 vf_online : 1; 376 HPT_U8 vf_bootmark : 1; 377 HPT_U8 vf_bootable : 1; 378 HPT_U8 vf_resetting: 1; 379 HPT_U8 vf_quiesced: 1; 380 HPT_U8 vf_clslock: 1; 381 382 HPT_U8 cache_policy; /* see CACHE_POLICY_* */ 383 384 HPT_UINT cq_len; 385 HPT_UINT cmds_sent; 386 387 struct list_head link; 388 struct list_head cq_wait_send; 389 struct list_head cq_sent; 390 391 int cq_priority; 392 struct list_head cq_wait_lock; 393 struct lock_request *locks_granted; 394 struct lock_request *locks_wait; 395 HPT_U32 ioctl_id; 396 void * cc_ext; 397} 398VDEV; 399 400#define CACHE_POLICY_NONE 0 401#define CACHE_POLICY_WRITE_THROUGH 1 402#define CACHE_POLICY_WRITE_BACK 2 403 404 405extern HIM *him_list; 406 407 408void ldm_register_him(PHIM him); 409 410 411void ldm_register_vdev_class(struct vdev_class *Class); 412 413 414HPT_BOOL ldm_register_adapter(PLDM_ADAPTER adapter); 415 416 417int init_config(void); 418 419HPT_UINT ldm_get_vbus_size(void); 420 421 422void ldm_create_vbus(PVBUS vbus, void *osext); 423 424 425void ldm_get_mem_info(PVBUS vbus, void *osext); 426 427 428void *ldm_get_vbus_ext(PVBUS vbus, struct vdev_class *Class); 429 430 431PVBUS ldm_get_next_vbus(PVBUS vbus, void **posext); 432 433#define ldm_for_each_vbus(vbus, vbus_ext) \ 434 for (vbus = ldm_get_next_vbus(0, (void **)(void *)&vbus_ext); vbus; \ 435 vbus = ldm_get_next_vbus(vbus, (void **)(void *)&vbus_ext)) 436 437 438void ldm_initialize_vbus_async(PVBUS vbus, PLDM_ADAPTER master_adapter, void (*done)(void *osext)); 439 440/* ldm_initialize_vbus is deprecated since it will hold the CPU too long. */ 441#define ldm_initialize_vbus(vbus, adapter) ldm_initialize_vbus_async(vbus, adapter, 0) 442 443 444void ldm_release_vbus(PVBUS vbus); 445 446PVDEV ldm_create_vdev(PVBUS vbus, HPT_U8 type); 447void ldm_release_vdev(PVDEV vd); 448 449PVDEV ldm_find_target(PVBUS vbus, int id); 450PVDEV ldm_find_stamp(PVBUS vbus, HPT_U32 stamp, int seq); 451 452 453PCOMMAND ldm_alloc_cmds(PVBUS vbus, HPT_UINT cnt); 454void ldm_free_cmds(PCOMMAND cmd); 455 456HPT_UINT ldm_get_cmd_size(void); 457PCOMMAND ldm_alloc_cmds_from_list(PVBUS vbus, struct freelist *list, HPT_UINT cnt); 458void ldm_free_cmds_to_list(struct freelist *list, PCOMMAND cmd); 459 460 461PCOMMAND __ldm_alloc_cmd(struct freelist *list); 462 463#ifdef OS_SUPPORT_TASK 464#define CMD_SET_PRIORITY(cmd, pri) cmd->priority = (pri) 465#else 466#define CMD_SET_PRIORITY(cmd, pri) 467#endif 468 469 470#define CMD_GROUP_GET(grp, cmd) \ 471 do {\ 472 grp->grplist->count++;\ 473 cmd = __ldm_alloc_cmd(grp->grplist);\ 474 cmd->vbus = grp->vbus;\ 475 cmd->grplist = grp->grplist;\ 476 CMD_SET_PRIORITY(cmd, grp->priority);\ 477 } while(0) 478 479#define CMD_GROUP_PUT(grp, cmd) \ 480 do {\ 481 freelist_put(grp->grplist, cmd);\ 482 grp->grplist->count--;\ 483 } while (0) 484 485 486 487 488void ldm_queue_cmd(PCOMMAND cmd); 489void vdev_queue_cmd(PCOMMAND cmd); 490void ldm_finish_cmd(PCOMMAND cmd); 491 492 493int ldm_acquire_lock(PVDEV vd, struct lock_request *req); 494void ldm_release_lock(PVDEV vd, struct lock_request *req); 495 496void ldm_queue_task(struct task_queue *tq, struct tq_item *t); 497void ldm_queue_vbus_dpc(PVBUS vbus, struct tq_item *t); 498 499HPT_BOOL ldm_intr(PVBUS vbus); 500void ldm_run(PVBUS vbus); 501int ldm_idle(PVBUS vbus); 502 503 504int ldm_reset_vbus(PVBUS vbus); 505 506 507void ldm_suspend(PVBUS vbus); 508void ldm_resume(PVBUS vbus); 509void ldm_shutdown(PVBUS vbus);/*shutdown all the controllers*/ 510 511 512#define HIM_EVENT_DEVICE_REMOVED 1 513#define HIM_EVENT_DEVICE_PLUGGED 2 514#define HIM_EVENT_DEVICE_ERROR 3 515#define HIM_EVENT_RESET_REQUIRED 4 516#define HIM_EVENT_QUIESCE_DEVICE 5 517#define HIM_EVENT_UNQUIESCE_DEVICE 6 518#define HIM_EVENT_CONFIG_CHANGED 7 519 520void ldm_event_notify(HPT_U32 event, void *arg1, void *arg2); 521 522void log_sector_repair(PVDEV vd, int success, HPT_LBA lba, HPT_U16 nsectors); 523 524void ldm_register_device(PVDEV vd); 525void ldm_unregister_device(PVDEV vd); 526 527PVBUS him_handle_to_vbus(void * him_handle); 528void ldm_ide_fixstring (HPT_U8 *s, const int bytecount); 529#if defined(__cplusplus) 530} 531#endif 532#endif 533