DragonFlyBSD Kernel Audit
sys/dev/disk/sili/sili.h
← back
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
/*
 * Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * $OpenBSD: sili.c,v 1.147 2009/02/16 21:19:07 miod Exp $
 */

#if defined(__DragonFly__)
#include "sili_dragonfly.h"
#else
#error "build for OS unknown"
#endif
#include "pmreg.h"
#include "atascsi.h"

/* change to SILI_DEBUG for dmesg spam */
#define NO_SILI_DEBUG

#ifdef SILI_DEBUG
#define DPRINTF(m, f...) do { if ((silidebug & (m)) == (m)) kprintf(f); } \
    while (0)
#define SILI_D_TIMEOUT		0x00
#define SILI_D_VERBOSE		0x01
#define SILI_D_INTR		0x02
#define SILI_D_XFER		0x08
int silidebug = SILI_D_VERBOSE;
#else
#define DPRINTF(m, f...)
#endif

/*
 * BAR0 - Global Registers		128-byte aligned, 128-byte region
 * BAR1 - Port Registers and LRAM	32KB-aligned
 * BAR2 - Indirect I/O registers	(we don't use this)
 */

/*
 * Port-N Slot Status.
 *
 * NOTE: Mirrors SILI_PREG_SLOTST
 */
#define SILI_REG_SLOTST(n)	(0x0000 + ((n) * 4))
#define SILI_REG_SLOTST_ATTN	0x80000000	/* attention required */

#define SILI_REG_GCTL		0x0040		/* Global Control	*/
#define SILI_REG_GCTL_PORTEN(n)	(1 << (n))	/* Port interrupt ena	*/
#define SILI_REG_GCTL_300CAP	0x01000000	/* 3Gb/s capable (R)	*/
#define SILI_REG_GCTL_I2C_IEN	0x20000000	/* I2C Int enable	*/
#define SILI_REG_GCTL_MSIACK	0x40000000	/* MSI Ack W1C		*/
#define SILI_REG_GCTL_GRESET	0x80000000	/* global reset */

#define SILI_REG_GINT		0x0044		/* Global Interrupt Status */
#define SILI_REG_GINT_I2C	0x20000000	/* I2C Int Status	*/
#define SILI_REG_GINT_PORTST(n)	(1 << (n))	/* Port interrupt stat  */
#define SILI_REG_GINT_PORTMASK	0x0000FFFF

/*
 * Most bits in phyconf should not be modified.  Setting the low four bits
 * to 1's, all channel Tx outputs spread spectrum clocking.
 */
#define SILI_REG_PHYCONF	0x0048		/* PHY Configuration */
#define SILI_REG_PHYCONF_ALLSS	0x000F		/* spread spectrum tx */

/*
 * BIST_CTL_TEN -	Enable data paths for running data loopback BIST
 * BIST_CTL_TPAT -	Select repeating pattern (1) or pseudo-random
 *			pattern (0)
 * BIST_CTL_RXSEL-	Select the rx port for pattern comparison
 * BIST_CTL_TXSEL-	Select the tx ports that transmit loopback data
 */
#define SILI_REG_BIST_CTL	0x0050
#define SILI_REG_BIST_CTL_TEN	0x80000000
#define SILI_REG_BIST_CTL_TPAT	0x40000000
#define SILI_REG_BIST_CTL_RXSEL(n) ((n) << 16)
#define SILI_REG_BIST_CTL_TXSEL(n) (1 << (n))

#define SILI_REG_BIST_PATTERN	0x0054	/* 32 bit pattern */

/*
 * GOOD is set to 1 on BIST initiation, and reset to 0 on the first
 * comparison failure.
 */
#define SILI_REG_BIST_STATUS	0x0058
#define SILI_REG_BIST_STATUS_CNT  0x000007FF	/* pattern counter */
#define SILI_REG_BIST_STATUS_GOOD 0x80000000	/* set to 0 on compare fail */

#define SILI_REG_I2C_CTL	0x0060
#define SILI_REG_I2C_CTL_START	0x00000001
#define SILI_REG_I2C_CTL_STOP	0x00000002
#define SILI_REG_I2C_CTL_NACK	0x00000004	/* send nack on data byte rx */
#define SILI_REG_I2C_CTL_TFDATA	0x00000008	/* set to initiate txfer     */
						/* to/from data buffer	     */
#define SILI_REG_I2C_CTL_MABORT	0x00000010	/* set w/STOP to send stop   */
						/* without first xfering a   */
						/* byte			     */
#define SILI_REG_I2C_CTL_SCLEN	0x00000020	/* clock-en for master mode  */
#define SILI_REG_I2C_CTL_UNITEN	0x00000040	/* enable controller 	     */
#define SILI_REG_I2C_CTL_GCALLD	0x00000080	/* Disable detect of a       */
						/* general call address      */
#define SILI_REG_I2C_CTL_TXBEI	0x00000100	/* xmit buffer empty int en  */
#define SILI_REG_I2C_CTL_RXBFI	0x00000200	/* rx buffer full int en     */
#define SILI_REG_I2C_CTL_BERRI	0x00000400	/* bus error int en	     */
#define SILI_REG_I2C_CTL_STOPI	0x00000800	/* stop detect int en	     */
#define SILI_REG_I2C_CTL_ARBLI	0x00001000	/* arb loss int en	     */
#define SILI_REG_I2C_CTL_ARBDI	0x00002000	/* arb detect int en	     */
#define SILI_REG_I2C_CTL_UNITRS	0x00004000	/* reset I2C controller	     */
#define SILI_REG_I2C_CTL_FASTM	0x00008000	/* 400kbit/s (else 100kbit/s)*/

#define SILI_REG_I2C_STS	0x0064
#define SILI_REG_I2C_STS_RW	0x00000001
#define SILI_REG_I2C_STS_ACKSTS	0x00000002	/* ack/nack status(R) last   */
						/* ack or nack sent or rcvd  */
#define SILI_REG_I2C_STS_UNTBSY	0x00000004	/* unit busy (R)	     */
#define SILI_REG_I2C_STS_BUSBSY	0x00000008	/* bus busy with activity(R) */
						/* other then from controller*/
