Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/aic7xxx/aic79xx_pci.c
39507 views
1
/*-
2
* Product specific probe and attach routines for:
3
* aic7901 and aic7902 SCSI controllers
4
*
5
* SPDX-License-Identifier: BSD-3-Clause
6
*
7
* Copyright (c) 1994-2001 Justin T. Gibbs.
8
* Copyright (c) 2000-2002 Adaptec Inc.
9
* All rights reserved.
10
*
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions
13
* are met:
14
* 1. Redistributions of source code must retain the above copyright
15
* notice, this list of conditions, and the following disclaimer,
16
* without modification.
17
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
18
* substantially similar to the "NO WARRANTY" disclaimer below
19
* ("Disclaimer") and any redistribution must be conditioned upon
20
* including a substantially similar Disclaimer requirement for further
21
* binary redistribution.
22
* 3. Neither the names of the above-listed copyright holders nor the names
23
* of any contributors may be used to endorse or promote products derived
24
* from this software without specific prior written permission.
25
*
26
* Alternatively, this software may be distributed under the terms of the
27
* GNU General Public License ("GPL") version 2 as published by the Free
28
* Software Foundation.
29
*
30
* NO WARRANTY
31
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
* POSSIBILITY OF SUCH DAMAGES.
42
*
43
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#88 $
44
*/
45
46
#include <dev/aic7xxx/aic79xx_osm.h>
47
#include <dev/aic7xxx/aic79xx_inline.h>
48
49
static __inline uint64_t
50
ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
51
{
52
uint64_t id;
53
54
id = subvendor
55
| (subdevice << 16)
56
| ((uint64_t)vendor << 32)
57
| ((uint64_t)device << 48);
58
59
return (id);
60
}
61
62
#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull
63
#define ID_ALL_IROC_MASK 0xFF7FFFFFFFFFFFFFull
64
#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull
65
#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull
66
#define ID_9005_GENERIC_IROC_MASK 0xFF70FFFF00000000ull
67
68
#define ID_AIC7901 0x800F9005FFFF9005ull
69
#define ID_AHA_29320A 0x8000900500609005ull
70
#define ID_AHA_29320ALP 0x8017900500449005ull
71
#define ID_AHA_29320LPE 0x8017900500459005ull
72
73
#define ID_AIC7901A 0x801E9005FFFF9005ull
74
#define ID_AHA_29320LP 0x8014900500449005ull
75
76
#define ID_AIC7902 0x801F9005FFFF9005ull
77
#define ID_AIC7902_B 0x801D9005FFFF9005ull
78
#define ID_AHA_39320 0x8010900500409005ull
79
#define ID_AHA_29320 0x8012900500429005ull
80
#define ID_AHA_29320B 0x8013900500439005ull
81
#define ID_AHA_39320_B 0x8015900500409005ull
82
#define ID_AHA_39320_B_DELL 0x8015900501681028ull
83
#define ID_AHA_39320A 0x8016900500409005ull
84
#define ID_AHA_39320D 0x8011900500419005ull
85
#define ID_AHA_39320D_B 0x801C900500419005ull
86
#define ID_AHA_39320D_HP 0x8011900500AC0E11ull
87
#define ID_AHA_39320D_B_HP 0x801C900500AC0E11ull
88
#define ID_AIC7902_PCI_REV_A4 0x3
89
#define ID_AIC7902_PCI_REV_B0 0x10
90
#define SUBID_HP 0x0E11
91
#define DEVICE8081 0x8081
92
#define DEVICE8088 0x8088
93
#define DEVICE8089 0x8089
94
#define ADAPTECVENDORID 0x9005
95
#define SUBVENDOR9005 0x9005
96
97
#define DEVID_9005_HOSTRAID(id) ((id) & 0x80)
98
99
#define DEVID_9005_TYPE(id) ((id) & 0xF)
100
#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */
101
#define DEVID_9005_TYPE_HBA_2EXT 0x1 /* 2 External Ports */
102
#define DEVID_9005_TYPE_MB 0xF /* On Motherboard */
103
104
#define DEVID_9005_MFUNC(id) ((id) & 0x10)
105
106
#define DEVID_9005_PACKETIZED(id) ((id) & 0x8000)
107
108
#define SUBID_9005_TYPE(id) ((id) & 0xF)
109
#define SUBID_9005_TYPE_HBA 0x0 /* Standard Card */
110
#define SUBID_9005_TYPE_MB 0xF /* On Motherboard */
111
112
#define SUBID_9005_AUTOTERM(id) (((id) & 0x10) == 0)
113
114
#define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20)
115
116
#define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6)
117
#define SUBID_9005_SEEPTYPE_NONE 0x0
118
#define SUBID_9005_SEEPTYPE_4K 0x1
119
120
static ahd_device_setup_t ahd_aic7901_setup;
121
static ahd_device_setup_t ahd_aic7901A_setup;
122
static ahd_device_setup_t ahd_aic7902_setup;
123
static ahd_device_setup_t ahd_aic790X_setup;
124
125
struct ahd_pci_identity ahd_pci_ident_table [] =
126
{
127
/* aic7901 based controllers */
128
{
129
ID_AHA_29320A,
130
ID_ALL_MASK,
131
"Adaptec 29320A Ultra320 SCSI adapter",
132
ahd_aic7901_setup
133
},
134
{
135
ID_AHA_29320ALP,
136
ID_ALL_MASK,
137
"Adaptec 29320ALP Ultra320 SCSI adapter",
138
ahd_aic7901_setup
139
},
140
{
141
ID_AHA_29320LPE,
142
ID_ALL_MASK,
143
"Adaptec 29320LPE Ultra320 SCSI adapter",
144
ahd_aic7901_setup
145
},
146
/* aic7901A based controllers */
147
{
148
ID_AHA_29320LP,
149
ID_ALL_MASK,
150
"Adaptec 29320LP Ultra320 SCSI adapter",
151
ahd_aic7901A_setup
152
},
153
/* aic7902 based controllers */
154
{
155
ID_AHA_29320,
156
ID_ALL_MASK,
157
"Adaptec 29320 Ultra320 SCSI adapter",
158
ahd_aic7902_setup
159
},
160
{
161
ID_AHA_29320B,
162
ID_ALL_MASK,
163
"Adaptec 29320B Ultra320 SCSI adapter",
164
ahd_aic7902_setup
165
},
166
{
167
ID_AHA_39320,
168
ID_ALL_MASK,
169
"Adaptec 39320 Ultra320 SCSI adapter",
170
ahd_aic7902_setup
171
},
172
{
173
ID_AHA_39320_B,
174
ID_ALL_MASK,
175
"Adaptec 39320 Ultra320 SCSI adapter",
176
ahd_aic7902_setup
177
},
178
{
179
ID_AHA_39320_B_DELL,
180
ID_ALL_MASK,
181
"Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter",
182
ahd_aic7902_setup
183
},
184
{
185
ID_AHA_39320A,
186
ID_ALL_MASK,
187
"Adaptec 39320A Ultra320 SCSI adapter",
188
ahd_aic7902_setup
189
},
190
{
191
ID_AHA_39320D,
192
ID_ALL_MASK,
193
"Adaptec 39320D Ultra320 SCSI adapter",
194
ahd_aic7902_setup
195
},
196
{
197
ID_AHA_39320D_HP,
198
ID_ALL_MASK,
199
"Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",
200
ahd_aic7902_setup
201
},
202
{
203
ID_AHA_39320D_B,
204
ID_ALL_MASK,
205
"Adaptec 39320D Ultra320 SCSI adapter",
206
ahd_aic7902_setup
207
},
208
{
209
ID_AHA_39320D_B_HP,
210
ID_ALL_MASK,
211
"Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",
212
ahd_aic7902_setup
213
},
214
/* Generic chip probes for devices we don't know 'exactly' */
215
{
216
ID_AIC7901 & ID_9005_GENERIC_MASK,
217
ID_9005_GENERIC_MASK,
218
"Adaptec AIC7901 Ultra320 SCSI adapter",
219
ahd_aic7901_setup
220
},
221
{
222
ID_AIC7901A & ID_DEV_VENDOR_MASK,
223
ID_DEV_VENDOR_MASK,
224
"Adaptec AIC7901A Ultra320 SCSI adapter",
225
ahd_aic7901A_setup
226
},
227
{
228
ID_AIC7902 & ID_9005_GENERIC_MASK,
229
ID_9005_GENERIC_MASK,
230
"Adaptec AIC7902 Ultra320 SCSI adapter",
231
ahd_aic7902_setup
232
}
233
};
234
235
const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table);
236
237
#define DEVCONFIG 0x40
238
#define PCIXINITPAT 0x0000E000ul
239
#define PCIXINIT_PCI33_66 0x0000E000ul
240
#define PCIXINIT_PCIX50_66 0x0000C000ul
241
#define PCIXINIT_PCIX66_100 0x0000A000ul
242
#define PCIXINIT_PCIX100_133 0x00008000ul
243
#define PCI_BUS_MODES_INDEX(devconfig) \
244
(((devconfig) & PCIXINITPAT) >> 13)
245
static const char *pci_bus_modes[] =
246
{
247
"PCI bus mode unknown",
248
"PCI bus mode unknown",
249
"PCI bus mode unknown",
250
"PCI bus mode unknown",
251
"PCI-X 101-133MHz",
252
"PCI-X 67-100MHz",
253
"PCI-X 50-66MHz",
254
"PCI 33 or 66MHz"
255
};
256
257
#define TESTMODE 0x00000800ul
258
#define IRDY_RST 0x00000200ul
259
#define FRAME_RST 0x00000100ul
260
#define PCI64BIT 0x00000080ul
261
#define MRDCEN 0x00000040ul
262
#define ENDIANSEL 0x00000020ul
263
#define MIXQWENDIANEN 0x00000008ul
264
#define DACEN 0x00000004ul
265
#define STPWLEVEL 0x00000002ul
266
#define QWENDIANSEL 0x00000001ul
267
268
#define DEVCONFIG1 0x44
269
#define PREQDIS 0x01
270
271
#define CSIZE_LATTIME 0x0c
272
#define CACHESIZE 0x000000fful
273
#define LATTIME 0x0000ff00ul
274
275
static int ahd_check_extport(struct ahd_softc *ahd);
276
static void ahd_configure_termination(struct ahd_softc *ahd,
277
u_int adapter_control);
278
static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat);
279
280
struct ahd_pci_identity *
281
ahd_find_pci_device(aic_dev_softc_t pci)
282
{
283
uint64_t full_id;
284
uint16_t device;
285
uint16_t vendor;
286
uint16_t subdevice;
287
uint16_t subvendor;
288
struct ahd_pci_identity *entry;
289
u_int i;
290
291
vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
292
device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
293
subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
294
subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);
295
296
if ((vendor == ADAPTECVENDORID) && (subvendor == SUBVENDOR9005)) {
297
if ((device == DEVICE8081) || (device == DEVICE8088) ||
298
(device == DEVICE8089)) {
299
printf("Controller device ID conflict with PMC Adaptec HBA\n");
300
return (NULL);
301
}
302
}
303
304
full_id = ahd_compose_id(device,
305
vendor,
306
subdevice,
307
subvendor);
308
309
/*
310
* If we are configured to attach to HostRAID
311
* controllers, mask out the IROC/HostRAID bit
312
* in the
313
*/
314
if (ahd_attach_to_HostRAID_controllers)
315
full_id &= ID_ALL_IROC_MASK;
316
317
for (i = 0; i < ahd_num_pci_devs; i++) {
318
entry = &ahd_pci_ident_table[i];
319
if (entry->full_id == (full_id & entry->id_mask)) {
320
/* Honor exclusion entries. */
321
if (entry->name == NULL)
322
return (NULL);
323
return (entry);
324
}
325
}
326
return (NULL);
327
}
328
329
int
330
ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
331
{
332
u_int command;
333
uint32_t devconfig;
334
uint16_t device;
335
uint16_t subvendor;
336
int error;
337
338
ahd->description = entry->name;
339
/*
340
* Record if this is a HostRAID board.
341
*/
342
device = aic_pci_read_config(ahd->dev_softc,
343
PCIR_DEVICE, /*bytes*/2);
344
if (DEVID_9005_HOSTRAID(device))
345
ahd->flags |= AHD_HOSTRAID_BOARD;
346
347
/*
348
* Record if this is an HP board.
349
*/
350
subvendor = aic_pci_read_config(ahd->dev_softc,
351
PCIR_SUBVEND_0, /*bytes*/2);
352
if (subvendor == SUBID_HP)
353
ahd->flags |= AHD_HP_BOARD;
354
355
error = entry->setup(ahd);
356
if (error != 0)
357
return (error);
358
359
/*
360
* Find the PCI-X cap pointer. If we don't find it,
361
* pcix_ptr will be 0.
362
*/
363
pci_find_cap(ahd->dev_softc, PCIY_PCIX, &ahd->pcix_ptr);
364
devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
365
if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) {
366
ahd->chip |= AHD_PCI;
367
/* Disable PCIX workarounds when running in PCI mode. */
368
ahd->bugs &= ~AHD_PCIX_BUG_MASK;
369
} else {
370
ahd->chip |= AHD_PCIX;
371
if (ahd->pcix_ptr == 0)
372
return (ENXIO);
373
}
374
ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)];
375
376
aic_power_state_change(ahd, AIC_POWER_STATE_D0);
377
378
error = ahd_pci_map_registers(ahd);
379
if (error != 0)
380
return (error);
381
382
/*
383
* If we need to support high memory, enable dual
384
* address cycles. This bit must be set to enable
385
* high address bit generation even if we are on a
386
* 64bit bus (PCI64BIT set in devconfig).
387
*/
388
if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) {
389
uint32_t devconfig;
390
391
if (bootverbose)
392
printf("%s: Enabling 39Bit Addressing\n",
393
ahd_name(ahd));
394
devconfig = aic_pci_read_config(ahd->dev_softc,
395
DEVCONFIG, /*bytes*/4);
396
devconfig |= DACEN;
397
aic_pci_write_config(ahd->dev_softc, DEVCONFIG,
398
devconfig, /*bytes*/4);
399
}
400
401
/* Ensure busmastering is enabled */
402
command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
403
command |= PCIM_CMD_BUSMASTEREN;
404
aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2);
405
406
error = ahd_softc_init(ahd);
407
if (error != 0)
408
return (error);
409
410
ahd->bus_intr = ahd_pci_intr;
411
412
error = ahd_reset(ahd, /*reinit*/FALSE);
413
if (error != 0)
414
return (ENXIO);
415
416
ahd->pci_cachesize =
417
aic_pci_read_config(ahd->dev_softc, CSIZE_LATTIME,
418
/*bytes*/1) & CACHESIZE;
419
ahd->pci_cachesize *= 4;
420
421
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
422
/* See if we have a SEEPROM and perform auto-term */
423
error = ahd_check_extport(ahd);
424
if (error != 0)
425
return (error);
426
427
/* Core initialization */
428
error = ahd_init(ahd);
429
if (error != 0)
430
return (error);
431
432
/*
433
* Allow interrupts now that we are completely setup.
434
*/
435
error = ahd_pci_map_int(ahd);
436
if (error != 0)
437
return (error);
438
439
ahd_lock(ahd);
440
/*
441
* Link this softc in with all other ahd instances.
442
*/
443
ahd_softc_insert(ahd);
444
ahd_unlock(ahd);
445
return (0);
446
}
447
448
/*
449
* Perform some simple tests that should catch situations where
450
* our registers are invalidly mapped.
451
*/
452
int
453
ahd_pci_test_register_access(struct ahd_softc *ahd)
454
{
455
uint32_t cmd;
456
u_int targpcistat;
457
u_int pci_status1;
458
int error;
459
uint8_t hcntrl;
460
461
error = EIO;
462
463
/*
464
* Enable PCI error interrupt status, but suppress NMIs
465
* generated by SERR raised due to target aborts.
466
*/
467
cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
468
aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
469
cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
470
471
/*
472
* First a simple test to see if any
473
* registers can be read. Reading
474
* HCNTRL has no side effects and has
475
* at least one bit that is guaranteed to
476
* be zero so it is a good register to
477
* use for this test.
478
*/
479
hcntrl = ahd_inb(ahd, HCNTRL);
480
if (hcntrl == 0xFF)
481
goto fail;
482
483
/*
484
* Next create a situation where write combining
485
* or read prefetching could be initiated by the
486
* CPU or host bridge. Our device does not support
487
* either, so look for data corruption and/or flagged
488
* PCI errors. First pause without causing another
489
* chip reset.
490
*/
491
hcntrl &= ~CHIPRST;
492
ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
493
while (ahd_is_paused(ahd) == 0)
494
;
495
496
/* Clear any PCI errors that occurred before our driver attached. */
497
ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
498
targpcistat = ahd_inb(ahd, TARGPCISTAT);
499
ahd_outb(ahd, TARGPCISTAT, targpcistat);
500
pci_status1 = aic_pci_read_config(ahd->dev_softc,
501
PCIR_STATUS + 1, /*bytes*/1);
502
aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
503
pci_status1, /*bytes*/1);
504
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
505
ahd_outb(ahd, CLRINT, CLRPCIINT);
506
507
ahd_outb(ahd, SEQCTL0, PERRORDIS);
508
ahd_outl(ahd, SRAM_BASE, 0x5aa555aa);
509
if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa)
510
goto fail;
511
512
if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
513
u_int targpcistat;
514
515
ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
516
targpcistat = ahd_inb(ahd, TARGPCISTAT);
517
if ((targpcistat & STA) != 0)
518
goto fail;
519
}
520
521
error = 0;
522
523
fail:
524
if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
525
ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
526
targpcistat = ahd_inb(ahd, TARGPCISTAT);
527
528
/* Silently clear any latched errors. */
529
ahd_outb(ahd, TARGPCISTAT, targpcistat);
530
pci_status1 = aic_pci_read_config(ahd->dev_softc,
531
PCIR_STATUS + 1, /*bytes*/1);
532
aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
533
pci_status1, /*bytes*/1);
534
ahd_outb(ahd, CLRINT, CLRPCIINT);
535
}
536
ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS);
537
aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
538
return (error);
539
}
540
541
/*
542
* Check the external port logic for a serial eeprom
543
* and termination/cable detection contrls.
544
*/
545
static int
546
ahd_check_extport(struct ahd_softc *ahd)
547
{
548
struct vpd_config vpd;
549
struct seeprom_config *sc;
550
u_int adapter_control;
551
int have_seeprom;
552
int error;
553
554
sc = ahd->seep_config;
555
have_seeprom = ahd_acquire_seeprom(ahd);
556
if (have_seeprom) {
557
u_int start_addr;
558
559
/*
560
* Fetch VPD for this function and parse it.
561
*/
562
if (bootverbose)
563
printf("%s: Reading VPD from SEEPROM...",
564
ahd_name(ahd));
565
566
/* Address is always in units of 16bit words */
567
start_addr = ((2 * sizeof(*sc))
568
+ (sizeof(vpd) * (ahd->channel - 'A'))) / 2;
569
570
error = ahd_read_seeprom(ahd, (uint16_t *)&vpd,
571
start_addr, sizeof(vpd)/2,
572
/*bytestream*/TRUE);
573
if (error == 0)
574
error = ahd_parse_vpddata(ahd, &vpd);
575
if (bootverbose)
576
printf("%s: VPD parsing %s\n",
577
ahd_name(ahd),
578
error == 0 ? "successful" : "failed");
579
580
if (bootverbose)
581
printf("%s: Reading SEEPROM...", ahd_name(ahd));
582
583
/* Address is always in units of 16bit words */
584
start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A');
585
586
error = ahd_read_seeprom(ahd, (uint16_t *)sc,
587
start_addr, sizeof(*sc)/2,
588
/*bytestream*/FALSE);
589
590
if (error != 0) {
591
printf("Unable to read SEEPROM\n");
592
have_seeprom = 0;
593
} else {
594
have_seeprom = ahd_verify_cksum(sc);
595
596
if (bootverbose) {
597
if (have_seeprom == 0)
598
printf ("checksum error\n");
599
else
600
printf ("done.\n");
601
}
602
}
603
ahd_release_seeprom(ahd);
604
}
605
606
if (!have_seeprom) {
607
u_int nvram_scb;
608
609
/*
610
* Pull scratch ram settings and treat them as
611
* if they are the contents of an seeprom if
612
* the 'ADPT', 'BIOS', or 'ASPI' signature is found
613
* in SCB 0xFF. We manually compose the data as 16bit
614
* values to avoid endian issues.
615
*/
616
ahd_set_scbptr(ahd, 0xFF);
617
nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET);
618
if (nvram_scb != 0xFF
619
&& ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
620
&& ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D'
621
&& ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
622
&& ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T')
623
|| (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B'
624
&& ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I'
625
&& ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O'
626
&& ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S')
627
|| (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
628
&& ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S'
629
&& ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
630
&& ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) {
631
uint16_t *sc_data;
632
int i;
633
634
ahd_set_scbptr(ahd, nvram_scb);
635
sc_data = (uint16_t *)sc;
636
for (i = 0; i < 64; i += 2)
637
*sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i);
638
have_seeprom = ahd_verify_cksum(sc);
639
if (have_seeprom)
640
ahd->flags |= AHD_SCB_CONFIG_USED;
641
}
642
}
643
644
#ifdef AHD_DEBUG
645
if (have_seeprom != 0
646
&& (ahd_debug & AHD_DUMP_SEEPROM) != 0) {
647
uint16_t *sc_data;
648
int i;
649
650
printf("%s: Seeprom Contents:", ahd_name(ahd));
651
sc_data = (uint16_t *)sc;
652
for (i = 0; i < (sizeof(*sc)); i += 2)
653
printf("\n\t0x%.4x", sc_data[i]);
654
printf("\n");
655
}
656
#endif
657
658
if (!have_seeprom) {
659
if (bootverbose)
660
printf("%s: No SEEPROM available.\n", ahd_name(ahd));
661
ahd->flags |= AHD_USEDEFAULTS;
662
error = ahd_default_config(ahd);
663
adapter_control = CFAUTOTERM|CFSEAUTOTERM;
664
free(ahd->seep_config, M_DEVBUF);
665
ahd->seep_config = NULL;
666
} else {
667
error = ahd_parse_cfgdata(ahd, sc);
668
adapter_control = sc->adapter_control;
669
}
670
if (error != 0)
671
return (error);
672
673
ahd_configure_termination(ahd, adapter_control);
674
675
return (0);
676
}
677
678
static void
679
ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)
680
{
681
int error;
682
u_int sxfrctl1;
683
uint8_t termctl;
684
uint32_t devconfig;
685
686
devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
687
devconfig &= ~STPWLEVEL;
688
if ((ahd->flags & AHD_STPWLEVEL_A) != 0)
689
devconfig |= STPWLEVEL;
690
if (bootverbose)
691
printf("%s: STPWLEVEL is %s\n",
692
ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off");
693
aic_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
694
695
/* Make sure current sensing is off. */
696
if ((ahd->flags & AHD_CURRENT_SENSING) != 0) {
697
(void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);
698
}
699
700
/*
701
* Read to sense. Write to set.
702
*/
703
error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl);
704
if ((adapter_control & CFAUTOTERM) == 0) {
705
if (bootverbose)
706
printf("%s: Manual Primary Termination\n",
707
ahd_name(ahd));
708
termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH);
709
if ((adapter_control & CFSTERM) != 0)
710
termctl |= FLX_TERMCTL_ENPRILOW;
711
if ((adapter_control & CFWSTERM) != 0)
712
termctl |= FLX_TERMCTL_ENPRIHIGH;
713
} else if (error != 0) {
714
printf("%s: Primary Auto-Term Sensing failed! "
715
"Using Defaults.\n", ahd_name(ahd));
716
termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH;
717
}
718
719
if ((adapter_control & CFSEAUTOTERM) == 0) {
720
if (bootverbose)
721
printf("%s: Manual Secondary Termination\n",
722
ahd_name(ahd));
723
termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH);
724
if ((adapter_control & CFSELOWTERM) != 0)
725
termctl |= FLX_TERMCTL_ENSECLOW;
726
if ((adapter_control & CFSEHIGHTERM) != 0)
727
termctl |= FLX_TERMCTL_ENSECHIGH;
728
} else if (error != 0) {
729
printf("%s: Secondary Auto-Term Sensing failed! "
730
"Using Defaults.\n", ahd_name(ahd));
731
termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH;
732
}
733
734
/*
735
* Now set the termination based on what we found.
736
*/
737
sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;
738
ahd->flags &= ~AHD_TERM_ENB_A;
739
if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {
740
ahd->flags |= AHD_TERM_ENB_A;
741
sxfrctl1 |= STPWEN;
742
}
743
/* Must set the latch once in order to be effective. */
744
ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);
745
ahd_outb(ahd, SXFRCTL1, sxfrctl1);
746
747
error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl);
748
if (error != 0) {
749
printf("%s: Unable to set termination settings!\n",
750
ahd_name(ahd));
751
} else if (bootverbose) {
752
printf("%s: Primary High byte termination %sabled\n",
753
ahd_name(ahd),
754
(termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis");
755
756
printf("%s: Primary Low byte termination %sabled\n",
757
ahd_name(ahd),
758
(termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis");
759
760
printf("%s: Secondary High byte termination %sabled\n",
761
ahd_name(ahd),
762
(termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis");
763
764
printf("%s: Secondary Low byte termination %sabled\n",
765
ahd_name(ahd),
766
(termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis");
767
}
768
return;
769
}
770
771
#define DPE 0x80
772
#define SSE 0x40
773
#define RMA 0x20
774
#define RTA 0x10
775
#define STA 0x08
776
#define DPR 0x01
777
778
static const char *split_status_source[] =
779
{
780
"DFF0",
781
"DFF1",
782
"OVLY",
783
"CMC",
784
};
785
786
static const char *pci_status_source[] =
787
{
788
"DFF0",
789
"DFF1",
790
"SG",
791
"CMC",
792
"OVLY",
793
"NONE",
794
"MSI",
795
"TARG"
796
};
797
798
static const char *split_status_strings[] =
799
{
800
"%s: Received split response in %s.\n",
801
"%s: Received split completion error message in %s\n",
802
"%s: Receive overrun in %s\n",
803
"%s: Count not complete in %s\n",
804
"%s: Split completion data bucket in %s\n",
805
"%s: Split completion address error in %s\n",
806
"%s: Split completion byte count error in %s\n",
807
"%s: Signaled Target-abort to early terminate a split in %s\n"
808
};
809
810
static const char *pci_status_strings[] =
811
{
812
"%s: Data Parity Error has been reported via PERR# in %s\n",
813
"%s: Target initial wait state error in %s\n",
814
"%s: Split completion read data parity error in %s\n",
815
"%s: Split completion address attribute parity error in %s\n",
816
"%s: Received a Target Abort in %s\n",
817
"%s: Received a Master Abort in %s\n",
818
"%s: Signal System Error Detected in %s\n",
819
"%s: Address or Write Phase Parity Error Detected in %s.\n"
820
};
821
822
void
823
ahd_pci_intr(struct ahd_softc *ahd)
824
{
825
uint8_t pci_status[8];
826
ahd_mode_state saved_modes;
827
u_int pci_status1;
828
u_int intstat;
829
u_int i;
830
u_int reg;
831
832
intstat = ahd_inb(ahd, INTSTAT);
833
834
if ((intstat & SPLTINT) != 0)
835
ahd_pci_split_intr(ahd, intstat);
836
837
if ((intstat & PCIINT) == 0)
838
return;
839
840
printf("%s: PCI error Interrupt\n", ahd_name(ahd));
841
saved_modes = ahd_save_modes(ahd);
842
ahd_dump_card_state(ahd);
843
ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
844
for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) {
845
if (i == 5)
846
continue;
847
pci_status[i] = ahd_inb(ahd, reg);
848
/* Clear latched errors. So our interrupt deasserts. */
849
ahd_outb(ahd, reg, pci_status[i]);
850
}
851
852
for (i = 0; i < 8; i++) {
853
u_int bit;
854
855
if (i == 5)
856
continue;
857
858
for (bit = 0; bit < 8; bit++) {
859
if ((pci_status[i] & (0x1 << bit)) != 0) {
860
static const char *s;
861
862
s = pci_status_strings[bit];
863
if (i == 7/*TARG*/ && bit == 3)
864
s = "%s: Signaled Target Abort\n";
865
printf(s, ahd_name(ahd), pci_status_source[i]);
866
}
867
}
868
}
869
pci_status1 = aic_pci_read_config(ahd->dev_softc,
870
PCIR_STATUS + 1, /*bytes*/1);
871
aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
872
pci_status1, /*bytes*/1);
873
ahd_restore_modes(ahd, saved_modes);
874
ahd_outb(ahd, CLRINT, CLRPCIINT);
875
ahd_unpause(ahd);
876
}
877
878
static void
879
ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)
880
{
881
uint8_t split_status[4];
882
uint8_t split_status1[4];
883
uint8_t sg_split_status[2];
884
uint8_t sg_split_status1[2];
885
ahd_mode_state saved_modes;
886
u_int i;
887
uint32_t pcix_status;
888
889
/*
890
* Check for splits in all modes. Modes 0 and 1
891
* additionally have SG engine splits to look at.
892
*/
893
pcix_status = aic_pci_read_config(ahd->dev_softc,
894
ahd->pcix_ptr + PCIXR_STATUS, /*bytes*/ 4);
895
printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n",
896
ahd_name(ahd), pcix_status >> 16);
897
saved_modes = ahd_save_modes(ahd);
898
for (i = 0; i < 4; i++) {
899
ahd_set_modes(ahd, i, i);
900
901
split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0);
902
split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1);
903
/* Clear latched errors. So our interrupt deasserts. */
904
ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]);
905
ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]);
906
if (i > 1)
907
continue;
908
sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0);
909
sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1);
910
/* Clear latched errors. So our interrupt deasserts. */
911
ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]);
912
ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]);
913
}
914
915
for (i = 0; i < 4; i++) {
916
u_int bit;
917
918
for (bit = 0; bit < 8; bit++) {
919
if ((split_status[i] & (0x1 << bit)) != 0) {
920
static const char *s;
921
922
s = split_status_strings[bit];
923
printf(s, ahd_name(ahd),
924
split_status_source[i]);
925
}
926
927
if (i > 1)
928
continue;
929
930
if ((sg_split_status[i] & (0x1 << bit)) != 0) {
931
static const char *s;
932
933
s = split_status_strings[bit];
934
printf(s, ahd_name(ahd), "SG");
935
}
936
}
937
}
938
/*
939
* Clear PCI-X status bits.
940
*/
941
aic_pci_write_config(ahd->dev_softc, ahd->pcix_ptr + PCIXR_STATUS,
942
pcix_status, /*bytes*/4);
943
ahd_outb(ahd, CLRINT, CLRSPLTINT);
944
ahd_restore_modes(ahd, saved_modes);
945
}
946
947
static int
948
ahd_aic7901_setup(struct ahd_softc *ahd)
949
{
950
951
ahd->chip = AHD_AIC7901;
952
ahd->features = AHD_AIC7901_FE;
953
return (ahd_aic790X_setup(ahd));
954
}
955
956
static int
957
ahd_aic7901A_setup(struct ahd_softc *ahd)
958
{
959
960
ahd->chip = AHD_AIC7901A;
961
ahd->features = AHD_AIC7901A_FE;
962
return (ahd_aic790X_setup(ahd));
963
}
964
965
static int
966
ahd_aic7902_setup(struct ahd_softc *ahd)
967
{
968
ahd->chip = AHD_AIC7902;
969
ahd->features = AHD_AIC7902_FE;
970
return (ahd_aic790X_setup(ahd));
971
}
972
973
static int
974
ahd_aic790X_setup(struct ahd_softc *ahd)
975
{
976
aic_dev_softc_t pci;
977
u_int rev;
978
979
pci = ahd->dev_softc;
980
rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
981
if (rev < ID_AIC7902_PCI_REV_A4) {
982
printf("%s: Unable to attach to unsupported chip revision %d\n",
983
ahd_name(ahd), rev);
984
aic_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2);
985
return (ENXIO);
986
}
987
ahd->channel = aic_get_pci_function(pci) + 'A';
988
if (rev < ID_AIC7902_PCI_REV_B0) {
989
/*
990
* Enable A series workarounds.
991
*/
992
ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG
993
| AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG
994
| AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG
995
| AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG
996
| AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG
997
| AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG
998
| AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG
999
| AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG
1000
| AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG
1001
| AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG
1002
| AHD_FAINT_LED_BUG;
1003
1004
/*
1005
* IO Cell parameter setup.
1006
*/
1007
AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
1008
1009
if ((ahd->flags & AHD_HP_BOARD) == 0)
1010
AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA);
1011
} else {
1012
u_int devconfig1;
1013
1014
ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS
1015
| AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY;
1016
ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG;
1017
1018
/*
1019
* Some issues have been resolved in the 7901B.
1020
*/
1021
if ((ahd->features & AHD_MULTI_FUNC) != 0)
1022
ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG
1023
| AHD_BUSFREEREV_BUG;
1024
1025
/*
1026
* IO Cell parameter setup.
1027
*/
1028
AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
1029
AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB);
1030
AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF);
1031
1032
/*
1033
* Set the PREQDIS bit for H2B which disables some workaround
1034
* that doesn't work on regular PCI busses.
1035
* XXX - Find out exactly what this does from the hardware
1036
* folks!
1037
*/
1038
devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
1039
aic_pci_write_config(pci, DEVCONFIG1,
1040
devconfig1|PREQDIS, /*bytes*/1);
1041
devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
1042
}
1043
1044
return (0);
1045
}
1046
1047