11fdeb165SXin LI /*-
2f29c86f1SXin LI * HighPoint RAID Driver for FreeBSD
3f29c86f1SXin LI *
44d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
5718cf2ccSPedro F. Giffuni *
6f29c86f1SXin LI * Copyright (C) 2005-2011 HighPoint Technologies, Inc. All Rights Reserved.
71fdeb165SXin LI * All rights reserved.
81fdeb165SXin LI *
91fdeb165SXin LI * Redistribution and use in source and binary forms, with or without
101fdeb165SXin LI * modification, are permitted provided that the following conditions
111fdeb165SXin LI * are met:
121fdeb165SXin LI * 1. Redistributions of source code must retain the above copyright
131fdeb165SXin LI * notice, this list of conditions and the following disclaimer.
141fdeb165SXin LI * 2. Redistributions in binary form must reproduce the above copyright
151fdeb165SXin LI * notice, this list of conditions and the following disclaimer in the
161fdeb165SXin LI * documentation and/or other materials provided with the distribution.
171fdeb165SXin LI *
181fdeb165SXin LI * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
191fdeb165SXin LI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
201fdeb165SXin LI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
211fdeb165SXin LI * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
221fdeb165SXin LI * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
231fdeb165SXin LI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
241fdeb165SXin LI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
251fdeb165SXin LI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
261fdeb165SXin LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
271fdeb165SXin LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
281fdeb165SXin LI * SUCH DAMAGE.
291fdeb165SXin LI */
301fdeb165SXin LI
311fdeb165SXin LI #include <dev/hpt27xx/hpt27xx_config.h>
321fdeb165SXin LI
331fdeb165SXin LI #include <dev/hpt27xx/os_bsd.h>
341fdeb165SXin LI
35f29c86f1SXin LI BUS_ADDRESS get_dmapool_phy_addr(void *osext, void * dmapool_virt_addr);
36f29c86f1SXin LI
371fdeb165SXin LI /* hardware access */
os_inb(void * port)381fdeb165SXin LI HPT_U8 os_inb (void *port) { return inb((unsigned)(HPT_UPTR)port); }
os_inw(void * port)391fdeb165SXin LI HPT_U16 os_inw (void *port) { return inw((unsigned)(HPT_UPTR)port); }
os_inl(void * port)401fdeb165SXin LI HPT_U32 os_inl (void *port) { return inl((unsigned)(HPT_UPTR)port); }
411fdeb165SXin LI
os_outb(void * port,HPT_U8 value)421fdeb165SXin LI void os_outb (void *port, HPT_U8 value) { outb((unsigned)(HPT_UPTR)port, (value)); }
os_outw(void * port,HPT_U16 value)431fdeb165SXin LI void os_outw (void *port, HPT_U16 value) { outw((unsigned)(HPT_UPTR)port, (value)); }
os_outl(void * port,HPT_U32 value)441fdeb165SXin LI void os_outl (void *port, HPT_U32 value) { outl((unsigned)(HPT_UPTR)port, (value)); }
451fdeb165SXin LI
os_insw(void * port,HPT_U16 * buffer,HPT_U32 count)461fdeb165SXin LI void os_insw (void *port, HPT_U16 *buffer, HPT_U32 count)
471fdeb165SXin LI { insw((unsigned)(HPT_UPTR)port, (void *)buffer, count); }
481fdeb165SXin LI
os_outsw(void * port,HPT_U16 * buffer,HPT_U32 count)491fdeb165SXin LI void os_outsw(void *port, HPT_U16 *buffer, HPT_U32 count)
501fdeb165SXin LI { outsw((unsigned)(HPT_UPTR)port, (void *)buffer, count); }
511fdeb165SXin LI
521fdeb165SXin LI HPT_U32 __dummy_reg = 0;
531fdeb165SXin LI
541fdeb165SXin LI /* PCI configuration space */
os_pci_readb(void * osext,HPT_U8 offset)551fdeb165SXin LI HPT_U8 os_pci_readb (void *osext, HPT_U8 offset)
561fdeb165SXin LI {
571fdeb165SXin LI return pci_read_config(((PHBA)osext)->pcidev, offset, 1);
581fdeb165SXin LI }
591fdeb165SXin LI
os_pci_readw(void * osext,HPT_U8 offset)601fdeb165SXin LI HPT_U16 os_pci_readw (void *osext, HPT_U8 offset)
611fdeb165SXin LI {
621fdeb165SXin LI return pci_read_config(((PHBA)osext)->pcidev, offset, 2);
631fdeb165SXin LI }
641fdeb165SXin LI
os_pci_readl(void * osext,HPT_U8 offset)651fdeb165SXin LI HPT_U32 os_pci_readl (void *osext, HPT_U8 offset)
661fdeb165SXin LI {
671fdeb165SXin LI return pci_read_config(((PHBA)osext)->pcidev, offset, 4);
681fdeb165SXin LI }
691fdeb165SXin LI
os_pci_writeb(void * osext,HPT_U8 offset,HPT_U8 value)701fdeb165SXin LI void os_pci_writeb (void *osext, HPT_U8 offset, HPT_U8 value)
711fdeb165SXin LI {
721fdeb165SXin LI pci_write_config(((PHBA)osext)->pcidev, offset, value, 1);
731fdeb165SXin LI }
741fdeb165SXin LI
os_pci_writew(void * osext,HPT_U8 offset,HPT_U16 value)751fdeb165SXin LI void os_pci_writew (void *osext, HPT_U8 offset, HPT_U16 value)
761fdeb165SXin LI {
771fdeb165SXin LI pci_write_config(((PHBA)osext)->pcidev, offset, value, 2);
781fdeb165SXin LI }
791fdeb165SXin LI
os_pci_writel(void * osext,HPT_U8 offset,HPT_U32 value)801fdeb165SXin LI void os_pci_writel (void *osext, HPT_U8 offset, HPT_U32 value)
811fdeb165SXin LI {
821fdeb165SXin LI pci_write_config(((PHBA)osext)->pcidev, offset, value, 4);
831fdeb165SXin LI }
841fdeb165SXin LI
get_dmapool_phy_addr(void * osext,void * dmapool_virt_addr)85f29c86f1SXin LI BUS_ADDRESS get_dmapool_phy_addr(void *osext, void * dmapool_virt_addr)
86f29c86f1SXin LI {
87f29c86f1SXin LI return (BUS_ADDRESS)vtophys(dmapool_virt_addr);
88f29c86f1SXin LI }
89f29c86f1SXin LI
901fdeb165SXin LI /* PCI space access */
pcicfg_read_byte(HPT_U8 bus,HPT_U8 dev,HPT_U8 func,HPT_U8 reg)911fdeb165SXin LI HPT_U8 pcicfg_read_byte (HPT_U8 bus, HPT_U8 dev, HPT_U8 func, HPT_U8 reg)
921fdeb165SXin LI {
93*1587a9dbSJohn Baldwin return (HPT_U8)pci_cfgregread(0, bus, dev, func, reg, 1);
941fdeb165SXin LI }
pcicfg_read_dword(HPT_U8 bus,HPT_U8 dev,HPT_U8 func,HPT_U8 reg)951fdeb165SXin LI HPT_U32 pcicfg_read_dword(HPT_U8 bus, HPT_U8 dev, HPT_U8 func, HPT_U8 reg)
961fdeb165SXin LI {
97*1587a9dbSJohn Baldwin return (HPT_U32)pci_cfgregread(0, bus, dev, func, reg, 4);
981fdeb165SXin LI }
pcicfg_write_byte(HPT_U8 bus,HPT_U8 dev,HPT_U8 func,HPT_U8 reg,HPT_U8 v)991fdeb165SXin LI void pcicfg_write_byte (HPT_U8 bus, HPT_U8 dev, HPT_U8 func, HPT_U8 reg, HPT_U8 v)
1001fdeb165SXin LI {
101*1587a9dbSJohn Baldwin pci_cfgregwrite(0, bus, dev, func, reg, v, 1);
1021fdeb165SXin LI }
pcicfg_write_dword(HPT_U8 bus,HPT_U8 dev,HPT_U8 func,HPT_U8 reg,HPT_U32 v)1031fdeb165SXin LI void pcicfg_write_dword(HPT_U8 bus, HPT_U8 dev, HPT_U8 func, HPT_U8 reg, HPT_U32 v)
1041fdeb165SXin LI {
105*1587a9dbSJohn Baldwin pci_cfgregwrite(0, bus, dev, func, reg, v, 4);
1061fdeb165SXin LI }/* PCI space access */
1071fdeb165SXin LI
os_map_pci_bar(void * osext,int index,HPT_U32 offset,HPT_U32 length)1081fdeb165SXin LI void *os_map_pci_bar(
1091fdeb165SXin LI void *osext,
1101fdeb165SXin LI int index,
1111fdeb165SXin LI HPT_U32 offset,
1121fdeb165SXin LI HPT_U32 length
1131fdeb165SXin LI )
1141fdeb165SXin LI {
1151fdeb165SXin LI PHBA hba = (PHBA)osext;
1161fdeb165SXin LI HPT_U32 base;
1171fdeb165SXin LI
1181fdeb165SXin LI hba->pcibar[index].rid = 0x10 + index * 4;
1191fdeb165SXin LI base = pci_read_config(hba->pcidev, hba->pcibar[index].rid, 4);
1201fdeb165SXin LI
1211fdeb165SXin LI if (base & 1) {
1221fdeb165SXin LI hba->pcibar[index].type = SYS_RES_IOPORT;
123eff83876SJustin Hibbits hba->pcibar[index].res = bus_alloc_resource_any(hba->pcidev,
124eff83876SJustin Hibbits hba->pcibar[index].type, &hba->pcibar[index].rid, RF_ACTIVE);
1251fdeb165SXin LI hba->pcibar[index].base = (void *)(unsigned long)(base & ~0x1);
1261fdeb165SXin LI } else {
1271fdeb165SXin LI hba->pcibar[index].type = SYS_RES_MEMORY;
128eff83876SJustin Hibbits hba->pcibar[index].res = bus_alloc_resource_any(hba->pcidev,
129eff83876SJustin Hibbits hba->pcibar[index].type, &hba->pcibar[index].rid, RF_ACTIVE);
1301fdeb165SXin LI hba->pcibar[index].base = (char *)rman_get_virtual(hba->pcibar[index].res) + offset;
1311fdeb165SXin LI }
1321fdeb165SXin LI
1331fdeb165SXin LI return hba->pcibar[index].base;
1341fdeb165SXin LI }
1351fdeb165SXin LI
os_unmap_pci_bar(void * osext,void * base)1361fdeb165SXin LI void os_unmap_pci_bar(void *osext, void *base)
1371fdeb165SXin LI {
1381fdeb165SXin LI PHBA hba = (PHBA)osext;
1391fdeb165SXin LI int index;
1401fdeb165SXin LI
1411fdeb165SXin LI for (index=0; index<6; index++) {
1421fdeb165SXin LI if (hba->pcibar[index].base==base) {
1431fdeb165SXin LI bus_release_resource(hba->pcidev, hba->pcibar[index].type,
1441fdeb165SXin LI hba->pcibar[index].rid, hba->pcibar[index].res);
1451fdeb165SXin LI hba->pcibar[index].base = 0;
1461fdeb165SXin LI return;
1471fdeb165SXin LI }
1481fdeb165SXin LI }
1491fdeb165SXin LI }
1501fdeb165SXin LI
freelist_reserve(struct freelist * list,void * osext,HPT_UINT size,HPT_UINT count)1511fdeb165SXin LI void freelist_reserve(struct freelist *list, void *osext, HPT_UINT size, HPT_UINT count)
1521fdeb165SXin LI {
1531fdeb165SXin LI PVBUS_EXT vbus_ext = osext;
1541fdeb165SXin LI
1551fdeb165SXin LI if (vbus_ext->ext_type!=EXT_TYPE_VBUS)
1561fdeb165SXin LI vbus_ext = ((PHBA)osext)->vbus_ext;
1571fdeb165SXin LI
1581fdeb165SXin LI list->next = vbus_ext->freelist_head;
1591fdeb165SXin LI vbus_ext->freelist_head = list;
1601fdeb165SXin LI list->dma = 0;
1611fdeb165SXin LI list->size = size;
1621fdeb165SXin LI list->head = 0;
1631fdeb165SXin LI #if DBG
1641fdeb165SXin LI list->reserved_count =
1651fdeb165SXin LI #endif
1661fdeb165SXin LI list->count = count;
1671fdeb165SXin LI }
1681fdeb165SXin LI
freelist_get(struct freelist * list)1691fdeb165SXin LI void *freelist_get(struct freelist *list)
1701fdeb165SXin LI {
1711fdeb165SXin LI void * result;
1721fdeb165SXin LI if (list->count) {
1731fdeb165SXin LI HPT_ASSERT(list->head);
1741fdeb165SXin LI result = list->head;
1751fdeb165SXin LI list->head = *(void **)result;
1761fdeb165SXin LI list->count--;
1771fdeb165SXin LI return result;
1781fdeb165SXin LI }
1791fdeb165SXin LI return 0;
1801fdeb165SXin LI }
1811fdeb165SXin LI
freelist_put(struct freelist * list,void * p)1821fdeb165SXin LI void freelist_put(struct freelist * list, void *p)
1831fdeb165SXin LI {
1841fdeb165SXin LI HPT_ASSERT(list->dma==0);
1851fdeb165SXin LI list->count++;
1861fdeb165SXin LI *(void **)p = list->head;
1871fdeb165SXin LI list->head = p;
1881fdeb165SXin LI }
1891fdeb165SXin LI
freelist_reserve_dma(struct freelist * list,void * osext,HPT_UINT size,HPT_UINT alignment,HPT_UINT count)1901fdeb165SXin LI void freelist_reserve_dma(struct freelist *list, void *osext, HPT_UINT size, HPT_UINT alignment, HPT_UINT count)
1911fdeb165SXin LI {
1921fdeb165SXin LI PVBUS_EXT vbus_ext = osext;
1931fdeb165SXin LI
1941fdeb165SXin LI if (vbus_ext->ext_type!=EXT_TYPE_VBUS)
1951fdeb165SXin LI vbus_ext = ((PHBA)osext)->vbus_ext;
1961fdeb165SXin LI
1971fdeb165SXin LI list->next = vbus_ext->freelist_dma_head;
1981fdeb165SXin LI vbus_ext->freelist_dma_head = list;
1991fdeb165SXin LI list->dma = 1;
2001fdeb165SXin LI list->alignment = alignment;
2011fdeb165SXin LI list->size = size;
2021fdeb165SXin LI list->head = 0;
2031fdeb165SXin LI #if DBG
2041fdeb165SXin LI list->reserved_count =
2051fdeb165SXin LI #endif
2061fdeb165SXin LI list->count = count;
2071fdeb165SXin LI }
2081fdeb165SXin LI
freelist_get_dma(struct freelist * list,BUS_ADDRESS * busaddr)2091fdeb165SXin LI void *freelist_get_dma(struct freelist *list, BUS_ADDRESS *busaddr)
2101fdeb165SXin LI {
2111fdeb165SXin LI void *result;
2121fdeb165SXin LI HPT_ASSERT(list->dma);
2131fdeb165SXin LI result = freelist_get(list);
2141fdeb165SXin LI if (result)
2151fdeb165SXin LI *busaddr = *(BUS_ADDRESS *)((void **)result+1);
2161fdeb165SXin LI return result;
2171fdeb165SXin LI }
2181fdeb165SXin LI
freelist_put_dma(struct freelist * list,void * p,BUS_ADDRESS busaddr)2191fdeb165SXin LI void freelist_put_dma(struct freelist *list, void *p, BUS_ADDRESS busaddr)
2201fdeb165SXin LI {
2211fdeb165SXin LI HPT_ASSERT(list->dma);
2221fdeb165SXin LI list->count++;
2231fdeb165SXin LI *(void **)p = list->head;
2241fdeb165SXin LI *(BUS_ADDRESS *)((void **)p+1) = busaddr;
2251fdeb165SXin LI list->head = p;
2261fdeb165SXin LI }
2271fdeb165SXin LI
os_get_stamp(void)2281fdeb165SXin LI HPT_U32 os_get_stamp(void)
2291fdeb165SXin LI {
2301fdeb165SXin LI HPT_U32 stamp;
2311fdeb165SXin LI do { stamp = random(); } while (stamp==0);
2321fdeb165SXin LI return stamp;
2331fdeb165SXin LI }
2341fdeb165SXin LI
os_stallexec(HPT_U32 microseconds)2351fdeb165SXin LI void os_stallexec(HPT_U32 microseconds)
2361fdeb165SXin LI {
2371fdeb165SXin LI DELAY(microseconds);
2381fdeb165SXin LI }
2391fdeb165SXin LI
os_timer_for_ldm(void * arg)2401fdeb165SXin LI static void os_timer_for_ldm(void *arg)
2411fdeb165SXin LI {
2421fdeb165SXin LI PVBUS_EXT vbus_ext = (PVBUS_EXT)arg;
2431fdeb165SXin LI ldm_on_timer((PVBUS)vbus_ext->vbus);
2441fdeb165SXin LI }
2451fdeb165SXin LI
os_request_timer(void * osext,HPT_U32 interval)2461fdeb165SXin LI void os_request_timer(void * osext, HPT_U32 interval)
2471fdeb165SXin LI {
2481fdeb165SXin LI PVBUS_EXT vbus_ext = osext;
2491fdeb165SXin LI
2501fdeb165SXin LI HPT_ASSERT(vbus_ext->ext_type==EXT_TYPE_VBUS);
25185c9dd9dSSteven Hartland callout_reset_sbt(&vbus_ext->timer, SBT_1US * interval, 0,
25285c9dd9dSSteven Hartland os_timer_for_ldm, vbus_ext, 0);
2531fdeb165SXin LI }
2541fdeb165SXin LI
os_query_time(void)2551fdeb165SXin LI HPT_TIME os_query_time(void)
2561fdeb165SXin LI {
2571fdeb165SXin LI return ticks * (1000000 / hz);
2581fdeb165SXin LI }
2591fdeb165SXin LI
os_schedule_task(void * osext,OSM_TASK * task)2601fdeb165SXin LI void os_schedule_task(void *osext, OSM_TASK *task)
2611fdeb165SXin LI {
2621fdeb165SXin LI PVBUS_EXT vbus_ext = osext;
2631fdeb165SXin LI
2641fdeb165SXin LI HPT_ASSERT(task->next==0);
2651fdeb165SXin LI
2661fdeb165SXin LI if (vbus_ext->tasks==0)
2671fdeb165SXin LI vbus_ext->tasks = task;
2681fdeb165SXin LI else {
2691fdeb165SXin LI OSM_TASK *t = vbus_ext->tasks;
2701fdeb165SXin LI while (t->next) t = t->next;
2711fdeb165SXin LI t->next = task;
2721fdeb165SXin LI }
2731fdeb165SXin LI
2741fdeb165SXin LI if (vbus_ext->worker.ta_context)
2751fdeb165SXin LI TASK_ENQUEUE(&vbus_ext->worker);
2761fdeb165SXin LI }
2771fdeb165SXin LI
os_revalidate_device(void * osext,int id)2781fdeb165SXin LI int os_revalidate_device(void *osext, int id)
2791fdeb165SXin LI {
2801fdeb165SXin LI
2811fdeb165SXin LI return 0;
2821fdeb165SXin LI }
2831fdeb165SXin LI
os_query_remove_device(void * osext,int id)2841fdeb165SXin LI int os_query_remove_device(void *osext, int id)
2851fdeb165SXin LI {
2867634a04bSXin LI return 0;
2871fdeb165SXin LI }
2881fdeb165SXin LI
os_get_vbus_seq(void * osext)2891fdeb165SXin LI HPT_U8 os_get_vbus_seq(void *osext)
2901fdeb165SXin LI {
2911fdeb165SXin LI return ((PVBUS_EXT)osext)->sim->path_id;
2921fdeb165SXin LI }
2931fdeb165SXin LI
os_printk(char * fmt,...)2941fdeb165SXin LI int os_printk(char *fmt, ...)
2951fdeb165SXin LI {
2961fdeb165SXin LI va_list args;
2971fdeb165SXin LI static char buf[512];
2981fdeb165SXin LI
2991fdeb165SXin LI va_start(args, fmt);
3001fdeb165SXin LI vsnprintf(buf, sizeof(buf), fmt, args);
3011fdeb165SXin LI va_end(args);
3021fdeb165SXin LI return printf("%s: %s\n", driver_name, buf);
3031fdeb165SXin LI }
3041fdeb165SXin LI
3051fdeb165SXin LI #if DBG
os_check_stack(const char * location,int size)3061fdeb165SXin LI void os_check_stack(const char *location, int size){}
3071fdeb165SXin LI
__os_dbgbreak(const char * file,int line)3081fdeb165SXin LI void __os_dbgbreak(const char *file, int line)
3091fdeb165SXin LI {
3101fdeb165SXin LI printf("*** break at %s:%d ***", file, line);
3111fdeb165SXin LI while (1);
3121fdeb165SXin LI }
3131fdeb165SXin LI
3141fdeb165SXin LI int hpt_dbg_level = 1;
3151fdeb165SXin LI #endif
316