#define SILI_REG_I2C_STS_STOPDT	0x00000010	/* stop detect (R/W1C)	     */
#define SILI_REG_I2C_STS_ARBLD	0x00000020	/* arb loss detect   (R/W1C) */
#define SILI_REG_I2C_STS_TXBED	0x00000040	/* tx buffer empty   (R)     */
#define SILI_REG_I2C_STS_RXBFD	0x00000080	/* rx buffer full    (R/W1C) */
#define SILI_REG_I2C_STS_GCALLD	0x00000100	/* Gen Call detect   (R/W1C) */
#define SILI_REG_I2C_STS_SADDRD	0x00000200	/* Slave addr detect (R/W1C) */
#define SILI_REG_I2C_STS_BERRD	0x00000400	/* Bus error detect  (R/W1C) */

#define SILI_REG_I2C_SADDR	0x0068		/* our slave address         */
#define SILI_REG_I2C_SADDR_MASK	0x0000003F	/* 6 bits                    */

#define SILI_REG_I2C_DATA	0x006C		/* data buffer (8 bits)      */

#define SILI_REG_FLASH_ADDR	0x0070		/* Flash control & addr reg  */
#define SILI_REG_FLASH_ADDR_MEMPRS 0x04000000	/* Flash memory present	     */
#define SILI_REG_FLASH_ADDR_GPIOEN 0x80000000	/* use flash data pins for   */
						/* GPIO */
#define SILI_REG_FLASH_ADDR_MEMST  0x02000000	/* Mem Access Start (R/W)    */
						/* (clears on op complete)   */
#define SILI_REG_FLASH_ADDR_MEMRD  0x01000000	/* 0=write, 1=read           */
#define SILI_REG_FLASH_ADDR_MASK   0x0003FFFF	/* 18 bit memory address     */

/*
 * NOTE: In order to set a GPIO pin to read the DATA bit must be written to
 *       1and the DCTL (drain control) bit must be written to 1 as well
 *       to make it open-drain only (drive on low only).
 */
#define SILI_REG_GPIO		0x0074
#define SILI_REG_GPIO_DATA_SHIFT	0	/* 8 bits Flash or GPIO data */
#define SILI_REG_GPIO_TDET_SHIFT	8	/* 8 bits transition detect  */
#define SILI_REG_GPIO_DCTL_SHIFT	16	/* 8 bits drain control      */

/*
 * Per-port registers
 *
 */

#define SILI_PORT_REGION(port)	(8192 * (port))
#define SILI_PORT_SIZE		8192
#define SILI_PREG_LRAM		0x0000		/* 0x0000-0x0F7F	     */
#define SILI_PREG_LRAM_SLOT(n)	(0x0000 + (128 * (n)))

#define SILI_PREG_LRAM_SLOT_FIS	0x0000		/* Current FIS and Control   */
#define SILI_PREG_LRAM_DMA0	0x0020		/* DMA Entry 0 or ATAPI cmd  */
#define SILI_PREG_LRAM_DMA1	0x0030		/* DMA Entry 0 or ATAPI cmd  */
#define SILI_PREG_LRAM_CMDACT	0x0040		/* Cmd Act Reg (actual) 64b  */
#define SILI_PREG_LRAM_DMATAB	0x0040		/* Scatter Gather Table      */

/*
 * Each port has a port status and qactive register for each target behind
 * the port multiplier, if there is a port multiplier.
 *
 * SERVICE - Service received from device, service command from controller
 *	     not yet acknowledged.
 *
 * LEGACY  - One or more legacy queued commands is outstanding.
 *
 * NATIVE  - One or more NCQ queued commands is outstanding.
 *
 * VBSY    - A virtual device busy indicating that a command has been issued
 *	     to the device and the device has not yet sent the final D2H
 *	     register FIS, or that a data transfer is in progress.
 *
 * The PM_QACTIVE register contains a demultiplexed bitmap of slots queued
 * to each target behind the port multiplier.
 *
 */
#define SILI_PREG_PM_STATUS(n)	(0x0F80 + (8 * (n)))
#define SILI_PREG_PM_QACTIVE(n)	(0x0F84 + (8 * (n)))

#define SILI_PREG_PM_STATUS_SERVICE	0x00010000	/* Service pending */
#define SILI_PREG_PM_STATUS_LEGACY	0x00008000	/* Legacy outstanding*/
#define SILI_PREG_PM_STATUS_NATIVE	0x00004000	/* NCQ outstanding */
#define SILI_PREG_PM_STATUS_VBSY	0x00002000	/* virtual dev busy */
#define SILI_PREG_PM_STATUS_EXEC_SHIFT	8		/* last active slot */
#define SILI_PREG_PM_STATUS_EXEC_MASK	0x1F
#define SILI_PREG_PM_STATUS_PIO_MASK	0xFF		/* last PIO setup   */

/*
 * NOTE: SILI_PREG_STATUS uses the same address as SILI_PREG_CTL_SET,
 * but for read.
 */
#define SILI_PREG_STATUS	0x1000		/* Port Control Status (R)   */
#define SILI_PREG_STATUS_READY	0x80000000	/* Port Ready          (R)   */
#define SILI_PREG_STATUS_SLOT	0x001F0000	/* Active Slot         (R)   */
#define SILI_PREG_STATUS_SLOT_SHIFT	16	/* Shift value		     */
#define SILI_PREG_STATUS_MASK	0x0200FFFF	/* see PREG_CTL_xxx          */

