dpt_pci.c revision 32801
132801Sjulian/*
232801Sjulian *       Copyright (c) 1997 by Simon Shapiro
332801Sjulian *       All Rights Reserved
432801Sjulian *
532801Sjulian * Redistribution and use in source and binary forms, with or without
632801Sjulian * modification, are permitted provided that the following conditions
732801Sjulian * are met:
832801Sjulian * 1. Redistributions of source code must retain the above copyright
932801Sjulian *    notice, this list of conditions, and the following disclaimer,
1032801Sjulian *    without modification, immediately at the beginning of the file.
1132801Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1232801Sjulian *    notice, this list of conditions and the following disclaimer in the
1332801Sjulian *    documentation and/or other materials provided with the distribution.
1432801Sjulian * 3. The name of the author may not be used to endorse or promote products
1532801Sjulian *    derived from this software without specific prior written permission.
1632801Sjulian *
1732801Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1832801Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1932801Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2032801Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
2132801Sjulian * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2232801Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2332801Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2432801Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2532801Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2632801Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2732801Sjulian * SUCH DAMAGE.
2832801Sjulian *
2932801Sjulian */
3032801Sjulian
3132801Sjulian/*
3232801Sjulian *  dptpci.c:  Pseudo device drivers for DPT on PCI on FreeBSD
3332801Sjulian *
3432801Sjulian *  caveats:   We may need an eisa and an isa files too
3532801Sjulian */
3632801Sjulian
3732801Sjulian#ident "$Id: dpt_pci.c,v 1.10 1998/01/21 04:38:47 ShimonR Exp $"
3832801Sjulian
3932801Sjulian#include "opt_dpt.h"
4032801Sjulian#include <pci.h>
4132801Sjulian
4232801Sjulian#include <sys/param.h>
4332801Sjulian#include <sys/systm.h>
4432801Sjulian#include <sys/malloc.h>
4532801Sjulian#include <sys/buf.h>
4632801Sjulian#include <sys/proc.h>
4732801Sjulian#include <sys/kernel.h>
4832801Sjulian
4932801Sjulian#include <scsi/scsi_all.h>
5032801Sjulian#include <scsi/scsi_message.h>
5132801Sjulian#include <scsi/scsiconf.h>
5232801Sjulian
5332801Sjulian#include <pci/pcireg.h>
5432801Sjulian#include <sys/queue.h>
5532801Sjulian#include <pci/pcivar.h>
5632801Sjulian
5732801Sjulian#include <sys/dpt.h>
5832801Sjulian#include <pci/dpt_pci.h>
5932801Sjulian
6032801Sjulian#include <machine/clock.h>
6132801Sjulian
6232801Sjulian#include <vm/vm.h>
6332801Sjulian#include <vm/vm_param.h>
6432801Sjulian#include <vm/pmap.h>
6532801Sjulian
6632801Sjulian#define PCI_BASEADR0  PCI_MAP_REG_START  /* I/O Address */
6732801Sjulian#define PCI_BASEADR1  PCI_MAP_REG_START + 4  /* Mem I/O Address */
6832801Sjulian
6932801Sjulian#define ISA_PRIMARY_WD_ADDRESS    0x1f8
7032801Sjulian
7132801Sjulian/* Global variables */
7232801Sjulian
7332801Sjulianint dpt_controllers_present = 0;
7432801Sjulian
7532801Sjulian/* Function Prototypes */
7632801Sjulian
7732801Sjulianchar    *dpt_pci_probe(pcici_t tag, pcidi_t type);
7832801Sjulianvoid     dpt_pci_attach(pcici_t config_id, int unit);
7932801Sjulianint      dpt_pci_shutdown(int foo, int bar);
8032801Sjulian
8132801Sjulianextern struct cdevsw dpt_cdevsw;
8232801Sjulian
8332801Sjulianstatic  struct pci_device dpt_pci_driver =
8432801Sjulian{
8532801Sjulian    "dpt",
8632801Sjulian    dpt_pci_probe,
8732801Sjulian    dpt_pci_attach,
8832801Sjulian    &dpt_unit,
8932801Sjulian    dpt_pci_shutdown
9032801Sjulian};
9132801Sjulian
9232801SjulianDATA_SET(pcidevice_set, dpt_pci_driver);
9332801Sjulian
9432801Sjulian/*
9532801Sjulian * Probe the PCI device.
9632801Sjulian * Some of this work will have to be duplicated in _attach
9732801Sjulian * because we do not know for sure how the two relate.
9832801Sjulian */
9932801Sjulian
10032801Sjulianchar   *
10132801Sjuliandpt_pci_probe(pcici_t tag, pcidi_t type)
10232801Sjulian{
10332801Sjulian    static char silly_message[64];
10432801Sjulian    static int  already_announced = 0;
10532801Sjulian
10632801Sjulian    u_int32_t  dpt_id;
10732801Sjulian    u_int32_t command;
10832801Sjulian    u_int32_t class;
10932801Sjulian
11032801Sjulian#define pci_device  tag.cfg2.port
11132801Sjulian#define pci_bus     tag.cfg2.forward
11232801Sjulian#define pci_index   tag.cfg2.enable
11332801Sjulian
11432801Sjulian#ifndef PCI_COMMAND_MASTER_ENABLE
11532801Sjulian#define PCI_COMMAND_MASTER_ENABLE 0x00000004
11632801Sjulian#endif
11732801Sjulian
11832801Sjulian#ifndef PCI_SUBCLASS_MASS_STORAGE_SCSI
11932801Sjulian#define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00000000
12032801Sjulian#endif
12132801Sjulian
12232801Sjulian    if ( !already_announced ) {
12332801Sjulian	printf("DPT:  PCI SCSI HBA Driver, version %d.%d.%d\n",
12432801Sjulian	       DPT_RELEASE, DPT_VERSION, DPT_PATCH);
12532801Sjulian	++already_announced;
12632801Sjulian    }
12732801Sjulian
12832801Sjulian    if ((dpt_id = (type & 0xffff0000) >> 16) == DPT_DEVICE_ID) {
12932801Sjulian	/* This one appears to belong to us, but what is it? */
13032801Sjulian	class = pci_conf_read(tag, PCI_CLASS_REG);
13132801Sjulian	if (((class & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE) &&
13232801Sjulian	    ((class & PCI_SUBCLASS_MASK) == PCI_SUBCLASS_MASS_STORAGE_SCSI) ) {
13332801Sjulian	    /* It is a SCSI storage device.  How do talk to it? */
13432801Sjulian	    command = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
13532801Sjulian#ifdef DPT_ALLOW_MEMIO
13632801Sjulian	    if ( ((command & PCI_COMMAND_IO_ENABLE) == 0)
13732801Sjulian		 && ((command & PCI_COMMAND_MEM_ENABLE) == 0) )
13832801Sjulian#else
13932801Sjulian	    if ( ((command & PCI_COMMAND_IO_ENABLE) == 0) )
14032801Sjulian#endif /* DPT_ALLOW_MEMIO */
14132801Sjulian		{
14232801Sjulian		    printf("DPT:  Cannot map the controller registers :-(\n");
14332801Sjulian		    return(NULL);
14432801Sjulian		}
14532801Sjulian	} else {
14632801Sjulian	    printf("DPT:  Device is not Mass Storage, nor SCSI controller\n");
14732801Sjulian	    return(NULL);
14832801Sjulian	}
14932801Sjulian
15032801Sjulian	command = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
15132801Sjulian	if ( (command & PCI_COMMAND_MASTER_ENABLE) == 0 ) {
15232801Sjulian	    printf("DPT:  Cannot be functional without BUSMASTER. :-(\n");
15332801Sjulian	    return (NULL);
15432801Sjulian	}
15532801Sjulian
15632801Sjulian#ifdef DPT_DEBUG_PCI
15732801Sjulian	printf("DPT:  Controller is %s mapable\n",
15832801Sjulian	       (command & PCI_COMMAND_MEM_ENABLE)
15932801Sjulian	       ? "MEMORY"
16032801Sjulian	       : ((command & PCI_COMMAND_IO_ENABLE)
16132801Sjulian		  ? "I/O"
16232801Sjulian		  : "NOT"));
16332801Sjulian#endif
16432801Sjulian	return ("DPT Caching SCSI RAID Controller");
16532801Sjulian    }
16632801Sjulian
16732801Sjulian#if defined(DPT_DEBUG_PCI) && defined(DPT_DEBUG_WARN)
16832801Sjulian    printf("DPT:  Unknown Controller Type %x Found\n", dpt_id);
16932801Sjulian    printf("     (class = %x, command = %x\n", class, command);
17032801Sjulian#endif
17132801Sjulian    return (NULL);
17232801Sjulian}
17332801Sjulian
17432801Sjulianvoid
17532801Sjuliandpt_pci_attach(pcici_t config_id, int unit)
17632801Sjulian{
17732801Sjulian    int          ospl;
17832801Sjulian    int          result;
17932801Sjulian    int          ndx;
18032801Sjulian
18132801Sjulian    vm_offset_t  vaddr;
18232801Sjulian    vm_offset_t  paddr;
18332801Sjulian    u_int16_t    io_base;
18432801Sjulian    u_int32_t    command;
18532801Sjulian    u_int32_t    data;
18632801Sjulian    dpt_conf_t  *config;
18732801Sjulian    dpt_softc_t *dpt;
18832801Sjulian
18932801Sjulian    if (dpt_controllers_present >= DPT_MAX_ADAPTERS) {
19032801Sjulian	  printf("dpt%d: More than %d Adapters found!  Adapter rejected\n",
19132801Sjulian			 unit, DPT_MAX_ADAPTERS);
19232801Sjulian	  return;
19332801Sjulian    }
19432801Sjulian
19532801Sjulian    if ((dpt = (dpt_softc_t *) malloc(sizeof(dpt_softc_t), M_DEVBUF, M_NOWAIT))
19632801Sjulian		== NULL) {
19732801Sjulian	  printf("dpt%d: Failed to allocate %d bytes for a DPT softc\n",
19832801Sjulian			 unit, sizeof(dpt_softc_t));
19932801Sjulian	  return;
20032801Sjulian    }
20132801Sjulian
20232801Sjulian    /*
20332801Sjulian     * Initialize the queues.  See dpt.h for details. We do this here,
20432801Sjulian     * as we may get hit with interrupts at any moment and we want to
20532801Sjulian     * have a minimal structure in place to handle them. We also want to
20632801Sjulian     * register interrupts correctly. To do so, we need a valid dpt
20732801Sjulian     * structure. To have that, we need this  minimal setup here.
20832801Sjulian     */
20932801Sjulian    bzero(dpt, sizeof(dpt_softc_t));
21032801Sjulian
21132801Sjulian    TAILQ_INIT(&dpt->free_ccbs);
21232801Sjulian    TAILQ_INIT(&dpt->waiting_ccbs);
21332801Sjulian    TAILQ_INIT(&dpt->submitted_ccbs);
21432801Sjulian    TAILQ_INIT(&dpt->completed_ccbs);
21532801Sjulian
21632801Sjulian    if (TAILQ_EMPTY(&dpt_softc_list)) {
21732801Sjulian	  TAILQ_INIT(&dpt_softc_list);
21832801Sjulian    }
21932801Sjulian
22032801Sjulian    TAILQ_INSERT_TAIL(&dpt_softc_list, dpt, links);
22132801Sjulian    dpt->queue_status       = DPT_QUEUES_NONE_ACTIVE;
22232801Sjulian    dpt->commands_processed = 0;
22332801Sjulian
22432801Sjulian#ifdef DPT_MEASURE_PERFORMANCE
22532801Sjulian    /* Zero out all command counters */
22632801Sjulian    bzero((void *)&dpt->performance, sizeof(dpt_perf_t));
22732801Sjulian    for ( ndx = 0; ndx < 256; ndx ++ )
22832801Sjulian	  dpt->performance.min_command_time[ndx] = BIG_ENOUGH;
22932801Sjulian
23032801Sjulian    dpt->performance.min_intr_time     = BIG_ENOUGH;
23132801Sjulian    dpt->performance.min_waiting_time  = BIG_ENOUGH;
23232801Sjulian    dpt->performance.min_submit_time   = BIG_ENOUGH;
23332801Sjulian    dpt->performance.min_complete_time = BIG_ENOUGH;
23432801Sjulian    dpt->performance.min_eata_tries    = BIG_ENOUGH;
23532801Sjulian
23632801Sjulian    for (ndx = 0; ndx < 10; ndx++ ) {
23732801Sjulian	    dpt->performance.read_by_size_min_time[ndx] = BIG_ENOUGH;
23832801Sjulian	    dpt->performance.write_by_size_min_time[ndx] = BIG_ENOUGH;
23932801Sjulian    }
24032801Sjulian#endif        /* DPT_MEASURE_PERFORMANCE */
24132801Sjulian
24232801Sjulian    dpt->unit = unit;
24332801Sjulian    dpt->handle_interrupts = 0;  /*
24432801Sjulian								  * Do not set to 1 until all
24532801Sjulian								  * initialization is done
24632801Sjulian								  */
24732801Sjulian    dpt->v_membase = NULL;
24832801Sjulian    dpt->p_membase = NULL;
24932801Sjulian    io_base = 0;
25032801Sjulian    vaddr   = 0;
25132801Sjulian    paddr   = 0;
25232801Sjulian    command = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
25332801Sjulian
25432801Sjulian#ifdef DPT_ALLOW_MEMIO
25532801Sjulian    if ( (command & PCI_COMMAND_MEM_ENABLE) == 0 ) {
25632801Sjulian#ifdef DPT_DEBUG_PCI
25732801Sjulian	  printf("dpt%d: Cannot be memory mapped\n", unit);
25832801Sjulian#endif
25932801Sjulian	force_io:
26032801Sjulian	  if ((command & PCI_COMMAND_IO_ENABLE) == 0 ) {
26132801Sjulian	    printf("dpt%d: Cannot be I/O mapped either :-(\n", unit);
26232801Sjulian	    free(dpt, M_DEVBUF);
26332801Sjulian	    return;
26432801Sjulian	  } else {
26532801Sjulian	    data = pci_conf_read(config_id, PCI_MAP_REG_START);
26632801Sjulian	    if ( pci_map_port(config_id, PCI_MAP_REG_START, &io_base) == 0 ) {
26732801Sjulian#ifdef DPT_DEBUG_ERROR
26832801Sjulian		  printf("dpt%d: Failed to map as I/O :-(\n", unit);
26932801Sjulian#endif
27032801Sjulian		  free(dpt, M_DEVBUF);
27132801Sjulian		  return;
27232801Sjulian	    } else {
27332801Sjulian		  dpt->io_base = io_base + 0x10;
27432801Sjulian#ifdef DPT_DEBUG_PCI
27532801Sjulian		  printf("dpt%d: Mapped registers to I/O space, "
27632801Sjulian				 "starting at %x\n",
27732801Sjulian				 dpt->unit, dpt->io_base);
27832801Sjulian#endif
27932801Sjulian	    }
28032801Sjulian	  }
28132801Sjulian    } else {
28232801Sjulian	  if ( pci_map_mem(config_id, PCI_MAP_REG_START + 4, &vaddr,
28332801Sjulian					   &paddr) == 0 ) {
28432801Sjulian#ifdef DPT_DEBUG_ERROR
28532801Sjulian	    printf("dpt%d: Failed to map as MEMORY.\n"
28632801Sjulian			   "  Attemting to force I/O mapping\n", unit);
28732801Sjulian#endif
28832801Sjulian	    goto force_io;
28932801Sjulian	  } else {
29032801Sjulian	    dpt->v_membase = (volatile u_int8_t *)(vaddr + 0x10);
29132801Sjulian	    dpt->p_membase = (volatile u_int8_t *)(paddr + 0x10);
29232801Sjulian#ifdef DPT_DEBUG_PCI
29332801Sjulian	    printf("dpt%d: Mapped registers to MEMORY space, "
29432801Sjulian			   "starting at %x/%x\n",
29532801Sjulian			   dpt->unit, dpt->v_membase, dpt->p_membase);
29632801Sjulian#endif
29732801Sjulian	  }
29832801Sjulian    }
29932801Sjulian
30032801Sjulian#else /* !DPT_ALLOW_MEMIO */
30132801Sjulian    data = pci_conf_read(config_id, PCI_MAP_REG_START);
30232801Sjulian    if ((command & PCI_COMMAND_IO_ENABLE) == 0 ) {
30332801Sjulian	  printf("dpt%d: Registers cannot be I/O mapped :-(\n", unit);
30432801Sjulian	  free(dpt, M_DEVBUF);
30532801Sjulian	  return;
30632801Sjulian    } else {
30732801Sjulian	  if ( pci_map_port(config_id, PCI_MAP_REG_START, &io_base) == 0 ) {
30832801Sjulian#ifdef DPT_DEBUG_ERROR
30932801Sjulian	    printf("dpt%d: Failed to map registers as I/O :-(\n", unit);
31032801Sjulian#endif
31132801Sjulian	    free(dpt, M_DEVBUF);
31232801Sjulian	    return;
31332801Sjulian	  } else {
31432801Sjulian	    dpt->io_base = io_base + 0x10;
31532801Sjulian#ifdef DPT_DEBUG_PCI
31632801Sjulian	    printf("dpt%d: Mapped registers to I/O space, starting at %x\n",
31732801Sjulian			   dpt->unit, dpt->io_base);
31832801Sjulian#endif
31932801Sjulian	  }
32032801Sjulian    }
32132801Sjulian#endif /* !DPT_ALLOW_MEMIO */
32232801Sjulian
32332801Sjulian    if (pci_map_int(config_id, dpt_intr, (void *)dpt, &cam_imask) == 0) {
32432801Sjulian#ifdef DPT_DEBUG_WARN
32532801Sjulian	  printf("dpt%d: Failed to map interrupt :-(\n", unit);
32632801Sjulian#endif
32732801Sjulian	  free(dpt, M_DEVBUF);
32832801Sjulian	  return;
32932801Sjulian    }
33032801Sjulian
33132801Sjulian    /* If the DPT is mapped as an IDE controller, let it be IDE controller */
33232801Sjulian    if (io_base == (ISA_PRIMARY_WD_ADDRESS)) {
33332801Sjulian#ifdef DPT_DEBUG_WARN
33432801Sjulian	  printf("dpt%d: Mapped as an IDE controller.  "
33532801Sjulian			 "Disabling SCSI setup\n", unit);
33632801Sjulian#endif
33732801Sjulian	  free(dpt, M_DEVBUF);
33832801Sjulian	  return;
33932801Sjulian    } else {
34032801Sjulian	  if ((config = dpt_get_conf(dpt, 0xc1, 7,
34132801Sjulian								 sizeof(dpt_conf_t), 1)) == NULL) {
34232801Sjulian#ifdef DPT_DEBUG_ERROR
34332801Sjulian	    printf("dpt%d: Failed to get board configuration (%x)\n",
34432801Sjulian			   unit, BaseRegister(dpt));
34532801Sjulian#endif
34632801Sjulian	    free(dpt, M_DEVBUF);
34732801Sjulian	    return;
34832801Sjulian	  }
34932801Sjulian    }
35032801Sjulian
35132801Sjulian    dpt->max_id      = config->MAX_ID;
35232801Sjulian    dpt->max_lun     = config->MAX_LUN;
35332801Sjulian    dpt->irq         = config->IRQ;
35432801Sjulian    dpt->channels    = config->MAX_CHAN;
35532801Sjulian    dpt->dma_channel = (8 - config->DMA_channel) & 7;
35632801Sjulian
35732801Sjulian#ifdef DPT_DEBUG_SETUP
35832801Sjulian    printf("dpt%d: max_id = %d, max_chan = %d, max_lun = %d\n",
35932801Sjulian		   dpt->unit, dpt->max_id, dpt->channels, dpt->max_lun);
36032801Sjulian#endif
36132801Sjulian
36232801Sjulian    if (result = dpt_setup(dpt, config)) {
36332801Sjulian	  free(config, M_TEMP);
36432801Sjulian	  free(dpt, M_DEVBUF);
36532801Sjulian	  printf("dpt%d: dpt_setup failed (%d).  Driver Disabled :-(\n",
36632801Sjulian			 dpt->unit, result);
36732801Sjulian    } else {
36832801Sjulian	  /* clean up the informational data, and display */
36932801Sjulian	  char clean_vendor[9];
37032801Sjulian	  char clean_model[17];
37132801Sjulian	  char clean_firmware[5];
37232801Sjulian	  char clean_protocol[5];
37332801Sjulian	  char clean_other[7];
37432801Sjulian
37532801Sjulian	  int     ndx;
37632801Sjulian
37732801Sjulian	  strncpy(clean_other, dpt->board_data.otherData, 8);
37832801Sjulian	  clean_other[6] = '\0';
37932801Sjulian	  for (ndx = 5; ndx >= 0; ndx--) {
38032801Sjulian	    if (clean_other[ndx] == ' ')
38132801Sjulian		  clean_other[ndx] = '\0';
38232801Sjulian	    else
38332801Sjulian		  break;
38432801Sjulian	  }
38532801Sjulian	  strncpy(dpt->board_data.otherData, clean_other, 6);
38632801Sjulian
38732801Sjulian	  strncpy(clean_vendor, dpt->board_data.vendor, 8);
38832801Sjulian	  clean_vendor[8] = '\0';
38932801Sjulian	  for (ndx = 7; ndx >= 0; ndx--) {
39032801Sjulian	    if (clean_vendor[ndx] == ' ')
39132801Sjulian		  clean_vendor[ndx] = '\0';
39232801Sjulian	    else
39332801Sjulian		  break;
39432801Sjulian	  }
39532801Sjulian	  strncpy(dpt->board_data.vendor, clean_vendor, 8);
39632801Sjulian
39732801Sjulian	  strncpy(clean_model, dpt->board_data.modelNum, 16);
39832801Sjulian	  clean_model[16] = '\0';
39932801Sjulian	  for (ndx = 15; ndx >= 0; ndx--) {
40032801Sjulian	    if (clean_model[ndx] == ' ')
40132801Sjulian		  clean_model[ndx] = '\0';
40232801Sjulian	    else
40332801Sjulian		  break;
40432801Sjulian	  }
40532801Sjulian	  strncpy(dpt->board_data.modelNum, clean_model, 16);
40632801Sjulian
40732801Sjulian	  strncpy(clean_firmware, dpt->board_data.firmware, 4);
40832801Sjulian	  clean_firmware[4] = '\0';
40932801Sjulian	  for (ndx = 3; ndx >= 0; ndx--) {
41032801Sjulian	    if (clean_firmware[ndx] == ' ')
41132801Sjulian		  clean_firmware[ndx] = '\0';
41232801Sjulian	    else
41332801Sjulian		  break;
41432801Sjulian	  }
41532801Sjulian	  strncpy(dpt->board_data.firmware, clean_firmware, 4);
41632801Sjulian
41732801Sjulian	  strncpy(clean_protocol, dpt->board_data.protocol, 4);
41832801Sjulian	  clean_protocol[4] = '\0';
41932801Sjulian	  for (ndx = 3; ndx >= 0; ndx--) {
42032801Sjulian	    if (clean_protocol[ndx] == ' ')
42132801Sjulian		  clean_protocol[ndx] = '\0';
42232801Sjulian	    else
42332801Sjulian		  break;
42432801Sjulian	  }
42532801Sjulian	  strncpy(dpt->board_data.protocol, clean_protocol, 4);
42632801Sjulian
42732801Sjulian	  dpt_detect_cache(dpt);
42832801Sjulian
42932801Sjulian	  printf("dpt%d: %s type %x, model %s firmware %s, Protocol %s \n"
43032801Sjulian			 "      on port %x with %s cache.  LED = %s\n",
43132801Sjulian			 dpt->unit, clean_vendor, dpt->board_data.deviceType,
43232801Sjulian			 clean_model, clean_firmware, clean_protocol, dpt->io_base,
43332801Sjulian			 (dpt->cache_type == DPT_NO_CACHE)
43432801Sjulian			 ? "Disabled"
43532801Sjulian			 : (dpt->cache_type == DPT_CACHE_WRITETHROUGH)
43632801Sjulian			 ? "Write-Through"
43732801Sjulian			 : "Write-Back",
43832801Sjulian			 i2bin(dpt_blinking_led(dpt), 8));
43932801Sjulian	  printf("dpt%d: Enabled Options:\n", dpt->unit);
44032801Sjulian#ifdef DPT_LOST_IRQ
44132801Sjulian	  printf("      Recover Lost Interrupts\n");
44232801Sjulian#endif
44332801Sjulian#ifdef DPT_VERIFY_HINTR
44432801Sjulian	  printf("      Verify Lost Transactions\n");
44532801Sjulian#endif
44632801Sjulian#ifdef DPT_RESTRICTED_FREELIST
44732801Sjulian	  printf("      Restrict the Freelist Size\n");
44832801Sjulian#endif
44932801Sjulian#ifdef DPT_MEASURE_PERFORMANCE
45032801Sjulian	  printf("      Collect Metrics\n");
45132801Sjulian#endif
45232801Sjulian#ifdef DPT_FREELIST_IS_STACK
45332801Sjulian	  printf("      Optimize CPU Cache\n");
45432801Sjulian#endif
45532801Sjulian#ifdef DPT_HANDLE_TIMEOUTS
45632801Sjulian	  printf("      Handle Timeouts\n");
45732801Sjulian#endif
45832801Sjulian#ifdef DPT_ALLOW_MEMIO
45932801Sjulian	  printf("      Allow I/O to be Memeory Mapped\n");
46032801Sjulian#endif
46132801Sjulian#ifdef DPT_HINTR_CHECK_SOFTC
46232801Sjulian	  printf("      Validate SoftC at Interrupt\n");
46332801Sjulian#endif
46432801Sjulian
46532801Sjulian	  /* register shutdown handlers */
46632801Sjulian	  result = at_shutdown((bootlist_fn)dpt_shutdown, (void *)dpt,
46732801Sjulian						   SHUTDOWN_POST_SYNC);
46832801Sjulian	  switch ( result ) {
46932801Sjulian	  case 0:
47032801Sjulian#ifdef DPT_DEBUG_SHUTDOWN
47132801Sjulian		printf("dpt%d: Shutdown handler registered\n", dpt->unit);
47232801Sjulian#endif
47332801Sjulian		break;
47432801Sjulian	  default:
47532801Sjulian#ifdef DPT_DEBUG_WARN
47632801Sjulian		printf("dpt%d: Failed to register shutdown handler (%d)\n",
47732801Sjulian			   dpt->unit, result);
47832801Sjulian#endif
47932801Sjulian		break;
48032801Sjulian	  }
48132801Sjulian
48232801Sjulian	  /* Attach SCSI devices */
48332801Sjulian	  dpt_attach(dpt);
48432801Sjulian	  ++dpt_controllers_present;
48532801Sjulian
48632801Sjulian	  /*
48732801Sjulian	   * Now we create the DEVFS entry.
48832801Sjulian	   * This would be normally done from dpt_control.c,
48932801Sjulian	   * But since it appears to be called before we do here,
49032801Sjulian	   * We never get the entries made.
49132801Sjulian       */
49232801Sjulian#ifdef DEVFS
49332801Sjulian	  dpt->devfs_data_token = devfs_add_devswf(&dpt_cdevsw, dpt->unit, DV_CHR,
49432801Sjulian											   UID_ROOT, GID_WHEEL, 0600,
49532801Sjulian											   "dpt%d", dpt->unit);
49632801Sjulian	  dpt->devfs_ctl_token = devfs_add_devswf(&dpt_cdevsw,
49732801Sjulian											  dpt->unit | SCSI_CONTROL_MASK,
49832801Sjulian											  DV_CHR,
49932801Sjulian											  UID_ROOT, GID_WHEEL, 0600,
50032801Sjulian											  "dpt%d.ctl", dpt->unit);
50132801Sjulian#endif
50232801Sjulian    }
50332801Sjulian}
50432801Sjulian
50532801Sjulianint
50632801Sjuliandpt_pci_shutdown(int foo, int bar)
50732801Sjulian{
50832801Sjulian#ifdef DPT_DEBUG_WARN
50932801Sjulian    printf("dpt_pci_shutdown(%x, %x)\n", foo, bar);
51032801Sjulian#endif
51132801Sjulian    return (0);
51232801Sjulian}
51332801Sjulian
51432801Sjulian/* End of the DPT PCI part of the driver */
51532801Sjulian
51632801Sjulian/*
51732801Sjulian * Hello emacs, these are the
51832801Sjulian * Local Variables:
51932801Sjulian *  c-indent-level:               8
52032801Sjulian *  c-continued-statement-offset: 8
52132801Sjulian *  c-continued-brace-offset:     0
52232801Sjulian *  c-brace-offset:              -8
52332801Sjulian *  c-brace-imaginary-offset:     0
52432801Sjulian *  c-argdecl-indent:             8
52532801Sjulian *  c-label-offset:              -8
52632801Sjulian *  c++-hanging-braces:           1
52732801Sjulian *  c++-access-specifier-offset: -8
52832801Sjulian *  c++-empty-arglist-indent:     8
52932801Sjulian *  c++-friend-offset:            0
53032801Sjulian * End:
53132801Sjulian */
532