/*
 * NOTE: Reset sequence.  Set CTL_RESET, Clear CTL_RESET, then Wait for
 *       the port to become ready.
 *
 * NOTE: NOAUTOCC.  If set to 1 a 1 must be written to the command completion
 *	 bit in the port interrupt status register to clear it.  When set to
 *	 0 then reading the port slot status register will automatically clear
 *       the command completion interrupt.
 *
 * NOTE: ATA16 controls whether a PACKET mode command is 12 or 16 bytes.
 *
 * NOTE: RESUME if set to 1 processing is enabled for outstanding commands
 *       to additional targets connected to a port multiplier after a command
 *	 error has occured.  When set the internal BUSY status will be set
 *	 for the target that errored, preventing additional commands from
 *       being sent until a Port Initialize operation is performed.
 *
 * NOTE: 32BITDMA if 1 causes a write to the low 32 bits of a Command
 *	 Activation register to  copy PREG_32BIT_ACTUA to the upper 32
 *       bits and start command execution.  If 0 you must write to the
 *       low 32 bits and then the high 32 bits and your write to the
 *       high 32 bits will start command execution.
 *
 * NOTE: OOB_BYP is set on global reset and not changed by a port reset.
 */
#define SILI_PREG_CTL_SET	0x1000		/* Port Control Set    (W1S) */
#define SILI_PREG_CTL_CLR	0x1004		/* Port Control Clear  (W1C) */
#define SILI_PREG_CTL_RESET	0x00000001	/* Hold port in reset        */
#define SILI_PREG_CTL_DEVRESET	0x00000002	/* Device reset              */
						/* (Self clearing)           */
#define SILI_PREG_CTL_INIT	0x00000004	/* Port initialize           */
						/* (Self clearing)           */
#define SILI_PREG_CTL_NOAUTOCC	0x00000008
#define SILI_PREG_CTL_NOLED	0x00000010	/* Disable the LED port      */
						/* activity indicator.       */
#define SILI_PREG_CTL_ATA16	0x00000020	/* 0=12 byte 1=16 byte       */
#define SILI_PREG_CTL_RESUME	0x00000040	/* PM special error handling */
#define SILI_PREG_CTL_TXBIST	0x00000080	/* transmit a BIST FIS       */
#define SILI_PREG_CTL_CONT_DIS	0x00000100	/* no CONT on repeat primitves*/
#define SILI_PREG_CTL_NOSCRAM	0x00000200	/* Disable link scrambler    */
#define SILI_PREG_CTL_32BITDMA	0x00000400	/* see above 		     */
#define SILI_PREG_CTL_ACC_ILCK	0x00000800	/* accept interlocked FIS rx */
						/* (Self clearing)           */
#define SILI_PREG_CTL_REJ_ILCK	0x00001000	/* reject interlocked FIS rx */
						/* (Self clearing)           */
#define SILI_PREG_CTL_PMA	0x00002000	/* Enable PM support         */
#define SILI_PREG_CTL_AUTO_ILCK	0x00004000	/* Auto interlock accept     */
#define SILI_PREG_CTL_LEDON	0x00008000	/* LED on		     */
#define SILI_PREG_CTL_OOB_BYP	0x02000000	/* Bypass OOB initialization */

/*
 * Status bits in the upper half of the register report the actual condition
 * while the status bits in the lower half of the register are masked by
 * the interrupt enable bits or threshold registers.  Writing a 1 to either
 * version will clear it.
 *
 * NOTE: The steering bits written to INT_ENABLE will not show up in the
 *       status register.  The INT_ENABLE/INT_DISABLE registers are R+W1S
 *	 or R+W1C and thus can be read.
 *
 * NOTE: PHYRDYCHG, COMWAKE, UNRECFIS, DEVEXCHG: Can be cleared by writing
 *	 W1C either here or via the DIAG.xxx bit bit in SError.
 */
#define SILI_PREG_INT_STATUS	0x1008		/* Control clear	     */
#define SILI_PREG_INT_ENABLE	0x1010		/* Interrupt Enable Set      */
#define SILI_PREG_INT_DISABLE	0x1014		/* Interrupt Enable Clear    */

#define SILI_PREG_INT_STEER(n)	((n) << 30)	/* Port Int -> INTA...INTD   */
#define SILI_PREG_INT_CCOMPLETE	0x00000001	/* one or more cmds completed*/
#define SILI_PREG_INT_CERROR	0x00000002	/* read port error register  */
						/* to get error              */
#define SILI_PREG_INT_READY	0x00000004	/* Port is ready for cmds    */
#define SILI_PREG_INT_PMCHANGE	0x00000008	/* Change in power mng state */
#define SILI_PREG_INT_PHYRDYCHG	0x00000010	/* Mirrors DIAG.N in SError  */
#define SILI_PREG_INT_COMWAKE	0x00000020	/* Mirrors DIAG.W in SError  */
#define SILI_PREG_INT_UNRECFIS	0x00000040	/* Mirrors DIAG.F in SError  */
#define SILI_PREG_INT_DEVEXCHG	0x00000080	/* Mirrors DIAG.X in SError  */
#define SILI_PREG_INT_DECODE	0x00000100	/* 8b/10b dec err  cnt > thr */
#define SILI_PREG_INT_CRC	0x00000200	/* CRC err       count > thr */
#define SILI_PREG_INT_HANDSHK	0x00000400	/* Handshake err count > thr */
#define SILI_PREG_INT_SDB	0x00000800	/* Set Device Bits (SNotify) */
#define SILI_PREG_INT_SHIFT	16		/* shift upper bits of status*/

#define SILI_PREG_IST_CCOMPLETE	0x00010000	/* one or more cmds completed*/
#define SILI_PREG_IST_CERROR	0x00020000	/* read port error register  */
						/* to get error              */
#define SILI_PREG_IST_READY	0x00040000	/* Port is ready for cmds    */
#define SILI_PREG_IST_PMCHANGE	0x00080000	/* Change in power mng state */
#define SILI_PREG_IST_PHYRDYCHG	0x00100000	/* Mirrors DIAG.N in SError  */
#define SILI_PREG_IST_COMWAKE	0x00200000	/* Mirrors DIAG.W in SError  */
#define SILI_PREG_IST_UNRECFIS	0x00400000	/* Mirrors DIAG.F in SError  */
#define SILI_PREG_IST_DEVEXCHG	0x00800000	/* Mirrors DIAG.X in SError  */
#define SILI_PREG_IST_DECODE	0x01000000	/* 8b/10b dec err  cnt > thr */
#define SILI_PREG_IST_CRC	0x02000000	/* CRC err       count > thr */
#define SILI_PREG_IST_HANDSHK	0x04000000	/* Handshake err count > thr */
#define SILI_PREG_IST_SDB	0x08000000	/* Set Device Bits (SNotify) */

#define SILI_PREG_INT_MASK	(SILI_PREG_INT_CCOMPLETE |		\
				 SILI_PREG_INT_CERROR |			\
				 SILI_PREG_INT_READY |			\
				 SILI_PREG_INT_PMCHANGE |		\
				 SILI_PREG_INT_PHYRDYCHG |		\
				 SILI_PREG_INT_COMWAKE |		\
				 SILI_PREG_INT_UNRECFIS |		\
				 SILI_PREG_INT_DEVEXCHG |		\
				 SILI_PREG_INT_DECODE |			\
				 SILI_PREG_INT_CRC |			\
				 SILI_PREG_INT_HANDSHK |		\
				 SILI_PREG_INT_SDB)
#define SILI_PREG_IST_MASK	(SILI_PREG_INT_MASK << 16)

#define SILI_PFMT_INT_STATUS	"\020" 			\
				"\034SDB"		\
				"\033HANDSHK"		\
				"\032CRC"		\
				"\031DECODE"		\
				"\030DEVEXCHG"		\
				"\027UNRECFIS"		\
				"\026COMWAKE"		\
				"\025PHYRDYCHG"		\
				"\024PMCHANGE"		\
				"\023READY"		\
				"\022ERROR"		\
				"\021COMPLETE"		\
							\
				"\014SDBm"		\
				"\013HANDSHKm"		\
				"\012CRCm"		\
				"\011DECODEm"		\
				"\010DEVEXCHGm"		\
				"\007UNRECFISm"		\
				"\006COMWAKEm"		\
				"\005PHYRDYCHGm"	\
				"\004PMCHANGEm"		\
				"\003READYm"		\
				"\002ERRORm"		\
				"\001COMPLETEm"

/*
 * 32BIT_ACTUA is only used when DMA is 32 bits.  It is typically set to 0.
 */
#define SILI_PREG_32BIT_ACTUA	0x101C		/* 32b activation upper addr */

/*
 * Writing a slot number 0-30 to CMD_FIFO starts the command from LRAM.
 */
#define SILI_PREG_CMD_FIFO	0x1020		/* Command execution FIFO    */

/*
 * If the port is interrupted via INT_CERROR this register contains
 * the error code.
 *
 * Most errors write the task file register back to the PRB slot for host
 * scrutiny.
 */
#define SILI_PREG_CERROR	0x1024		/* Command error             */
#define SILI_PREG_CERROR_DEVICE		1	/* ERR set in D2H FIS        */
#define SILI_PREG_CERROR_SDBERROR	2	/* ERR set in SDB from device*/
#define SILI_PREG_CERROR_DATAFISERR	3	/* Sil3132 error on send     */
#define SILI_PREG_CERROR_SENDFISERR	4	/* Sil3132 error on send     */
#define SILI_PREG_CERROR_BADSTATE	5	/* Sil3132 inconsistency     */
#define SILI_PREG_CERROR_DIRECTION	6	/* DMA direction mismatch    */
#define SILI_PREG_CERROR_UNDERRUN	7	/* DMA SG H2D list too small */
#define SILI_PREG_CERROR_OVERRUN	8	/* DMA SG D2H list too small */
#define SILI_PREG_CERROR_LLOVERUN	9	/* Too much data from device */
#define SILI_PREG_CERROR_PKTPROTO	11	/* Packet protocol error     */
#define SILI_PREG_CERROR_BADALIGN	16	/* Bad SG list, not 8-byte   */
						/* aligned                   */
#define SILI_PREG_CERROR_PCITGTABRT	17	/* PCI target abort received */
#define SILI_PREG_CERROR_PCIMASABRT	18	/* PCI master abort received */
#define SILI_PREG_CERROR_PCIPARABRT	19	/* PCI parity abort received */
#define SILI_PREG_CERROR_PRBALIGN	24	/* PRB addr not 8-byte algned*/
#define SILI_PREG_CERROR_PCITGTABRT2	25	/* During fetch of PRB       */
#define SILI_PREG_CERROR_PCIMASABRT2	26	/* During fetch of PRB       */
#define SILI_PREG_CERROR_PCIPARABRT3	33	/* During data transfer      */
#define SILI_PREG_CERROR_PCITGTABRT3	34	/* During data transfer      */
#define SILI_PREG_CERROR_PCIMASABRT3	35	/* During data transfer      */
#define SILI_PREG_CERROR_SERVICE	36	/* FIS received during tx    */
						/* phase                     */

/*
 * Port FIS Configuration.  Fir each possible FIS type, a 2-bit code
 * defines the desired reception behavior as follows.  Bits [1:0] define
 * the code for all other FIS types not defined by [29:2].
 *
 *	00 Accept FIS without interlock
 *	01 Reject FIS without interlock
 *	10 Interlock FIS
 *	11 (reserved)
 *
 * FIS Code	Name			Start	Default
 * --------	------			------	-------
 *    ----	(reserved)		30
 *    0x27	Register (H2D)		28	01
 *    0x34	Register (D2H)		26	00
 *    0x39	DMA Activate		24	00
 *    0x41	DMA Setup		22	00
 *    0x46	Data			20	00
 *    0x58	BIST Activate		18	00
 *    0x5F	PIO Setup		16	00
 *    0xA1	Set Device Bits		14	00
 *    0xA6	(reserved)		12	01
 *    0xB8	(reserved)		10	01
 *    0xBF	(reserved)		8	01
 *    0xC7	(reserved)		6	01
 *    0xD4	(reserved)		4	01
 *    0xD9	(reserved)		2	01
 * ALL OTHERS	(reserved)		0	01
 */
#define SILI_PREG_FIS_CONFIG	0x1028		/* FIS configuration         */

/*
 * The data FIFO is 2KBytes in each direction.
 *
 * When DMAing from the device the Write Request Threshold is used.
 * When DMAing to the device the Read Request Threshold is used.
 *
 * The threshold can be set from 1-2040 bytes (write 0-2039), in multiples
 * of 8 bits.  The low 3 bits are hardwired to 0.  A value of 0 causes a
 * request whenever possible.
 */
#define SILI_PREG_FIFO_CTL	0x102C		/* PCIex request FIFO thresh */
#define SILI_PREG_FIFO_CTL_READ_SHIFT	0
#define SILI_PREG_FIFO_CTL_WRITE_SHIFT	16
#define SILI_PREG_FIFO_CTL_MASK	0xFF
#define SILI_PREG_FIFO_CTL_ENCODE(rlevel, wlevel)  (rlevel | (wlevel << 16))

/*
 * Error counters and thresholds.  The counter occupies the low 16 bits
 * and the threshold occupies the high 16 bits.  The appropriate interrupt
 * occurs when the counter exceeds the threshold.  Clearing the interrupt
 * clears the counter as well.  A threshold of 0 disables the interrupt
 * assertion and masks the interrupt status bit in the port interrupt status
 * register.
 */
#define SILI_PREG_CTR_DECODE	0x1040		/* 8B/10B Decode Error Ctr   */
#define SILI_PREG_CTR_CRC	0x1044		/* CRC Error Counter         */
#define SILI_PREG_CTR_HANDSHK	0x1048		/* Handshake Error Counter   */

/*
 * NOTE: This register is reset only by the global reset and will not be
 * 	 reset by a port reset.
 *
 * NOTE: Bits 15:5 configure the PHY and should not be changed unless you
 *	 want to blow up the part.
 *
 *	 Bits 4:0 define the nominal output swing for the transmitter
 *	 and are set to 0x0C by default.  Generally speaking, don't mess
 *	 with them.
 */
#define SILI_PREG_PHY_CONFIG	0x1050		/* Handshake Error Counter   */
#define SILI_PREG_PHY_CONFIG_AMP_MASK	0x1F

#define SILI_PREG_SLOTST	0x1800		/* Slot Status		     */
#define SILI_PREG_SLOTST_ATTN	0x80000000	/* 0-30 bit for each slot */

/*
 * Shadow command activation register, shadows low or high 32 bits
 * of actual command activation register.
 */
#define SILI_PREG_CMDACT(n)	(0x1C00 + (8 * (n)))

/*
 * Port Context Register.  Contains the port multipler target (0-15) and
 * the command slot (0-31) for the PM port state machine.
 *
 * Upon a processing halt due to a device specific error, the port multipler
 * target is the one that returned the error status.
 *
 * The command slot is NOT deterministic in this case and should not be
 * assumed valid.  Use READ LOG EXTENDED to determine the tag number.
 * However, the documentation does appear to indicate that for non-NCQ
 * errors the command slot does contain the tag that errored (since there
 * will be only one truely active).
 */
#define SILI_PREG_CONTEXT		0x1E04
#define SILI_PREG_CONTEXT_SLOT_MASK	0x1F
#define SILI_PREG_CONTEXT_PMPORT_MASK	0x0F
#define SILI_PREG_CONTEXT_SLOT_SHIFT	0
#define SILI_PREG_CONTEXT_PMPORT_SHIFT	5

/*
 * SControl register - power management, speed negotiation, and COMRESET
 *		       operation.
 */
#define SILI_PREG_SCTL			0x1F00

/*
 * PMP: Identify the PM port for accessing the SActive register and some
 *	bit fields of the Diagnostic registers.
 */
#define SILI_PREG_SCTL_PMP		0x000F0000
#define SILI_PREG_SCTL_PMP_SHIFT	16

/*
 * SPM: It is unclear from mode 4 is.  "Transition from a power management
 *	state initiate (ComWake asserted)".  When setting a state, the field
 *	will self-reset to 0 as soon as the action is initiated.
 */
#define SILI_PREG_SCTL_SPM		0x0000F000
#define  SILI_PREG_SCTL_SPM_NONE	0x00000000
#define  SILI_PREG_SCTL_SPM_PARTIAL	0x00010000
#define  SILI_PREG_SCTL_SPM_SLUMBER	0x00020000
#define  SILI_PREG_SCTL_SPM_FROM	0x00040000

/*
 * IPM: Identify interface power management states not supported (bits).
 */
#define SILI_PREG_SCTL_IPM		0x00000F00
#define  SILI_PREG_SCTL_IPM_NONE	0x00000000
#define  SILI_PREG_SCTL_IPM_NPARTIAL	0x00000100
#define  SILI_PREG_SCTL_IPM_NSLUMBER	0x00000200

/*
 * SPD: Limit speed negotiation (0000 for no restrictions)
 */
#define	SILI_PREG_SCTL_SPD		0x000000F0
#define	 SILI_PREG_SCTL_SPD_NONE	0x00000000
#define	 SILI_PREG_SCTL_SPD_GEN1	0x00000010
#define	 SILI_PREG_SCTL_SPD_GEN2	0x00000020

/*
 * DET: Control host adapter device detection and interface initialization
 */
#define	SILI_PREG_SCTL_DET		0x0000000F
#define	 SILI_PREG_SCTL_DET_NONE	0x00000000	/* nop/complete     */
#define	 SILI_PREG_SCTL_DET_INIT	0x00000001	/* hold in COMRESET */

/*
 * SStatus register - Probe status
 */
#define SILI_PREG_SSTS			0x1F04
#define  SILI_PREG_SSTS_IPM		0x00000F00
#define  SILI_PREG_SSTS_IPM_NOCOMM	0x00000000
#define  SILI_PREG_SSTS_IPM_ACTIVE	0x00000100
#define  SILI_PREG_SSTS_IPM_PARTIAL	0x00000200
#define  SILI_PREG_SSTS_IPM_SLUMBER	0x00000600

#define SILI_PREG_SSTS_SPD		0x000000F0
#define  SILI_PREG_SSTS_SPD_NONE	0x00000000
#define  SILI_PREG_SSTS_SPD_GEN1	0x00000010
#define  SILI_PREG_SSTS_SPD_GEN2	0x00000020

#define SILI_PREG_SSTS_DET		0x0000000F
#define  SILI_PREG_SSTS_DET_NOPHY	0x00000000	/* no dev, no phy */
#define  SILI_PREG_SSTS_DET_DEV_NE	0x00000001	/* dev, no phy	*/
#define  SILI_PREG_SSTS_DET_DEV		0x00000003	/* dev and phy	*/
#define  SILI_PREG_SSTS_DET_OFFLINE	0x00000004	/* BIST/LOOPBACK */

/*
 * These are mostly R/W1C bits.  "B", "C", and "H" operate independantly
 * and depend on the corresponding error counter register.
 */
#define SILI_PREG_SERR			0x1F08
#define  SILI_PREG_SERR_ERR_I		(1<<0) /* Recovered Data Integrity */
#define  SILI_PREG_SERR_ERR_M		(1<<1) /* Recovered Communications */
#define  SILI_PREG_SERR_ERR_T		(1<<8) /* Transient Data Integrity */
#define  SILI_PREG_SERR_ERR_C		(1<<9) /* Persistent Comm/Data */
#define  SILI_PREG_SERR_ERR_P		(1<<10) /* Protocol */
#define  SILI_PREG_SERR_ERR_E		(1<<11) /* Internal */
#define  SILI_PREG_SERR_DIAG_N		(1<<16) /* PhyRdy Change */
#define  SILI_PREG_SERR_DIAG_I		(1<<17) /* Phy Internal Error */
#define  SILI_PREG_SERR_DIAG_W		(1<<18) /* Comm Wake */
#define  SILI_PREG_SERR_DIAG_B		(1<<19) /* 10B to 8B Decode Error */
#define  SILI_PREG_SERR_DIAG_D		(1<<20) /* Disparity Error */
#define  SILI_PREG_SERR_DIAG_C		(1<<21) /* CRC Error */
#define  SILI_PREG_SERR_DIAG_H		(1<<22) /* Handshake Error */
#define  SILI_PREG_SERR_DIAG_S		(1<<23) /* Link Sequence Error */
#define  SILI_PREG_SERR_DIAG_T		(1<<24) /* Transport State Trans Err */
#define  SILI_PREG_SERR_DIAG_F		(1<<25) /* Unknown FIS Type */
#define  SILI_PREG_SERR_DIAG_X		(1<<26) /* Exchanged */

#define  SILI_PFMT_SERR	"\020" 	\
			"\033DIAG.X" "\032DIAG.F" "\031DIAG.T" "\030DIAG.S" \
			"\027DIAG.H" "\026DIAG.C" "\025DIAG.D" "\024DIAG.B" \
			"\023DIAG.W" "\022DIAG.I" "\021DIAG.N"		    \
			"\014ERR.E" "\013ERR.P" "\012ERR.C" "\011ERR.T"	    \
			"\002ERR.M" "\001ERR.I"

/*
 * SACT provides indirect access to the Port Device QActive registers.
 * We have direct access and do not have to use this.
 */
#define SILI_PREG_SACT			0x1F0C

/*
 * Indicate which devices have sent a Set Device Bits FIS with Notifcation
 * set.  R/W1C
 */
#define SILI_PREG_SNTF			0x1F10

/*
 * Internal register space indirect register access via the PCI I/O space.
 * (This is for BIOSes running in 16-bit mode, we use the direct map).
 *
 * All offsets must be 4-byte aligned
 */
#define SILI_BAR2_GRO			0x0000	/* Global Register Offset */
#define SILI_BAR2_GRD			0x0004	/* Global Register Data */
#define SILI_BAR2_PRO			0x0008	/* Port Register Offset */
#define SILI_BAR2_PRD			0x000C	/* Port Register Data */

/*
 * SILI mapped structures
 */
struct sili_sge {
	u_int64_t		sge_paddr;
	u_int32_t		sge_count;
	u_int32_t		sge_flags;
} __packed;

#define SILI_SGE_FLAGS_TRM	0x80000000	/* last SGE associated w/cmd */
#define SILI_SGE_FLAGS_LNK	0x40000000	/* link to SGE array	*/
#define SILI_SGE_FLAGS_DRD	0x20000000	/* discard (ign sge_paddr) */
#define SILI_SGE_FLAGS_XCF	0x10000000	/* external cmd fetch	*/

/*
 * Each sge is 16 bytes.
 *
 * We want our prb structure to be power-of-2 aligned (it is required to be
 * at least 8-byte aligned).  the prb base header is 4 SGE's but includes 2
 * SGE's within it.
 * The prb structure also can't cross a 64KB boundary, and thus can only
 * have a maximum size of 65536 / 16 / 32  == ~128 entries (128 - 4)
 */
#define SILI_MAX_SGET		(128 - 4)
#define SILI_MAX_PMPORTS	16
#define SILI_MAXPHYS		(256 * 1024)	/* 256 KB */

#if SILI_MAXPHYS / PAGE_SIZE + 1 > (SILI_MAX_SGET * 3 / 4)
#error "SILI_MAX_SGET is not big enough"
#endif


/*
 * The PRB
 *
 * NOTE: ATAPI PACKETS.  The packet is stored in prb_sge[0] and sge[1]
 *			 is the first SGE.
 *
 * NOTE: LRAM PRB.  The PRB layout in the LRAM includes a single struct
 *	 sili_sge[4].  We could use the LRAM for the PRB and host memory
 *	 for an external SGE array, but LRAM in general has some serious
 *	 hardware bugs.
 *
 *	 From linux: Reading the LRAM for a port while a command is
 *	 outstanding can corrupt DMA.  So we use a completely external PRB.
 */
struct sili_prb {
	u_int16_t		prb_control;
	u_int16_t		prb_override;
	u_int32_t		prb_xfer_count;
	union {
		struct ata_fis_h2d	h2d;
		struct ata_fis_d2h	d2h;
	} prb_fis;
	u_int32_t		prb_reserved1c;
	struct sili_sge		prb_sge_base[2];
	struct sili_sge		prb_sge[SILI_MAX_SGET];
} __packed;

#define prb_h2d		prb_fis.h2d
#define prb_d2h		prb_fis.d2h
#define prb_activation	prb_ext[0].sge_paddr
#define prb_packet(prb)	((u_int8_t *)&(prb)->prb_sge[0])
#define prb_sge_normal	prb_sge_base[0]
#define prb_sge_packet	prb_sge_base[1]

/*
 * NOTE: override may be left 0 and the SIL3132 will decode the
 *	 8-bit ATA command and use the correct protocol.
 */
#define SILI_PRB_CTRL_OVERRIDE	0x0001	/* use protocol field override	*/
#define SILI_PRB_CTRL_REXMIT	0x0002	/* ok to rexmit ext command	*/
#define SILI_PRB_CTRL_EXTCMD	0x0004	/* FIS fetched from host memory */
					/* (else from LRAM)		*/
#define SILI_PRB_CTRL_RECEIVE	0x0008	/* Reserve cmd slot to receive	*/
					/* an interlocked FIS		*/
#define SILI_PRB_CTRL_READ	0x0010	/* device to host data		*/
#define SILI_PRB_CTRL_WRITE	0x0020	/* host to device data		*/
#define SILI_PRB_CTRL_NOINT	0x0040	/* do not post int on completion*/
#define SILI_PRB_CTRL_SOFTRESET	0x0080	/* issue soft reset (special)	*/

#define SILI_PRB_OVER_ATAPI	0x0001
#define SILI_PRB_OVER_ATA	0x0002
#define SILI_PRB_OVER_NCQ	0x0004
#define SILI_PRB_OVER_READ	0x0008	/* device to host data */
#define SILI_PRB_OVER_WRITE	0x0010	/* host to device data */
#define SILI_PRB_OVER_RAW	0x0020	/* no protocol special case */

#define SILI_MAX_PORTS		16
#define SILI_MAX_CMDS		31	/* not 32 */

struct sili_dmamem {
	bus_dma_tag_t		adm_tag;
	bus_dmamap_t		adm_map;
	bus_dma_segment_t	adm_seg;
	bus_addr_t		adm_busaddr;
	caddr_t			adm_kva;
};
#define SILI_DMA_MAP(_adm)	((_adm)->adm_map)
#define SILI_DMA_DVA(_adm)	((_adm)->adm_busaddr)
#define SILI_DMA_KVA(_adm)	((void *)(_adm)->adm_kva)

struct sili_softc;
struct sili_port;
struct sili_device;

struct sili_ccb {
	/* ATA xfer associated with this CCB.  Must be 1st struct member. */
	struct ata_xfer		ccb_xa;
	struct callout          ccb_timeout;

	int			ccb_slot;
	struct sili_port	*ccb_port;

	bus_dmamap_t		ccb_dmamap;
	struct sili_prb		*ccb_prb;
	struct sili_prb		*ccb_prb_lram;
	u_int64_t		ccb_prb_paddr;	/* phys addr of prb */

	void			(*ccb_done)(struct sili_ccb *);

	TAILQ_ENTRY(sili_ccb)	ccb_entry;
};

struct sili_port {
	struct sili_softc	*ap_sc;
	bus_space_handle_t	ap_ioh;

	int			ap_num;
	int			ap_pmcount;
	int			ap_flags;
#define AP_F_BUS_REGISTERED	0x0001
#define AP_F_CAM_ATTACHED	0x0002
#define AP_F_IN_RESET		0x0004
#define AP_F_SCAN_RUNNING	0x0008
#define AP_F_SCAN_REQUESTED	0x0010
#define AP_F_SCAN_COMPLETED	0x0020
#define AP_F_IGNORE_IFS		0x0040
#define AP_F_UNUSED0200		0x0200
#define AP_F_ERR_CCB_RESERVED	0x0400
#define AP_F_REINIT_ACTIVE	0x0800
	int			ap_signal;	/* os per-port thread sig */
	thread_t		ap_thread;	/* os per-port thread */
	struct lock		ap_lock;	/* os per-port lock */
	struct lock		ap_sim_lock;	/* cam sim lock */
	struct lock		ap_sig_lock;	/* signal thread */
#define AP_SIGF_INIT		0x0001
#define AP_SIGF_TIMEOUT		0x0002
#define AP_SIGF_PORTINT		0x0004
#define AP_SIGF_STOP		0x8000
	struct cam_sim		*ap_sim;

	struct sili_prb		*ap_prbs;

	struct sili_dmamem	*ap_dmamem_prbs;/* separate sge tables	*/

	u_int32_t		ap_active;	/* active bmask		*/
	u_int32_t		ap_active_cnt;	/* active count		*/
	u_int32_t		ap_expired;	/* deferred expired bmask */
	struct sili_ccb		*ap_ccbs;
	struct sili_ccb		*ap_err_ccb;	/* used to read LOG page  */
	int			ap_run_flags;	/* used to check excl mode */

	TAILQ_HEAD(, sili_ccb)	ap_ccb_free;
	TAILQ_HEAD(, sili_ccb)	ap_ccb_pending;
	struct lock		ap_ccb_lock;

	int			ap_type;	/* ATA_PORT_T_xxx */
	int			ap_probe;	/* ATA_PROBE_xxx */
	struct ata_port		*ap_ata;

	u_int32_t		ap_state;
#define AP_S_NORMAL			0
#define AP_S_FATAL_ERROR		1

	/* For error recovery. */
	u_int8_t		*ap_err_scratch;

	char			ap_name[16];
};

#define PORTNAME(_ap)		((_ap)->ap_name)
#define ATANAME(_ap, _at)	((_at) ? (_at)->at_name : (_ap)->ap_name)

struct sili_softc {
	device_t		sc_dev;
	const struct sili_device *sc_ad;	/* special casing */

	struct resource		*sc_irq;	/* bus resources */
	struct resource		*sc_regs;	/* bus resources */
	struct resource		*sc_pregs;	/* bus resources */
	bus_space_tag_t		sc_iot;		/* split from sc_regs */
	bus_space_handle_t	sc_ioh;		/* split from sc_regs */
	bus_space_tag_t		sc_piot;	/* split from sc_pregs */
	bus_space_handle_t	sc_pioh;	/* split from sc_pregs */

	int			sc_irq_type;
	int			sc_rid_irq;	/* saved bus RIDs */
	int			sc_rid_regs;
	int			sc_rid_pregs;

	void			*sc_irq_handle;	/* installed irq vector */

	bus_dma_tag_t		sc_tag_prbs;
	bus_dma_tag_t		sc_tag_data;

	int			sc_flags;
#define SILI_F_NO_NCQ			0x0001
#define SILI_F_IGN_FR			0x0002
#define SILI_F_INT_GOOD			0x0004
#define SILI_F_64BIT			0x0008
#define SILI_F_300			0x0010
#define SILI_F_NCQ			0x0020
#define SILI_F_SSNTF			0x0040
#define SILI_F_SPM			0x0080

	u_int			sc_ncmds;	/* max 31, NOT 32 */

	struct sili_port	*sc_ports[SILI_MAX_PORTS];
};

struct sili_device {
	pci_vendor_id_t		ad_vendor;
	pci_product_id_t	ad_product;
	int			ad_nports;
	int			(*ad_attach)(device_t dev);
	int			(*ad_detach)(device_t dev);
	char			*name;
};

/* Wait for all bits in _b to be cleared */
#define sili_pwait_clr(_ap, _r, _b) \
	sili_pwait_eq((_ap), SILI_PWAIT_TIMEOUT, (_r), (_b), 0)
#define sili_pwait_clr_to(_ap, _to,  _r, _b) \
	sili_pwait_eq((_ap), _to, (_r), (_b), 0)

/* Wait for all bits in _b to be set */
#define sili_pwait_set(_ap, _r, _b) \
	sili_pwait_eq((_ap), SILI_PWAIT_TIMEOUT, (_r), (_b), (_b))
#define sili_pwait_set_to(_ap, _to, _r, _b) \
	sili_pwait_eq((_ap), _to, (_r), (_b), (_b))

/*
 * Misc defines
 */
#define SILI_PWAIT_TIMEOUT      1000

/*
 * Prototypes
 */
const struct sili_device *sili_lookup_device(device_t dev);
int	sili_init(struct sili_softc *);
int	sili_port_init(struct sili_port *ap);
int	sili_port_alloc(struct sili_softc *, u_int);
void	sili_port_state_machine(struct sili_port *ap, int initial);
void	sili_port_free(struct sili_softc *, u_int);
int	sili_port_reset(struct sili_port *, struct ata_port *at, int);
void	sili_exclusive_access(struct sili_port *ap);

u_int32_t sili_read(struct sili_softc *, bus_size_t);
void	sili_write(struct sili_softc *, bus_size_t, u_int32_t);
int	sili_wait_ne(struct sili_softc *, bus_size_t, u_int32_t, u_int32_t);
u_int32_t sili_pread(struct sili_port *, bus_size_t);
void	sili_pwrite(struct sili_port *, bus_size_t, u_int32_t);
int	sili_pwait_eq(struct sili_port *, int, bus_size_t,
			u_int32_t, u_int32_t);
void	sili_intr(void *);
void	sili_port_intr(struct sili_port *ap, int blockable);

int	sili_cam_attach(struct sili_port *ap);
void	sili_cam_changed(struct sili_port *ap, struct ata_port *at, int found);
void	sili_cam_detach(struct sili_port *ap);
int	sili_cam_probe(struct sili_port *ap, struct ata_port *at);

struct ata_xfer *sili_ata_get_xfer(struct sili_port *ap, struct ata_port *at);
void	sili_ata_put_xfer(struct ata_xfer *xa);
int	sili_ata_cmd(struct ata_xfer *xa);

int	sili_pm_port_probe(struct sili_port *ap, int);
int	sili_pm_port_init(struct sili_port *ap, struct ata_port *at);
int	sili_pm_identify(struct sili_port *ap);
int	sili_pm_set_feature(struct sili_port *ap, int feature, int enable);
int	sili_pm_hardreset(struct sili_port *ap, int target, int hard);
int	sili_pm_softreset(struct sili_port *ap, int target);
int	sili_pm_phy_status(struct sili_port *ap, int target, u_int32_t *datap);
int	sili_pm_read(struct sili_port *ap, int target,
			int which, u_int32_t *res);
int	sili_pm_write(struct sili_port *ap, int target,
			int which, u_int32_t data);
void	sili_pm_check_good(struct sili_port *ap, int target);
void	sili_ata_cmd_timeout(struct sili_ccb *ccb);
void	sili_quick_timeout(struct sili_ccb *ccb);
struct sili_ccb *sili_get_ccb(struct sili_port *ap);
void	sili_put_ccb(struct sili_ccb *ccb);
struct sili_ccb *sili_get_err_ccb(struct sili_port *);
void	sili_put_err_ccb(struct sili_ccb *);
int	sili_poll(struct sili_ccb *ccb, int timeout,
			void (*timeout_fn)(struct sili_ccb *));

int     sili_port_signature(struct sili_port *ap, struct ata_port *at,
			u_int32_t sig);
void	sili_port_thread_core(struct sili_port *ap, int mask);

void	sili_os_sleep(int ms);
void	sili_os_hardsleep(int us);
int	sili_os_softsleep(void);
void	sili_os_start_port(struct sili_port *ap);
void	sili_os_stop_port(struct sili_port *ap);
void	sili_os_signal_port_thread(struct sili_port *ap, int mask);
void	sili_os_lock_port(struct sili_port *ap);
int	sili_os_lock_port_nb(struct sili_port *ap);
void	sili_os_unlock_port(struct sili_port *ap);

extern u_int32_t SiliForceGen1;
extern u_int32_t SiliNoFeatures;